summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS10
-rw-r--r--ChangeLog89
-rw-r--r--cmake/Platform/Emscripten.cmake8
-rwxr-xr-xemcc135
-rw-r--r--emscripten-version.txt2
-rwxr-xr-xemscripten.py1088
-rw-r--r--src/embind/embind.js436
-rw-r--r--src/embind/emval.js21
-rw-r--r--src/emscripten-source-map.min.js3
-rw-r--r--src/jsifier.js10
-rw-r--r--src/library.js323
-rw-r--r--src/library_browser.js146
-rw-r--r--src/library_fs.js77
-rw-r--r--src/library_gl.js47
-rw-r--r--src/library_glfw.js2
-rw-r--r--src/library_html5.js6
-rw-r--r--src/library_sdl.js394
-rw-r--r--src/modules.js1
-rw-r--r--src/parseTools.js19
-rw-r--r--src/preamble.js236
-rw-r--r--src/relooper/Relooper.cpp122
-rw-r--r--src/relooper/Relooper.h14
-rw-r--r--src/relooper/fuzzer.py6
-rw-r--r--src/relooper/test.cpp31
-rw-r--r--src/relooper/test.txt153
-rw-r--r--src/runtime.js13
-rw-r--r--src/settings.js18
-rw-r--r--src/shell.html18
-rw-r--r--src/shell.js6
-rw-r--r--src/shell_minimal.html18
-rw-r--r--src/simd.js1643
-rw-r--r--src/struct_info.json18
-rw-r--r--system/include/emscripten/bind.h463
-rw-r--r--system/include/emscripten/emscripten.h58
-rw-r--r--system/include/emscripten/html5.h6
-rw-r--r--system/include/emscripten/val.h20
-rw-r--r--system/lib/embind/bind.cpp1
-rw-r--r--system/lib/libc.symbols22
-rw-r--r--system/lib/libc/musl/src/compat/readme.txt2
-rw-r--r--system/lib/libc/musl/src/compat/strlwr.c12
-rw-r--r--system/lib/libc/musl/src/compat/strtol_l.c22
-rw-r--r--system/lib/libc/musl/src/compat/strupr.c12
-rw-r--r--system/lib/libc/musl/src/ctype/isalnum.c6
-rw-r--r--system/lib/libc/musl/src/ctype/isalpha.c7
-rw-r--r--system/lib/libc/musl/src/ctype/isascii.c6
-rw-r--r--system/lib/libc/musl/src/ctype/isblank.c6
-rw-r--r--system/lib/libc/musl/src/ctype/iscntrl.c6
-rw-r--r--system/lib/libc/musl/src/ctype/isdigit.c7
-rw-r--r--system/lib/libc/musl/src/ctype/isgraph.c4
-rw-r--r--system/lib/libc/musl/src/ctype/islower.c7
-rw-r--r--system/lib/libc/musl/src/ctype/isprint.c4
-rw-r--r--system/lib/libc/musl/src/ctype/ispunct.c6
-rw-r--r--system/lib/libc/musl/src/ctype/isspace.c6
-rw-r--r--system/lib/libc/musl/src/ctype/isupper.c7
-rw-r--r--system/lib/libc/musl/src/ctype/isxdigit.c6
-rw-r--r--system/lib/libc/musl/src/ctype/toascii.c7
-rw-r--r--system/lib/libc/musl/src/ctype/tolower.c7
-rw-r--r--system/lib/libc/musl/src/ctype/toupper.c7
-rw-r--r--system/lib/libc/musl/src/internal/stdio_impl.h4
-rw-r--r--system/lib/libc/musl/src/locale/isalnum_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/isalpha_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/isblank_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/iscntrl_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/isdigit_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/isgraph_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/islower_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/isprint_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/ispunct_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/isspace_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/isupper_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/isxdigit_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/tolower_l.c6
-rw-r--r--system/lib/libc/musl/src/locale/toupper_l.c6
-rw-r--r--system/lib/libc/musl/src/math/frexp.c23
-rw-r--r--system/lib/libc/musl/src/math/frexpf.c23
-rw-r--r--system/lib/libc/musl/src/math/frexpl.c37
-rw-r--r--system/lib/libc/musl/src/stdio/__string_read.c16
-rw-r--r--system/lib/libc/musl/src/stdio/asprintf.c13
-rw-r--r--system/lib/libc/musl/src/stdio/fwrite.c41
-rw-r--r--system/lib/libc/musl/src/stdio/snprintf.c13
-rw-r--r--system/lib/libc/musl/src/stdio/sprintf.c12
-rw-r--r--system/lib/libc/musl/src/stdio/sscanf.c15
-rw-r--r--system/lib/libc/musl/src/stdio/vasprintf.c28
-rw-r--r--system/lib/libc/musl/src/stdio/vfprintf.c685
-rw-r--r--system/lib/libc/musl/src/stdio/vfscanf.c332
-rw-r--r--system/lib/libc/musl/src/stdio/vsnprintf.c45
-rw-r--r--system/lib/libc/musl/src/stdio/vsprintf.c7
-rw-r--r--system/lib/libc/musl/src/stdio/vsscanf.c20
-rw-r--r--system/lib/libc/musl/src/stdlib/strtol.c64
-rw-r--r--system/lib/libcextra.symbols40
-rw-r--r--tests/cases/floatundefinvoke_fastcomp.ll30
-rw-r--r--tests/cases/floatundefinvoke_fastcomp.txt3
-rw-r--r--tests/cases/i1tof_ta2.ll71
-rw-r--r--tests/cases/i1tof_ta2.txt3
-rw-r--r--tests/cases/redundantswitch_fastcomp.ll28
-rw-r--r--tests/cases/redundantswitch_fastcomp.txt2
-rw-r--r--tests/cmake/target_library/CMakeLists.txt43
-rw-r--r--tests/cmake/target_library/srcfile.cmake6
-rw-r--r--tests/core/test_double_varargs.c34
-rw-r--r--tests/core/test_double_varargs.out2
-rw-r--r--tests/core/test_exceptions_white_list_empty.out0
-rw-r--r--tests/core/test_floatvars.in9
-rw-r--r--tests/core/test_floatvars.out1
-rw-r--r--tests/core/test_polymorph.in8
-rw-r--r--tests/core/test_polymorph.out4
-rw-r--r--tests/core/test_set_align.c50
-rw-r--r--tests/core/test_set_align.out8
-rw-r--r--tests/core/test_simd4.in39
-rw-r--r--tests/core/test_simd4.out1
-rw-r--r--tests/core/test_sscanf.in3
-rw-r--r--tests/core/test_sscanf_hex.in24
-rw-r--r--tests/core/test_sscanf_hex.out3
-rw-r--r--tests/core/test_strptime_tm.in31
-rw-r--r--tests/core/test_strptime_tm.out19
-rw-r--r--tests/embind/embind.test.js440
-rw-r--r--tests/embind/embind_test.cpp290
-rw-r--r--tests/embind/imvu_test_adapter.js6
-rw-r--r--tests/emscripten_fs_api_browser.cpp5
-rw-r--r--tests/fs/test_trackingdelegate.c39
-rw-r--r--tests/fs/test_trackingdelegate.out9
-rw-r--r--tests/fs/test_writeFile.cc43
-rw-r--r--tests/fs/test_writeFile.out3
-rw-r--r--tests/fuzz/19.c1408
-rw-r--r--tests/fuzz/19.c.txt1
-rw-r--r--tests/fuzz/20.cpp977
-rw-r--r--tests/fuzz/20.cpp.txt1
-rw-r--r--tests/fuzz/21.c2332
-rw-r--r--tests/fuzz/21.c.txt1
-rw-r--r--tests/gl_teximage.c120
-rw-r--r--tests/hello_world_file.cpp4
-rw-r--r--tests/life.c2
-rw-r--r--tests/return64bit/test.c6
-rw-r--r--tests/return64bit/testbind.js18
-rw-r--r--tests/return64bit/testbindend.js2
-rw-r--r--tests/return64bit/testbindstart.js3
-rw-r--r--tests/sdl_audio_mix.c2
-rw-r--r--tests/sdl_audio_quickload.c44
-rw-r--r--tests/sdl_image.c10
-rw-r--r--tests/sdl_touch.c9
-rw-r--r--tests/test_benchmark.py37
-rw-r--r--tests/test_browser.py9
-rw-r--r--tests/test_core.py274
-rw-r--r--tests/test_interactive.py6
-rw-r--r--tests/test_other.py258
-rw-r--r--tests/test_sanity.py2
-rw-r--r--tests/webidl/output.txt58
-rw-r--r--tests/webidl/post.js120
-rw-r--r--tests/webidl/test.cpp8
-rw-r--r--tests/webidl/test.h75
-rw-r--r--tests/webidl/test.idl67
-rw-r--r--third_party/WebIDL.py5033
-rw-r--r--third_party/__init__.py2
-rwxr-xr-xtools/bindings_generator.py55
-rw-r--r--tools/bisect_pair_lines.py63
-rw-r--r--tools/eliminator/asm-eliminator-test-output.js129
-rw-r--r--tools/eliminator/asm-eliminator-test.js94
-rwxr-xr-xtools/ffdb.py453
-rw-r--r--tools/js-optimizer.js396
-rw-r--r--tools/js_optimizer.py28
-rw-r--r--tools/jsrun.py9
-rw-r--r--tools/shared.py189
-rw-r--r--tools/system_libs.py65
-rw-r--r--tools/test-js-optimizer-asm-last-output.js27
-rw-r--r--tools/test-js-optimizer-asm-last.js33
-rw-r--r--tools/test-js-optimizer-asm-pre-f32.js8
-rw-r--r--tools/test-js-optimizer-asm-pre-output-f32.js8
-rw-r--r--tools/test-js-optimizer-asm-pre-output.js78
-rw-r--r--tools/test-js-optimizer-asm-pre.js79
-rw-r--r--tools/test-js-optimizer-asm-regs-harder-output.js5
-rw-r--r--tools/test-js-optimizer-asm-regs-harder.js8
-rw-r--r--tools/webidl_binder.py433
171 files changed, 19076 insertions, 2562 deletions
diff --git a/AUTHORS b/AUTHORS
index ad372e92..d356a05b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -134,4 +134,14 @@ a license to everyone to use it as detailed in LICENSE.)
* Daniele Di Proietto <daniele.di.proietto@gmail.com>
* Dan Dascalescu <dNOSPAMdascalescu@gmail.com>
* Thomas Borsos <thomasborsos@gmail.com>
+* Ori Avtalion <ori@avtalion.name>
* Guillaume Blanc <guillaumeblanc.sc@gmail.com>
+* Usagi Ito <usagi@WonderRabbitProject.net>
+* Camilo Polymeris <cpolymeris@gmail.com>
+* Markus Henschel <markus.henschel@yager.de>
+* Ophir Lojkine <ophir.lojkine@eleves.ec-nantes.fr>
+* Ryan Sturgell <ryan.sturgell@gmail.com> (copyright owned by Google, Inc.)
+* Jason Green <jason@transgaming.com> (copyright owned by TransGaming, Inc.)
+* Ningxin Hu <ningxin.hu@intel.com> (copyright owned by Intel)
+* Nicolas Guillemot <nlguillemot@gmail.com>
+
diff --git a/ChangeLog b/ChangeLog
index 328e3cac..18640add 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -10,7 +10,83 @@ Not all changes are documented here. In particular, new features, user-oriented
Current trunk code
------------------
- To see a list of commits in the active development branch 'incoming', which have not yet been packaged in a release, see
- https://github.com/kripken/emscripten/compare/1.13.1...incoming
+ - Emscripten: https://github.com/kripken/emscripten/compare/1.16.0...incoming
+ - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.16.0...incoming
+ - Emscripten-Clang: https://github.com/kripken/emscripten-fastcomp-clang/compare/1.16.0...incoming
+
+v1.16.0: 4/16/2014
+------------------
+ - Removed browser warnings message in VFS library about replacing __proto__ performance issue.
+ - Full list of changes:
+ - Emscripten: https://github.com/kripken/emscripten/compare/1.15.1...1.16.0
+ - Emscripten-LLVM: no changes.
+ - Emscripten-Clang: https://github.com/kripken/emscripten-fastcomp-clang/compare/1.15.1...1.16.0
+
+v1.15.1: 4/15/2014
+------------------
+ - Added support for SDL2 touch api.
+ - Added new user-controllable emdind-related define #define EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES, which allows optimizing embind for minimal size when std::type_info is not needed.
+ - Fixed issues with CMake support where CMAKE_AR and CMAKE_RANLIB were not accessible from CMakeLists.txt files.
+ - Full list of changes:
+ - Emscripten: https://github.com/kripken/emscripten/compare/1.15.0...1.15.1
+ - Emscripten-LLVM: no changes.
+ - Emscripten-Clang: no changes.
+
+v1.15.0: 4/11/2014
+------------------
+ - Fix outlining feature for functions that return a double (#2278)
+ - Added support for C++11 atomic constructs (#2273)
+ - Adjusted stdout and stderr stream behavior in the default shell.html to always print out to both web page text log box, and the browser console.
+ - Fixed an issue with loop variable optimization.
+ - Full list of changes:
+ - Emscripten: https://github.com/kripken/emscripten/compare/1.14.1...1.15.0
+ - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.14.1...1.15.0
+ - Emscripten-Clang: https://github.com/kripken/emscripten-fastcomp-clang/compare/1.14.1...1.15.0
+
+v1.14.1: 4/8/2014
+------------------
+ - Added new command line utility 'emcmake', which can be used to call emconfigure for cmake.
+ - Added a new emcc command line parameter '--valid-abspath', which allows selectively suppressing warning messages that occur when using absolute path names in include and link directories.
+ - Added a new emcc linker command line parameter '--emit-symbol-map', which will save a map file between minified global names and the original function names.
+ - Fixed an issue with --default-object-ext not always working properly.
+ - Added optimizations to eliminate redundant loop variables and redundant self-assignments.
+ - Migrated several libc functions to use compiled code from musl instead of handwritten JS implementations.
+ - Improved embind support.
+ - Renamed the EM_ASM_() macro to the form EM_ASM_ARGS().
+ - Fixed mouse button ordering issue in glfw.
+ - Fixed an issue when creating a path name that ends in a slash (#2258, #2263)
+ - Full list of changes:
+ - Emscripten: https://github.com/kripken/emscripten/compare/1.14.0...1.14.1
+ - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.14.0...1.14.1
+ - Emscripten-Clang: no changes.
+
+v1.14.0: 3/25/2014
+------------------
+ - Added new emcc linker command line option '-profiling', which defaults JS code generation options suited for benchmarking and profiling purposes.
+ - Implemented the EGL function eglWaitGL().
+ - Fixed an issue with the HTML5 API that caused the HTML5 event listener unregistration to fail.
+ - Fixed issues with numpad keys in SDL support library.
+ - Added a new JS optimizer pass 'simplifyIfs', which is run when -s SIMPLIFY_IFS=1 link flag is set and -g is not specified. This pass merges multiple nested if()s together into single comparisons, where possible.
+ - Removed false positive messages on missing internal "emscripten_xxx" symbols at link stage.
+ - Updated to latest relooper version.
+ - Full list of changes:
+ - Emscripten: https://github.com/kripken/emscripten/compare/1.13.2...1.14.0
+ - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.13.2...1.14.0
+ - Emscripten-Clang: no changes.
+
+v1.13.2: 3/15/2014
+------------------
+ - Fixed issues with SDL audio on Safari.
+ - Fixed issues with HTML5 API mouse scroll events on Safari.
+ - Fixed issues with HTML5 fullscreen requests in IE11.
+ - Enabled support for emscripten_get_callstack on IE10+.
+ - Fixed issues with Closure symbol minification.
+ - Further improved em_asm()-related error messages.
+ - Updated to latest relooper version.
+ - Full list of changes:
+ - Emscripten: https://github.com/kripken/emscripten/compare/1.13.1...1.13.2
+ - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.13.1...1.13.2
+ - Emscripten-Clang: no changes.
v1.13.1: 3/10/2014
------------------
@@ -21,7 +97,16 @@ v1.13.1: 3/10/2014
- Fix an issue where extraneous system libraries would get included in the generated output (#2191).
- Added a new function emscripten_async_wget2_data() that allows reading from an XMLHTTPRequest directly into memory while supporting advanced features.
- Fixed esc key code in GLFW.
- - Full list of changes: https://github.com/kripken/emscripten/compare/1.13.0...1.13.1
+ - Added new emscripten_debugger() intrinsic function, which calls into JS "debugger;" statement to break into a JS debugger.
+ - Fixed varargs function call alignment of doubles to 8 bytes.
+ - Switched to using default function local stack alignment to 16 bytes to be SIMD-friendly.
+ - Improved error messages when user code has a syntax error in em_asm() statements.
+ - Switched to using a new custom LLVM datalayout format for Emscripten. See https://github.com/kripken/emscripten-fastcomp/commit/65405351ba0b32a8658c65940e0b65ceb2601ad4
+ - Optimized function local stack space to use fewer temporary JS variables.
+ - Full list of changes:
+ - Emscripten: https://github.com/kripken/emscripten/compare/1.13.0...1.13.1
+ - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.13.0...1.13.1
+ - Emscripten-Clang: https://github.com/kripken/emscripten-fastcomp-clang/compare/1.13.0...1.13.1
v1.13.0: 3/3/2014
------------------
diff --git a/cmake/Platform/Emscripten.cmake b/cmake/Platform/Emscripten.cmake
index f9d8c773..362a552d 100644
--- a/cmake/Platform/Emscripten.cmake
+++ b/cmake/Platform/Emscripten.cmake
@@ -98,6 +98,8 @@ set(CMAKE_SYSTEM_INCLUDE_PATH "${EMSCRIPTEN_ROOT_PATH}/system/include")
#SET(CMAKE_FIND_LIBRARY_PREFIXES "")
#SET(CMAKE_FIND_LIBRARY_SUFFIXES ".bc")
+SET(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES 1)
+SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_LIBRARIES 1)
SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1)
SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1)
SET(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES 1)
@@ -107,10 +109,8 @@ set(CMAKE_C_RESPONSE_FILE_LINK_FLAG "@")
set(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "@")
# Specify the program to use when building static libraries. Force Emscripten-related command line options to clang.
-set(CMAKE_CXX_ARCHIVE_CREATE "${CMAKE_AR} rc <TARGET> ${CMAKE_START_TEMP_FILE} <LINK_FLAGS> <OBJECTS>${CMAKE_END_TEMP_FILE}")
-set(CMAKE_C_ARCHIVE_CREATE "${CMAKE_AR} rc <TARGET> ${CMAKE_START_TEMP_FILE} <LINK_FLAGS> <OBJECTS>${CMAKE_END_TEMP_FILE}")
-set(CMAKE_CXX_ARCHIVE_APPEND "${CMAKE_AR} r <TARGET> ${CMAKE_START_TEMP_FILE} <LINK_FLAGS> <OBJECTS>${CMAKE_END_TEMP_FILE}")
-set(CMAKE_C_ARCHIVE_APPEND "${CMAKE_AR} r <TARGET> ${CMAKE_START_TEMP_FILE} <LINK_FLAGS> <OBJECTS>${CMAKE_END_TEMP_FILE}")
+set(CMAKE_C_CREATE_STATIC_LIBRARY "<CMAKE_AR> rc <TARGET> <LINK_FLAGS> <OBJECTS>")
+set(CMAKE_CXX_CREATE_STATIC_LIBRARY "<CMAKE_AR> rc <TARGET> <LINK_FLAGS> <OBJECTS>")
# Set a global EMSCRIPTEN variable that can be used in client CMakeLists.txt to detect when building using Emscripten.
set(EMSCRIPTEN 1 CACHE BOOL "If true, we are targeting Emscripten output.")
diff --git a/emcc b/emcc
index c8e1814b..5e57bc37 100755
--- a/emcc
+++ b/emcc
@@ -64,6 +64,7 @@ DYNAMICLIB_ENDINGS = ('.dylib', '.so', '.dll')
STATICLIB_ENDINGS = ('.a',)
ASSEMBLY_ENDINGS = ('.ll',)
HEADER_ENDINGS = ('.h', '.hxx', '.hpp', '.hh', '.H', '.HXX', '.HPP', '.HH')
+SUPPORTED_LINKER_FLAGS = ('--start-group', '-(', '--end-group', '-)')
LIB_PREFIXES = ('', 'lib')
@@ -1098,12 +1099,24 @@ try:
# Find input files
+ # These three arrays are used to store arguments of different types for
+ # type-specific processing. In order to shuffle the arguments back together
+ # after processing, all of these arrays hold tuples (original_index, value).
+ # Note that the index part of the tuple can have a fractional part for input
+ # arguments that expand into multiple processed arguments, as in -Wl,-f1,-f2.
input_files = []
+ libs = []
+ link_flags = []
+
+ # All of the above arg lists entries contain indexes into the full argument
+ # list. In order to add extra implicit args (embind.cc, etc) below, we keep a
+ # counter for the next index that should be used.
+ next_arg_index = len(newargs)
+
has_source_inputs = False
has_header_inputs = False
lib_dirs = [shared.path_from_root('system', 'local', 'lib'),
shared.path_from_root('system', 'lib')]
- libs = []
for i in range(len(newargs)): # find input files XXX this a simple heuristic. we should really analyze based on a full understanding of gcc params,
# right now we just assume that what is left contains no more |-x OPT| things
arg = newargs[i]
@@ -1124,13 +1137,13 @@ try:
if arg_ending.endswith(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + ASSEMBLY_ENDINGS + HEADER_ENDINGS) or shared.Building.is_ar(arg): # we already removed -o <target>, so all these should be inputs
newargs[i] = ''
if arg_ending.endswith(SOURCE_ENDINGS):
- input_files.append(arg)
+ input_files.append((i, arg))
has_source_inputs = True
elif arg_ending.endswith(HEADER_ENDINGS):
- input_files.append(arg)
+ input_files.append((i, arg))
has_header_inputs = True
elif arg_ending.endswith(ASSEMBLY_ENDINGS) or shared.Building.is_bitcode(arg): # this should be bitcode, make sure it is valid
- input_files.append(arg)
+ input_files.append((i, arg))
elif arg_ending.endswith(STATICLIB_ENDINGS + DYNAMICLIB_ENDINGS):
# if it's not, and it's a library, just add it to libs to find later
l = unsuffixed_basename(arg)
@@ -1139,7 +1152,7 @@ try:
if l.startswith(prefix):
l = l[len(prefix):]
break
- libs.append(l)
+ libs.append((i, l))
newargs[i] = ''
else:
logging.warning(arg + ' is not valid LLVM bitcode')
@@ -1157,7 +1170,20 @@ try:
lib_dirs.append(arg[2:])
newargs[i] = ''
elif arg.startswith('-l'):
- libs.append(arg[2:])
+ libs.append((i, arg[2:]))
+ newargs[i] = ''
+ elif arg.startswith('-Wl,'):
+ # Multiple comma separated link flags can be specified. Create fake
+ # fractional indices for these: -Wl,a,b,c,d at index 4 becomes:
+ # (4, a), (4.25, b), (4.5, c), (4.75, d)
+ link_flags_to_add = arg.split(',')[1:]
+ for flag_index, flag in enumerate(link_flags_to_add):
+ # Only keep flags that shared.Building.link knows how to deal with.
+ # We currently can't handle flags with options (like
+ # -Wl,-rpath,/bin:/lib, where /bin:/lib is an option for the -rpath
+ # flag).
+ if flag in SUPPORTED_LINKER_FLAGS:
+ link_flags.append((i + float(flag_index) / len(link_flags_to_add), flag))
newargs[i] = ''
original_input_files = input_files[:]
@@ -1173,7 +1199,7 @@ try:
final_ending = ('.' + final_suffix) if len(final_suffix) > 0 else ''
# Find library files
- for lib in libs:
+ for i, lib in libs:
logging.debug('looking for library "%s"', lib)
found = False
for prefix in LIB_PREFIXES:
@@ -1183,7 +1209,7 @@ try:
path = os.path.join(lib_dir, name)
if os.path.exists(path):
logging.debug('found library "%s" at %s', lib, path)
- input_files.append(path)
+ input_files.append((i, path))
found = True
break
if found: break
@@ -1199,7 +1225,7 @@ try:
return False
else:
return True
- input_files = [input_file for input_file in input_files if check(input_file)]
+ input_files = [(i, input_file) for (i, input_file) in input_files if check(input_file)]
if len(input_files) == 0:
logging.error('no input files\nnote that input files without a known suffix are ignored, make sure your input files end with one of: ' + str(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + STATICLIB_ENDINGS + ASSEMBLY_ENDINGS + HEADER_ENDINGS))
@@ -1211,7 +1237,8 @@ try:
# If we are using embind and generating JS, now is the time to link in bind.cpp
if bind and final_suffix in JS_CONTAINING_SUFFIXES:
- input_files.append(shared.path_from_root('system', 'lib', 'embind', 'bind.cpp'))
+ input_files.append((next_arg_index, shared.path_from_root('system', 'lib', 'embind', 'bind.cpp')))
+ next_arg_index += 1
# Apply optimization level settings
shared.Settings.apply_opt_level(opt_level, noisy=True)
@@ -1223,11 +1250,8 @@ try:
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
- if bind and shared.Settings.ASM_JS:
- logging.warning('disabling asm.js since embind is not ready for it yet')
- shared.Settings.ASM_JS = 0
+ if key == 'EXPORTED_FUNCTIONS':
+ shared.Settings.ORIGINAL_EXPORTED_FUNCTIONS = shared.Settings.EXPORTED_FUNCTIONS[:] # used for warnings in emscripten.py
fastcomp = os.environ.get('EMCC_FAST_COMPILER') != '0'
@@ -1245,11 +1269,10 @@ try:
assert shared.Settings.TARGET_ASMJS_UNKNOWN_EMSCRIPTEN == 1, 'fastcomp requires asmjs-unknown-emscripten'
assert shared.Settings.USE_TYPED_ARRAYS == 2, 'fastcomp assumes ta2'
assert not split_js_file, '--split-js is deprecated and not supported in fastcomp'
- assert not bind, 'embind not supported in fastcomp yet'
- assert shared.Settings.MAX_SETJMPS == 20, 'changing MAX_SETJMPS is not supported in fastcomp yet'
assert shared.Settings.INIT_HEAP == 0, 'HEAP_INIT is not supported in fastcomp (and should never be needed except for debugging)'
assert not shared.Settings.RUNTIME_TYPE_INFO, 'RUNTIME_TYPE_INFO is not supported in fastcomp'
assert not shared.Settings.CORRUPTION_CHECK, 'CORRUPTION_CHECK is not supported in asm.js mode, which is what fastcomp can emit (you can use non-asm.js mode in non-fastcomp)'
+ assert not shared.Settings.MAIN_MODULE and not shared.Settings.SIDE_MODULE, 'Linking modules is not supported in fastcomp'
except Exception, e:
logging.error('Compiler settings are incompatible with fastcomp. You can fall back to the older compiler core, although that is not recommended, see https://github.com/kripken/emscripten/wiki/LLVM-Backend')
raise e
@@ -1266,8 +1289,8 @@ try:
fastcomp_opts += ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt']
if shared.Settings.DISABLE_EXCEPTION_CATCHING != 1:
fastcomp_opts += ['-enable-emscripten-cxx-exceptions']
- if len(shared.Settings.EXCEPTION_CATCHING_WHITELIST) > 0:
- fastcomp_opts += ['-emscripten-cxx-exceptions-whitelist=' + ','.join(shared.Settings.EXCEPTION_CATCHING_WHITELIST)]
+ if shared.Settings.DISABLE_EXCEPTION_CATCHING == 2:
+ fastcomp_opts += ['-emscripten-cxx-exceptions-whitelist=' + ','.join(shared.Settings.EXCEPTION_CATCHING_WHITELIST or ['fake'])]
if shared.Settings.ASM_JS:
assert opt_level >= 1 or fastcomp, 'asm.js requires -O1 or above'
@@ -1297,6 +1320,8 @@ try:
logging.warning('disabling closure because debug info was requested')
closure = False
+ assert not (shared.Settings.NO_DYNAMIC_EXECUTION and closure), 'cannot have both NO_DYNAMIC_EXECUTION and closure compiler enabled at the same time'
+
if closure:
shared.Settings.CLOSURE_COMPILER = 1
assert os.path.exists(shared.CLOSURE_COMPILER), logging.error('fatal: Closure compiler (%s) does not exist', shared.CLOSURE_COMPILER)
@@ -1322,6 +1347,7 @@ try:
if shared.Settings.MAIN_MODULE:
assert not shared.Settings.SIDE_MODULE
shared.Settings.INCLUDE_FULL_LIBRARY = 1
+ shared.Settings.EXPORT_ALL = 1
elif shared.Settings.SIDE_MODULE:
assert not shared.Settings.MAIN_MODULE
@@ -1335,7 +1361,8 @@ try:
logging.warning('ALIASING_FUNCTION_POINTERS is on, function pointer comparisons may be invalid across types')
if shared.Settings.STB_IMAGE and final_suffix in JS_CONTAINING_SUFFIXES:
- input_files.append(shared.path_from_root('third_party', 'stb_image.c'))
+ input_files.append((next_arg_index, shared.path_from_root('third_party', 'stb_image.c')))
+ next_arg_index += 1
shared.Settings.EXPORTED_FUNCTIONS += ['_stbi_load', '_stbi_load_from_memory', '_stbi_image_free']
if type(shared.Settings.EXPORTED_FUNCTIONS) in (list, tuple):
@@ -1369,12 +1396,15 @@ try:
# Precompiled headers support
if has_header_inputs:
- for header in input_files:
- assert header.endswith(HEADER_ENDINGS), 'if you have one header input, we assume you want to precompile headers, and cannot have source files or other inputs as well: ' + str(input_files) + ' : ' + header
- args = newargs + shared.EMSDK_CXX_OPTS + input_files
- logging.debug("running (for precompiled headers: " + call + ' ' + ' '.join(args))
+ headers = [header for _, header in input_files]
+ for header in headers:
+ assert header.endswith(HEADER_ENDINGS), 'if you have one header input, we assume you want to precompile headers, and cannot have source files or other inputs as well: ' + str(headers) + ' : ' + header
+ args = newargs + shared.EMSDK_CXX_OPTS + headers
+ if specified_target:
+ args += ['-o', specified_target]
+ logging.debug("running (for precompiled headers): " + call + ' ' + ' '.join(args))
execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that)
- sys.exit(1)
+ sys.exit(0)
def get_bitcode_file(input_file):
if final_suffix not in JS_CONTAINING_SUFFIXES:
@@ -1390,12 +1420,12 @@ try:
return in_temp(unsuffixed(uniquename(input_file)) + default_object_extension)
# First, generate LLVM bitcode. For each input file, we get base.o with bitcode
- for input_file in input_files:
+ for i, input_file in input_files:
file_ending = filename_type_ending(input_file)
if file_ending.endswith(SOURCE_ENDINGS):
logging.debug('compiling source file: ' + input_file)
output_file = get_bitcode_file(input_file)
- temp_files.append(output_file)
+ temp_files.append((i, output_file))
args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file]
if file_ending.endswith(CXX_ENDINGS):
args += shared.EMSDK_CXX_OPTS
@@ -1409,18 +1439,18 @@ try:
logging.debug('copying bitcode file: ' + input_file)
temp_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
shutil.copyfile(input_file, temp_file)
- temp_files.append(temp_file)
+ temp_files.append((i, temp_file))
elif file_ending.endswith(DYNAMICLIB_ENDINGS) or shared.Building.is_ar(input_file):
logging.debug('copying library file: ' + input_file)
temp_file = in_temp(uniquename(input_file))
shutil.copyfile(input_file, temp_file)
- temp_files.append(temp_file)
+ temp_files.append((i, temp_file))
elif file_ending.endswith(ASSEMBLY_ENDINGS):
if not LEAVE_INPUTS_RAW:
logging.debug('assembling assembly file: ' + input_file)
temp_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
shared.Building.llvm_as(input_file, temp_file)
- temp_files.append(temp_file)
+ temp_files.append((i, temp_file))
else:
logging.error(input_file + ': Unknown file suffix when compiling to LLVM bitcode!')
sys.exit(1)
@@ -1432,10 +1462,10 @@ try:
# Optimize source files
if llvm_opts > 0:
- for i, input_file in enumerate(input_files):
+ for pos, (_, input_file) in enumerate(input_files):
file_ending = filename_type_ending(input_file)
if file_ending.endswith(SOURCE_ENDINGS):
- temp_file = temp_files[i]
+ (_, temp_file) = temp_files[pos]
logging.debug('optimizing %s', input_file)
#if DEBUG: shutil.copyfile(temp_file, os.path.join(TEMP_DIR, 'to_opt.bc') # useful when LLVM opt aborts
shared.Building.llvm_opt(temp_file, llvm_opts)
@@ -1443,26 +1473,30 @@ try:
# If we were just asked to generate bitcode, stop there
if final_suffix not in JS_CONTAINING_SUFFIXES:
if not specified_target:
- for input_file in input_files:
+ for _, input_file in input_files:
safe_move(get_bitcode_file(input_file), unsuffixed_basename(input_file) + final_ending)
else:
if len(input_files) == 1:
- safe_move(temp_files[0], specified_target if specified_target else unsuffixed_basename(input_file) + final_ending)
- temp_output_base = unsuffixed(temp_files[0])
+ _, input_file = input_files[0]
+ _, temp_file = temp_files[0]
+ safe_move(temp_file, specified_target if specified_target else unsuffixed_basename(input_file) + final_ending)
+ temp_output_base = unsuffixed(temp_file)
if os.path.exists(temp_output_base + '.d'):
# There was a .d file generated, from -MD or -MMD and friends, save a copy of it to where the output resides,
# adjusting the target name away from the temporary file name to the specified target.
# It will be deleted with the rest of the temporary directory.
deps = open(temp_output_base + '.d').read()
deps = deps.replace(temp_output_base + default_object_extension, specified_target)
- with open(os.path.join(os.path.dirname(specified_target), os.path.basename(unsuffixed(input_files[0]) + '.d')), "w") as out_dep:
+ with open(os.path.join(os.path.dirname(specified_target), os.path.basename(unsuffixed(input_file) + '.d')), "w") as out_dep:
out_dep.write(deps)
else:
assert len(original_input_files) == 1 or not has_dash_c, 'fatal error: cannot specify -o with -c with multiple files' + str(sys.argv) + ':' + str(original_input_files)
# We have a specified target (-o <target>), which is not JavaScript or HTML, and
# we have multiple files: Link them
logging.debug('link: ' + str(temp_files) + specified_target)
- shared.Building.link(temp_files, specified_target)
+ # Sort arg tuples and pass the extracted values to link.
+ link_args = [f for (i, f) in sorted(temp_files)]
+ shared.Building.link(link_args, specified_target)
logging.debug('stopping at bitcode')
exit(0)
@@ -1475,7 +1509,7 @@ try:
if not LEAVE_INPUTS_RAW and \
not shared.Settings.BUILD_AS_SHARED_LIB and \
not shared.Settings.SIDE_MODULE: # shared libraries/side modules link no C libraries, need them in parent
- extra_files_to_link = system_libs.calculate(temp_files, in_temp, stdout, stderr)
+ extra_files_to_link = system_libs.calculate([f for _, f in sorted(temp_files)], in_temp, stdout, stderr)
else:
extra_files_to_link = []
@@ -1483,18 +1517,20 @@ try:
# First, combine the bitcode files if there are several. We must also link if we have a singleton .a
if len(input_files) + len(extra_files_to_link) > 1 or \
- (not LEAVE_INPUTS_RAW and not (suffix(temp_files[0]) in BITCODE_ENDINGS or suffix(temp_files[0]) in DYNAMICLIB_ENDINGS) and shared.Building.is_ar(temp_files[0])):
- linker_inputs = temp_files + extra_files_to_link
+ (not LEAVE_INPUTS_RAW and not (suffix(temp_files[0][1]) in BITCODE_ENDINGS or suffix(temp_files[0][1]) in DYNAMICLIB_ENDINGS) and shared.Building.is_ar(temp_files[0][1])):
+ linker_inputs = [val for _, val in sorted(temp_files + link_flags)] + extra_files_to_link
logging.debug('linking: ' + str(linker_inputs))
- shared.Building.link(linker_inputs, in_temp(target_basename + '.bc'), force_archive_contents=len([temp for temp in temp_files if not temp.endswith(STATICLIB_ENDINGS)]) == 0)
+ shared.Building.link(linker_inputs, in_temp(target_basename + '.bc'), force_archive_contents=len([temp for i, temp in temp_files if not temp.endswith(STATICLIB_ENDINGS)]) == 0)
final = in_temp(target_basename + '.bc')
else:
if not LEAVE_INPUTS_RAW:
- shutil.move(temp_files[0], in_temp(target_basename + '.bc'))
+ _, temp_file = temp_files[0]
+ shutil.move(temp_file, in_temp(target_basename + '.bc'))
final = in_temp(target_basename + '.bc')
else:
- final = in_temp(input_files[0])
- shutil.copyfile(input_files[0], final)
+ _, input_file = input_files[0]
+ final = in_temp(input_file)
+ shutil.copyfile(input_file, final)
log_time('link')
@@ -1731,7 +1767,7 @@ try:
# with commaified code breaks late aggressive variable elimination)
if shared.Settings.SIMPLIFY_IFS and (debug_level == 0 or profiling) and shared.Settings.OUTLINING_LIMIT == 0: js_optimizer_queue += ['simplifyIfs']
- if opt_level >= 3 and shared.Settings.PRECISE_F32: js_optimizer_queue += ['optimizeFrounds']
+ if shared.Settings.PRECISE_F32: js_optimizer_queue += ['optimizeFrounds']
if closure and not shared.Settings.ASM_JS:
flush_js_optimizer_queue()
@@ -1750,7 +1786,7 @@ try:
js_optimizer_extra_info['sizeToOutline'] = shared.Settings.OUTLINING_LIMIT
if opt_level >= 2 and (not closure or shared.Settings.ASM_JS) and shared.Settings.RELOOP and debug_level < 3:
- if shared.Settings.ASM_JS and opt_level >= 3 and shared.Settings.OUTLINING_LIMIT == 0:
+ if shared.Settings.ASM_JS and opt_level >= 3:
js_optimizer_queue += ['registerizeHarder']
else:
js_optimizer_queue += ['registerize']
@@ -1761,8 +1797,11 @@ try:
if emit_symbol_map: js_optimizer_queue += ['symbolMap='+target+'.symbols']
if debug_level == 0: js_optimizer_queue += ['minifyWhitespace']
- if closure and shared.Settings.ASM_JS:
- js_optimizer_queue += ['closure']
+ if shared.Settings.ASM_JS:
+ if closure:
+ js_optimizer_queue += ['closure']
+ elif debug_level <= 2 and not shared.Settings.MAIN_MODULE and not shared.Settings.SIDE_MODULE:
+ js_optimizer_queue += ['cleanup']
if not shared.Settings.SIDE_MODULE: js_optimizer_queue += ['last'] # side modules are not finalized until after relocation
diff --git a/emscripten-version.txt b/emscripten-version.txt
index db39b14c..de59d0c6 100644
--- a/emscripten-version.txt
+++ b/emscripten-version.txt
@@ -1,2 +1,2 @@
-1.15.1
+1.19.1
diff --git a/emscripten.py b/emscripten.py
index c8122cb9..98877a8e 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -455,7 +455,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
basic_funcs = ['abort', 'assert', 'asmPrintInt', 'asmPrintFloat'] + [m.replace('.', '_') for m in math_envs]
if settings['RESERVED_FUNCTION_POINTERS'] > 0: basic_funcs.append('jsCall')
- if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE']
+ if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE', 'SAFE_FT_MASK']
if settings['CHECK_HEAP_ALIGN']: basic_funcs += ['CHECK_ALIGN_2', 'CHECK_ALIGN_4', 'CHECK_ALIGN_8']
if settings['ASSERTIONS']:
basic_funcs += ['nullFunc']
@@ -477,7 +477,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
if '_rand' in exported_implemented_functions or '_srand' in exported_implemented_functions:
basic_vars += ['___rand_seed']
- asm_runtime_funcs = ['stackAlloc', 'stackSave', 'stackRestore', 'setThrew'] + ['setTempRet%d' % i for i in range(10)]
+ asm_runtime_funcs = ['stackAlloc', 'stackSave', 'stackRestore', 'setThrew'] + ['setTempRet%d' % i for i in range(10)] + ['getTempRet%d' % i for i in range(10)]
# function tables
function_tables = ['dynCall_' + table for table in last_forwarded_json['Functions']['tables']]
function_tables_impls = []
@@ -584,7 +584,7 @@ var asm = (function(global, env, buffer) {
var undef = 0;
var tempInt = 0, tempBigInt = 0, tempBigIntP = 0, tempBigIntS = 0, tempBigIntR = 0.0, tempBigIntI = 0, tempBigIntD = 0, tempValue = 0, tempDouble = 0.0;
''' + ''.join(['''
- var tempRet%d = 0;''' % i for i in range(10)]) + '\n' + asm_global_funcs] + [' var tempFloat = %s;\n' % ('Math_fround(0)' if settings.get('PRECISE_F32') else '0.0')] + ['''
+ var tempRet%d = 0;''' % i for i in range(10)]) + '\n' + asm_global_funcs] + [' var tempFloat = %s;\n' % ('Math_fround(0)' if settings.get('PRECISE_F32') else '0.0')] + ([' const f0 = Math_fround(0);\n'] if settings.get('PRECISE_F32') else []) + ['''
// EMSCRIPTEN_START_FUNCS
function stackAlloc(size) {
size = size|0;
@@ -611,27 +611,31 @@ function setThrew(threw, value) {
}
function copyTempFloat(ptr) {
ptr = ptr|0;
- HEAP8[tempDoublePtr] = HEAP8[ptr];
- HEAP8[tempDoublePtr+1|0] = HEAP8[ptr+1|0];
- HEAP8[tempDoublePtr+2|0] = HEAP8[ptr+2|0];
- HEAP8[tempDoublePtr+3|0] = HEAP8[ptr+3|0];
+ HEAP8[tempDoublePtr>>0] = HEAP8[ptr>>0];
+ HEAP8[tempDoublePtr+1>>0] = HEAP8[ptr+1>>0];
+ HEAP8[tempDoublePtr+2>>0] = HEAP8[ptr+2>>0];
+ HEAP8[tempDoublePtr+3>>0] = HEAP8[ptr+3>>0];
}
function copyTempDouble(ptr) {
ptr = ptr|0;
- HEAP8[tempDoublePtr] = HEAP8[ptr];
- HEAP8[tempDoublePtr+1|0] = HEAP8[ptr+1|0];
- HEAP8[tempDoublePtr+2|0] = HEAP8[ptr+2|0];
- HEAP8[tempDoublePtr+3|0] = HEAP8[ptr+3|0];
- HEAP8[tempDoublePtr+4|0] = HEAP8[ptr+4|0];
- HEAP8[tempDoublePtr+5|0] = HEAP8[ptr+5|0];
- HEAP8[tempDoublePtr+6|0] = HEAP8[ptr+6|0];
- HEAP8[tempDoublePtr+7|0] = HEAP8[ptr+7|0];
+ HEAP8[tempDoublePtr>>0] = HEAP8[ptr>>0];
+ HEAP8[tempDoublePtr+1>>0] = HEAP8[ptr+1>>0];
+ HEAP8[tempDoublePtr+2>>0] = HEAP8[ptr+2>>0];
+ HEAP8[tempDoublePtr+3>>0] = HEAP8[ptr+3>>0];
+ HEAP8[tempDoublePtr+4>>0] = HEAP8[ptr+4>>0];
+ HEAP8[tempDoublePtr+5>>0] = HEAP8[ptr+5>>0];
+ HEAP8[tempDoublePtr+6>>0] = HEAP8[ptr+6>>0];
+ HEAP8[tempDoublePtr+7>>0] = HEAP8[ptr+7>>0];
}
''' + ''.join(['''
function setTempRet%d(value) {
value = value|0;
tempRet%d = value;
}
+''' % (i, i) for i in range(10)]) + ''.join(['''
+function getTempRet%d() {
+ return tempRet%d|0;
+}
''' % (i, i) for i in range(10)])] + [PostSets.js + '\n'] + funcs_js + ['''
%s
@@ -644,9 +648,11 @@ function setTempRet%d(value) {
if not settings.get('SIDE_MODULE'):
funcs_js.append('''
-Runtime.stackAlloc = function(size) { return asm['stackAlloc'](size) };
-Runtime.stackSave = function() { return asm['stackSave']() };
-Runtime.stackRestore = function(top) { asm['stackRestore'](top) };
+Runtime.stackAlloc = asm['stackAlloc'];
+Runtime.stackSave = asm['stackSave'];
+Runtime.stackRestore = asm['stackRestore'];
+Runtime.setTempRet0 = asm['setTempRet0'];
+Runtime.getTempRet0 = asm['getTempRet0'];
''')
# Set function table masks
@@ -720,7 +726,7 @@ Runtime.stackRestore = function(top) { asm['stackRestore'](top) };
def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
jcache=None, temp_files=None, DEBUG=None, DEBUG_CACHE=None):
- """Runs the emscripten LLVM-to-JS compiler. We parallelize as much as possible
+ """Runs the emscripten LLVM-to-JS compiler.
Args:
infile: The path to the input LLVM assembly file.
@@ -731,559 +737,583 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
assert(settings['ASM_JS'])
- # Overview:
- # * Run LLVM backend to emit JS. JS includes function bodies, memory initializer,
- # and various metadata
- # * Run compiler.js on the metadata to emit the shell js code, pre/post-ambles,
- # JS library dependencies, etc.
-
- temp_js = temp_files.get('.4.js').name
- backend_compiler = os.path.join(shared.LLVM_ROOT, 'llc')
- backend_args = [backend_compiler, infile, '-march=js', '-filetype=asm', '-o', temp_js]
- if settings['PRECISE_F32']:
- backend_args += ['-emscripten-precise-f32']
- if settings['WARN_UNALIGNED']:
- backend_args += ['-emscripten-warn-unaligned']
- if settings['RESERVED_FUNCTION_POINTERS'] > 0:
- backend_args += ['-emscripten-reserved-function-pointers=%d' % settings['RESERVED_FUNCTION_POINTERS']]
- if settings['ASSERTIONS'] > 0:
- backend_args += ['-emscripten-assertions=%d' % settings['ASSERTIONS']]
- backend_args += ['-O' + str(settings['OPT_LEVEL'])]
- if DEBUG:
- logging.debug('emscript: llvm backend: ' + ' '.join(backend_args))
- t = time.time()
- shared.jsrun.timeout_run(subprocess.Popen(backend_args, stdout=subprocess.PIPE))
- if DEBUG:
- logging.debug(' emscript: llvm backend took %s seconds' % (time.time() - t))
- t = time.time()
-
- # Split up output
- backend_output = open(temp_js).read()
- #if DEBUG: print >> sys.stderr, backend_output
-
- start_funcs_marker = '// EMSCRIPTEN_START_FUNCTIONS'
- end_funcs_marker = '// EMSCRIPTEN_END_FUNCTIONS'
- metadata_split_marker = '// EMSCRIPTEN_METADATA'
-
- start_funcs = backend_output.index(start_funcs_marker)
- end_funcs = backend_output.rindex(end_funcs_marker)
- metadata_split = backend_output.rindex(metadata_split_marker)
-
- funcs = backend_output[start_funcs+len(start_funcs_marker):end_funcs]
- metadata_raw = backend_output[metadata_split+len(metadata_split_marker):]
- #if DEBUG: print >> sys.stderr, "METAraw", metadata_raw
- metadata = json.loads(metadata_raw)
- mem_init = backend_output[end_funcs+len(end_funcs_marker):metadata_split]
- #if DEBUG: print >> sys.stderr, "FUNCS", funcs
- #if DEBUG: print >> sys.stderr, "META", metadata
- #if DEBUG: print >> sys.stderr, "meminit", mem_init
-
- # function table masks
-
- table_sizes = {}
- for k, v in metadata['tables'].iteritems():
- table_sizes[k] = str(v.count(',')) # undercounts by one, but that is what we want
- #if settings['ASSERTIONS'] >= 2 and table_sizes[k] == 0:
- # print >> sys.stderr, 'warning: no function pointers with signature ' + k + ', but there is a call, which will abort if it occurs (this can result from undefined behavior, check for compiler warnings on your source files and consider -Werror)'
- funcs = re.sub(r"#FM_(\w+)#", lambda m: table_sizes[m.groups(0)[0]], funcs)
-
- # fix +float into float.0, if not running js opts
- if not settings['RUNNING_JS_OPTS']:
- def fix_dot_zero(m):
- num = m.group(3)
- # TODO: handle 0x floats?
- if num.find('.') < 0:
- e = num.find('e');
- if e < 0:
- num += '.0'
- else:
- num = num[:e] + '.0' + num[e:]
- return m.group(1) + m.group(2) + num
- funcs = re.sub(r'([(=,+\-*/%<>:?] *)\+(-?)((0x)?[0-9a-f]*\.?[0-9]+([eE][-+]?[0-9]+)?)', lambda m: fix_dot_zero(m), funcs)
-
- # js compiler
-
- if DEBUG: logging.debug('emscript: js compiler glue')
+ success = False
- # Settings changes
- assert settings['TARGET_ASMJS_UNKNOWN_EMSCRIPTEN'] == 1
- settings['TARGET_ASMJS_UNKNOWN_EMSCRIPTEN'] = 2
- i64_funcs = ['i64Add', 'i64Subtract', '__muldi3', '__divdi3', '__udivdi3', '__remdi3', '__uremdi3']
- for i64_func in i64_funcs:
- if i64_func in metadata['declares']:
- settings['PRECISE_I64_MATH'] = 2
- break
-
- metadata['declares'] = filter(lambda i64_func: i64_func not in ['getHigh32', 'setHigh32', '__muldi3', '__divdi3', '__remdi3', '__udivdi3', '__uremdi3'], metadata['declares']) # FIXME: do these one by one as normal js lib funcs
+ try:
- # Integrate info from backend
- settings['DEFAULT_LIBRARY_FUNCS_TO_INCLUDE'] = list(
- set(settings['DEFAULT_LIBRARY_FUNCS_TO_INCLUDE'] + map(shared.JS.to_nice_ident, metadata['declares'])).difference(
- map(lambda x: x[1:], metadata['implementedFunctions'])
- )
- ) + map(lambda x: x[1:], metadata['externs'])
- if metadata['simd']:
- settings['SIMD'] = 1
- if not metadata['canValidate'] and settings['ASM_JS'] != 2:
- logging.warning('disabling asm.js validation due to use of non-supported features')
- settings['ASM_JS'] = 2
+ # Overview:
+ # * Run LLVM backend to emit JS. JS includes function bodies, memory initializer,
+ # and various metadata
+ # * Run compiler.js on the metadata to emit the shell js code, pre/post-ambles,
+ # JS library dependencies, etc.
+
+ temp_js = temp_files.get('.4.js').name
+ backend_compiler = os.path.join(shared.LLVM_ROOT, 'llc')
+ backend_args = [backend_compiler, infile, '-march=js', '-filetype=asm', '-o', temp_js]
+ if settings['PRECISE_F32']:
+ backend_args += ['-emscripten-precise-f32']
+ if settings['WARN_UNALIGNED']:
+ backend_args += ['-emscripten-warn-unaligned']
+ if settings['RESERVED_FUNCTION_POINTERS'] > 0:
+ backend_args += ['-emscripten-reserved-function-pointers=%d' % settings['RESERVED_FUNCTION_POINTERS']]
+ if settings['ASSERTIONS'] > 0:
+ backend_args += ['-emscripten-assertions=%d' % settings['ASSERTIONS']]
+ if settings['ALIASING_FUNCTION_POINTERS'] == 0:
+ backend_args += ['-emscripten-no-aliasing-function-pointers']
+ backend_args += ['-O' + str(settings['OPT_LEVEL'])]
+ backend_args += ['-emscripten-max-setjmps=%d' % settings['MAX_SETJMPS']]
+ if DEBUG:
+ logging.debug('emscript: llvm backend: ' + ' '.join(backend_args))
+ t = time.time()
+ shared.jsrun.timeout_run(subprocess.Popen(backend_args, stdout=subprocess.PIPE))
+ if DEBUG:
+ logging.debug(' emscript: llvm backend took %s seconds' % (time.time() - t))
+ t = time.time()
+
+ # Split up output
+ backend_output = open(temp_js).read()
+ #if DEBUG: print >> sys.stderr, backend_output
+
+ start_funcs_marker = '// EMSCRIPTEN_START_FUNCTIONS'
+ end_funcs_marker = '// EMSCRIPTEN_END_FUNCTIONS'
+ metadata_split_marker = '// EMSCRIPTEN_METADATA'
+
+ start_funcs = backend_output.index(start_funcs_marker)
+ end_funcs = backend_output.rindex(end_funcs_marker)
+ metadata_split = backend_output.rindex(metadata_split_marker)
+
+ funcs = backend_output[start_funcs+len(start_funcs_marker):end_funcs]
+ metadata_raw = backend_output[metadata_split+len(metadata_split_marker):]
+ #if DEBUG: print >> sys.stderr, "METAraw", metadata_raw
+ metadata = json.loads(metadata_raw)
+ mem_init = backend_output[end_funcs+len(end_funcs_marker):metadata_split]
+ #if DEBUG: print >> sys.stderr, "FUNCS", funcs
+ #if DEBUG: print >> sys.stderr, "META", metadata
+ #if DEBUG: print >> sys.stderr, "meminit", mem_init
+
+ # function table masks
+
+ table_sizes = {}
+ for k, v in metadata['tables'].iteritems():
+ table_sizes[k] = str(v.count(',')) # undercounts by one, but that is what we want
+ #if settings['ASSERTIONS'] >= 2 and table_sizes[k] == 0:
+ # print >> sys.stderr, 'warning: no function pointers with signature ' + k + ', but there is a call, which will abort if it occurs (this can result from undefined behavior, check for compiler warnings on your source files and consider -Werror)'
+ funcs = re.sub(r"#FM_(\w+)#", lambda m: table_sizes[m.groups(0)[0]], funcs)
+
+ # fix +float into float.0, if not running js opts
+ if not settings['RUNNING_JS_OPTS']:
+ def fix_dot_zero(m):
+ num = m.group(3)
+ # TODO: handle 0x floats?
+ if num.find('.') < 0:
+ e = num.find('e');
+ if e < 0:
+ num += '.0'
+ else:
+ num = num[:e] + '.0' + num[e:]
+ return m.group(1) + m.group(2) + num
+ funcs = re.sub(r'([(=,+\-*/%<>:?] *)\+(-?)((0x)?[0-9a-f]*\.?[0-9]+([eE][-+]?[0-9]+)?)', lambda m: fix_dot_zero(m), funcs)
- # Save settings to a file to work around v8 issue 1579
- settings_file = temp_files.get('.txt').name
- def save_settings():
- global settings_text
- settings_text = json.dumps(settings, sort_keys=True)
- s = open(settings_file, 'w')
- s.write(settings_text)
- s.close()
- save_settings()
+ # js compiler
- # Call js compiler
- if DEBUG: t = time.time()
- out = jsrun.run_js(path_from_root('src', 'compiler.js'), compiler_engine, [settings_file, ';', 'glue'] + libraries, stdout=subprocess.PIPE, stderr=STDERR_FILE,
- cwd=path_from_root('src'))
- assert '//FORWARDED_DATA:' in out, 'Did not receive forwarded data in pre output - process failed?'
- glue, forwarded_data = out.split('//FORWARDED_DATA:')
+ if DEBUG: logging.debug('emscript: js compiler glue')
- if DEBUG:
- logging.debug(' emscript: glue took %s seconds' % (time.time() - t))
- t = time.time()
+ # Settings changes
+ assert settings['TARGET_ASMJS_UNKNOWN_EMSCRIPTEN'] == 1
+ settings['TARGET_ASMJS_UNKNOWN_EMSCRIPTEN'] = 2
+ i64_funcs = ['i64Add', 'i64Subtract', '__muldi3', '__divdi3', '__udivdi3', '__remdi3', '__uremdi3']
+ for i64_func in i64_funcs:
+ if i64_func in metadata['declares']:
+ settings['PRECISE_I64_MATH'] = 2
+ break
- last_forwarded_json = forwarded_json = json.loads(forwarded_data)
+ metadata['declares'] = filter(lambda i64_func: i64_func not in ['getHigh32', 'setHigh32', '__muldi3', '__divdi3', '__remdi3', '__udivdi3', '__uremdi3'], metadata['declares']) # FIXME: do these one by one as normal js lib funcs
- # merge in information from llvm backend
+ # Integrate info from backend
+ settings['DEFAULT_LIBRARY_FUNCS_TO_INCLUDE'] = list(
+ set(settings['DEFAULT_LIBRARY_FUNCS_TO_INCLUDE'] + map(shared.JS.to_nice_ident, metadata['declares'])).difference(
+ map(lambda x: x[1:], metadata['implementedFunctions'])
+ )
+ ) + map(lambda x: x[1:], metadata['externs'])
+ if metadata['simd']:
+ settings['SIMD'] = 1
+ if not metadata['canValidate'] and settings['ASM_JS'] != 2:
+ logging.warning('disabling asm.js validation due to use of non-supported features')
+ settings['ASM_JS'] = 2
+
+ # Save settings to a file to work around v8 issue 1579
+ settings_file = temp_files.get('.txt').name
+ def save_settings():
+ global settings_text
+ settings_text = json.dumps(settings, sort_keys=True)
+ s = open(settings_file, 'w')
+ s.write(settings_text)
+ s.close()
+ save_settings()
- last_forwarded_json['Functions']['tables'] = metadata['tables']
+ # Call js compiler
+ if DEBUG: t = time.time()
+ out = jsrun.run_js(path_from_root('src', 'compiler.js'), compiler_engine, [settings_file, ';', 'glue'] + libraries, stdout=subprocess.PIPE, stderr=STDERR_FILE,
+ cwd=path_from_root('src'))
+ assert '//FORWARDED_DATA:' in out, 'Did not receive forwarded data in pre output - process failed?'
+ glue, forwarded_data = out.split('//FORWARDED_DATA:')
- '''indexed_functions = set()
- for key in forwarded_json['Functions']['indexedFunctions'].iterkeys():
- indexed_functions.add(key)'''
+ if DEBUG:
+ logging.debug(' emscript: glue took %s seconds' % (time.time() - t))
+ t = time.time()
- pre, post = glue.split('// EMSCRIPTEN_END_FUNCS')
+ last_forwarded_json = forwarded_json = json.loads(forwarded_data)
- #print >> sys.stderr, 'glue:', pre, '\n\n||||||||||||||||\n\n', post, '...............'
+ # merge in information from llvm backend
- # memory and global initializers
+ last_forwarded_json['Functions']['tables'] = metadata['tables']
- global_initializers = ', '.join(map(lambda i: '{ func: function() { %s() } }' % i, metadata['initializers']))
+ '''indexed_functions = set()
+ for key in forwarded_json['Functions']['indexedFunctions'].iterkeys():
+ indexed_functions.add(key)'''
- pre = pre.replace('STATICTOP = STATIC_BASE + 0;', '''STATICTOP = STATIC_BASE + Runtime.alignMemory(%d);
-/* global initializers */ __ATINIT__.push(%s);
-%s''' % (mem_init.count(',')+1, global_initializers, mem_init)) # XXX wrong size calculation!
+ pre, post = glue.split('// EMSCRIPTEN_END_FUNCS')
- funcs_js = [funcs]
- if settings.get('ASM_JS'):
- parts = pre.split('// ASM_LIBRARY FUNCTIONS\n')
- if len(parts) > 1:
- pre = parts[0]
- funcs_js.append(parts[1])
+ #print >> sys.stderr, 'glue:', pre, '\n\n||||||||||||||||\n\n', post, '...............'
- # merge forwarded data
- assert settings.get('ASM_JS'), 'fastcomp is asm.js only'
- settings['EXPORTED_FUNCTIONS'] = forwarded_json['EXPORTED_FUNCTIONS']
- all_exported_functions = set(settings['EXPORTED_FUNCTIONS']) # both asm.js and otherwise
- for additional_export in settings['DEFAULT_LIBRARY_FUNCS_TO_INCLUDE']: # additional functions to export from asm, if they are implemented
- all_exported_functions.add('_' + additional_export)
- exported_implemented_functions = set(metadata['exports'])
- export_bindings = settings['EXPORT_BINDINGS']
- export_all = settings['EXPORT_ALL']
- for key in metadata['implementedFunctions'] + forwarded_json['Functions']['implementedFunctions'].keys(): # XXX perf
- if key in all_exported_functions or export_all or (export_bindings and key.startswith('_emscripten_bind')):
- exported_implemented_functions.add(key)
- implemented_functions = set(metadata['implementedFunctions'])
-
- # Add named globals
- named_globals = '\n'.join(['var %s = %s;' % (k, v) for k, v in metadata['namedGlobals'].iteritems()])
- pre = pre.replace('// === Body ===', '// === Body ===\n' + named_globals + '\n')
+ # memory and global initializers
- #if DEBUG: outfile.write('// pre\n')
- outfile.write(pre)
- pre = None
+ global_initializers = ', '.join(map(lambda i: '{ func: function() { %s() } }' % i, metadata['initializers']))
- #if DEBUG: outfile.write('// funcs\n')
-
- if settings.get('ASM_JS'):
- # Move preAsms to their right place
- def move_preasm(m):
- contents = m.groups(0)[0]
- outfile.write(contents + '\n')
- return ''
- funcs_js[1] = re.sub(r'/\* PRE_ASM \*/(.*)\n', lambda m: move_preasm(m), funcs_js[1])
+ pre = pre.replace('STATICTOP = STATIC_BASE + 0;', '''STATICTOP = STATIC_BASE + Runtime.alignMemory(%d);
+ /* global initializers */ __ATINIT__.push(%s);
+ %s''' % (mem_init.count(',')+1, global_initializers, mem_init)) # XXX wrong size calculation!
- funcs_js += ['\n// EMSCRIPTEN_END_FUNCS\n']
+ funcs_js = [funcs]
+ if settings.get('ASM_JS'):
+ parts = pre.split('// ASM_LIBRARY FUNCTIONS\n')
+ if len(parts) > 1:
+ pre = parts[0]
+ funcs_js.append(parts[1])
- simple = os.environ.get('EMCC_SIMPLE_ASM')
- class Counter:
- i = 0
- j = 0
- if 'pre' in last_forwarded_json['Functions']['tables']:
- pre_tables = last_forwarded_json['Functions']['tables']['pre']
- del last_forwarded_json['Functions']['tables']['pre']
- else:
- pre_tables = ''
+ # merge forwarded data
+ assert settings.get('ASM_JS'), 'fastcomp is asm.js only'
+ settings['EXPORTED_FUNCTIONS'] = forwarded_json['EXPORTED_FUNCTIONS']
+ all_exported_functions = set(settings['EXPORTED_FUNCTIONS']) # both asm.js and otherwise
+ for additional_export in settings['DEFAULT_LIBRARY_FUNCS_TO_INCLUDE']: # additional functions to export from asm, if they are implemented
+ all_exported_functions.add('_' + additional_export)
+ exported_implemented_functions = set(metadata['exports'])
+ export_bindings = settings['EXPORT_BINDINGS']
+ export_all = settings['EXPORT_ALL']
+ all_implemented = metadata['implementedFunctions'] + forwarded_json['Functions']['implementedFunctions'].keys() # XXX perf?
+ for key in all_implemented:
+ if key in all_exported_functions or export_all or (export_bindings and key.startswith('_emscripten_bind')):
+ exported_implemented_functions.add(key)
+ implemented_functions = set(metadata['implementedFunctions'])
+ if settings['ASSERTIONS'] and settings.get('ORIGINAL_EXPORTED_FUNCTIONS'):
+ for requested in settings['ORIGINAL_EXPORTED_FUNCTIONS']:
+ if requested not in all_implemented:
+ logging.warning('function requested to be exported, but not implemented: "%s"', requested)
+
+ # Add named globals
+ named_globals = '\n'.join(['var %s = %s;' % (k, v) for k, v in metadata['namedGlobals'].iteritems()])
+ pre = pre.replace('// === Body ===', '// === Body ===\n' + named_globals + '\n')
+
+ #if DEBUG: outfile.write('// pre\n')
+ outfile.write(pre)
+ pre = None
+
+ #if DEBUG: outfile.write('// funcs\n')
- def unfloat(s):
- return 'd' if s == 'f' else s # lower float to double for ffis
+ if settings.get('ASM_JS'):
+ # Move preAsms to their right place
+ def move_preasm(m):
+ contents = m.groups(0)[0]
+ outfile.write(contents + '\n')
+ return ''
+ funcs_js[1] = re.sub(r'/\* PRE_ASM \*/(.*)\n', lambda m: move_preasm(m), funcs_js[1])
+
+ funcs_js += ['\n// EMSCRIPTEN_END_FUNCS\n']
+
+ simple = os.environ.get('EMCC_SIMPLE_ASM')
+ class Counter:
+ i = 0
+ j = 0
+ if 'pre' in last_forwarded_json['Functions']['tables']:
+ pre_tables = last_forwarded_json['Functions']['tables']['pre']
+ del last_forwarded_json['Functions']['tables']['pre']
+ else:
+ pre_tables = ''
- if settings['ASSERTIONS'] >= 2:
- debug_tables = {}
+ def unfloat(s):
+ return 'd' if s == 'f' else s # lower float to double for ffis
- def make_table(sig, raw):
- params = ','.join(['p%d' % p for p in range(len(sig)-1)])
- coerced_params = ','.join([shared.JS.make_coercion('p%d', unfloat(sig[p+1]), settings) % p for p in range(len(sig)-1)])
- coercions = ';'.join(['p%d = %s' % (p, shared.JS.make_coercion('p%d' % p, sig[p+1], settings)) for p in range(len(sig)-1)]) + ';'
- def make_func(name, code):
- return 'function %s(%s) { %s %s }' % (name, params, coercions, code)
- def make_bad(target=None):
- i = Counter.i
- Counter.i += 1
- if target is None: target = i
- name = 'b' + str(i)
- if not settings['ASSERTIONS']:
- code = 'abort(%s);' % target
- else:
- code = 'nullFunc_' + sig + '(%d);' % target
- if sig[0] != 'v':
- code += 'return %s' % shared.JS.make_initializer(sig[0], settings) + ';'
- return name, make_func(name, code)
- bad, bad_func = make_bad() # the default bad func
- if settings['ASSERTIONS'] <= 1:
- Counter.pre = [bad_func]
- else:
- Counter.pre = []
- start = raw.index('[')
- end = raw.rindex(']')
- body = raw[start+1:end].split(',')
- for j in range(settings['RESERVED_FUNCTION_POINTERS']):
- curr = 'jsCall_%s_%s' % (sig, j)
- body[settings['FUNCTION_POINTER_ALIGNMENT'] * (1 + j)] = curr
- implemented_functions.add(curr)
- Counter.j = 0
- def fix_item(item):
- Counter.j += 1
- newline = Counter.j % 30 == 29
- if item == '0':
- if settings['ASSERTIONS'] <= 1:
- return bad if not newline else (bad + '\n')
+ if settings['ASSERTIONS'] >= 2:
+ debug_tables = {}
+
+ def make_table(sig, raw):
+ params = ','.join(['p%d' % p for p in range(len(sig)-1)])
+ coerced_params = ','.join([shared.JS.make_coercion('p%d', unfloat(sig[p+1]), settings) % p for p in range(len(sig)-1)])
+ coercions = ';'.join(['p%d = %s' % (p, shared.JS.make_coercion('p%d' % p, sig[p+1], settings)) for p in range(len(sig)-1)]) + ';'
+ def make_func(name, code):
+ return 'function %s(%s) { %s %s }' % (name, params, coercions, code)
+ def make_bad(target=None):
+ i = Counter.i
+ Counter.i += 1
+ if target is None: target = i
+ name = 'b' + str(i)
+ if not settings['ASSERTIONS']:
+ code = 'abort(%s);' % target
else:
- specific_bad, specific_bad_func = make_bad(Counter.j-1)
- Counter.pre.append(specific_bad_func)
- return specific_bad if not newline else (specific_bad + '\n')
- if item not in implemented_functions:
- # this is imported into asm, we must wrap it
- call_ident = item
- if call_ident in metadata['redirects']: call_ident = metadata['redirects'][call_ident]
- if not call_ident.startswith('_') and not call_ident.startswith('Math_'): call_ident = '_' + call_ident
- code = call_ident + '(' + coerced_params + ')'
+ code = 'nullFunc_' + sig + '(%d);' % target
if sig[0] != 'v':
- # ffis cannot return float
- if sig[0] == 'f': code = '+' + code
- code = 'return ' + shared.JS.make_coercion(code, sig[0], settings)
- code += ';'
- Counter.pre.append(make_func(item + '__wrapper', code))
- return item + '__wrapper'
- return item if not newline else (item + '\n')
- if settings['ASSERTIONS'] >= 2:
- debug_tables[sig] = body
- body = ','.join(map(fix_item, body))
- return ('\n'.join(Counter.pre), ''.join([raw[:start+1], body, raw[end:]]))
-
- infos = [make_table(sig, raw) for sig, raw in last_forwarded_json['Functions']['tables'].iteritems()]
- Counter.pre = []
-
- function_tables_defs = '\n'.join([info[0] for info in infos]) + '\n// EMSCRIPTEN_END_FUNCS\n' + '\n'.join([info[1] for info in infos])
-
- asm_setup = ''
- maths = ['Math.' + func for func in ['floor', 'abs', 'sqrt', 'pow', 'cos', 'sin', 'tan', 'acos', 'asin', 'atan', 'atan2', 'exp', 'log', 'ceil', 'imul']]
- fundamentals = ['Math', 'Int8Array', 'Int16Array', 'Int32Array', 'Uint8Array', 'Uint16Array', 'Uint32Array', 'Float32Array', 'Float64Array']
- math_envs = ['Math.min'] # TODO: move min to maths
- asm_setup += '\n'.join(['var %s = %s;' % (f.replace('.', '_'), f) for f in math_envs])
-
- if settings['PRECISE_F32']: maths += ['Math.fround']
-
- basic_funcs = ['abort', 'assert', 'asmPrintInt', 'asmPrintFloat'] + [m.replace('.', '_') for m in math_envs]
- if settings['RESERVED_FUNCTION_POINTERS'] > 0: basic_funcs.append('jsCall')
- if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE']
- if settings['CHECK_HEAP_ALIGN']: basic_funcs += ['CHECK_ALIGN_2', 'CHECK_ALIGN_4', 'CHECK_ALIGN_8']
- if settings['ASSERTIONS']:
- if settings['ASSERTIONS'] >= 2: import difflib
- for sig in last_forwarded_json['Functions']['tables'].iterkeys():
- basic_funcs += ['nullFunc_' + sig]
+ code += 'return %s' % shared.JS.make_initializer(sig[0], settings) + ';'
+ return name, make_func(name, code)
+ bad, bad_func = make_bad() # the default bad func
if settings['ASSERTIONS'] <= 1:
- extra = ' Module["printErr"]("Build with ASSERTIONS=2 for more info.");'
- pointer = ' '
+ Counter.pre = [bad_func]
else:
- pointer = ' \'" + x + "\' '
- asm_setup += '\nvar debug_table_' + sig + ' = ' + json.dumps(debug_tables[sig]) + ';'
- extra = ' Module["printErr"]("This pointer might make sense in another type signature: '
- # sort signatures, attempting to show most likely related ones first
- sigs = last_forwarded_json['Functions']['tables'].keys()
- def keyfunc(other):
- ret = 0
- minlen = min(len(other), len(sig))
- maxlen = min(len(other), len(sig))
- if other.startswith(sig) or sig.startswith(other): ret -= 1000 # prioritize prefixes, could be dropped params
- ret -= 133*difflib.SequenceMatcher(a=other, b=sig).ratio() # prioritize on diff similarity
- ret += 15*abs(len(other) - len(sig))/float(maxlen) # deprioritize the bigger the length difference is
- for i in range(minlen):
- if other[i] == sig[i]: ret -= 5/float(maxlen) # prioritize on identically-placed params
- ret += 20*len(other) # deprioritize on length
- return ret
- sigs.sort(key=keyfunc)
- for other in sigs:
- if other != sig:
- extra += other + ': " + debug_table_' + other + '[x] + " '
- extra += '"); '
- asm_setup += '\nfunction nullFunc_' + sig + '(x) { Module["printErr"]("Invalid function pointer' + pointer + 'called with signature \'' + sig + '\'. ' + \
- 'Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? ' + \
- 'Or calling a function with an incorrect type, which will fail? ' + \
- '(it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)' + \
- '"); ' + extra + ' abort(x) }\n'
+ Counter.pre = []
+ start = raw.index('[')
+ end = raw.rindex(']')
+ body = raw[start+1:end].split(',')
+ for j in range(settings['RESERVED_FUNCTION_POINTERS']):
+ curr = 'jsCall_%s_%s' % (sig, j)
+ body[settings['FUNCTION_POINTER_ALIGNMENT'] * (1 + j)] = curr
+ implemented_functions.add(curr)
+ Counter.j = 0
+ def fix_item(item):
+ Counter.j += 1
+ newline = Counter.j % 30 == 29
+ if item == '0':
+ if settings['ASSERTIONS'] <= 1:
+ return bad if not newline else (bad + '\n')
+ else:
+ specific_bad, specific_bad_func = make_bad(Counter.j-1)
+ Counter.pre.append(specific_bad_func)
+ return specific_bad if not newline else (specific_bad + '\n')
+ if item not in implemented_functions:
+ # this is imported into asm, we must wrap it
+ call_ident = item
+ if call_ident in metadata['redirects']: call_ident = metadata['redirects'][call_ident]
+ if not call_ident.startswith('_') and not call_ident.startswith('Math_'): call_ident = '_' + call_ident
+ code = call_ident + '(' + coerced_params + ')'
+ if sig[0] != 'v':
+ # ffis cannot return float
+ if sig[0] == 'f': code = '+' + code
+ code = 'return ' + shared.JS.make_coercion(code, sig[0], settings)
+ code += ';'
+ Counter.pre.append(make_func(item + '__wrapper', code))
+ return item + '__wrapper'
+ return item if not newline else (item + '\n')
+ if settings['ASSERTIONS'] >= 2:
+ debug_tables[sig] = body
+ body = ','.join(map(fix_item, body))
+ return ('\n'.join(Counter.pre), ''.join([raw[:start+1], body, raw[end:]]))
+
+ infos = [make_table(sig, raw) for sig, raw in last_forwarded_json['Functions']['tables'].iteritems()]
+ Counter.pre = []
+
+ function_tables_defs = '\n'.join([info[0] for info in infos]) + '\n// EMSCRIPTEN_END_FUNCS\n' + '\n'.join([info[1] for info in infos])
+
+ asm_setup = ''
+ maths = ['Math.' + func for func in ['floor', 'abs', 'sqrt', 'pow', 'cos', 'sin', 'tan', 'acos', 'asin', 'atan', 'atan2', 'exp', 'log', 'ceil', 'imul']]
+ fundamentals = ['Math', 'Int8Array', 'Int16Array', 'Int32Array', 'Uint8Array', 'Uint16Array', 'Uint32Array', 'Float32Array', 'Float64Array']
+ math_envs = ['Math.min'] # TODO: move min to maths
+ asm_setup += '\n'.join(['var %s = %s;' % (f.replace('.', '_'), f) for f in math_envs])
+
+ if settings['PRECISE_F32']: maths += ['Math.fround']
+
+ basic_funcs = ['abort', 'assert', 'asmPrintInt', 'asmPrintFloat'] + [m.replace('.', '_') for m in math_envs]
+ if settings['RESERVED_FUNCTION_POINTERS'] > 0: basic_funcs.append('jsCall')
+ if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE', 'SAFE_FT_MASK']
+ if settings['CHECK_HEAP_ALIGN']: basic_funcs += ['CHECK_ALIGN_2', 'CHECK_ALIGN_4', 'CHECK_ALIGN_8']
+ if settings['ASSERTIONS']:
+ if settings['ASSERTIONS'] >= 2: import difflib
+ for sig in last_forwarded_json['Functions']['tables'].iterkeys():
+ basic_funcs += ['nullFunc_' + sig]
+ if settings['ASSERTIONS'] <= 1:
+ extra = ' Module["printErr"]("Build with ASSERTIONS=2 for more info.");'
+ pointer = ' '
+ else:
+ pointer = ' \'" + x + "\' '
+ asm_setup += '\nvar debug_table_' + sig + ' = ' + json.dumps(debug_tables[sig]) + ';'
+ extra = ' Module["printErr"]("This pointer might make sense in another type signature: '
+ # sort signatures, attempting to show most likely related ones first
+ sigs = last_forwarded_json['Functions']['tables'].keys()
+ def keyfunc(other):
+ ret = 0
+ minlen = min(len(other), len(sig))
+ maxlen = min(len(other), len(sig))
+ if other.startswith(sig) or sig.startswith(other): ret -= 1000 # prioritize prefixes, could be dropped params
+ ret -= 133*difflib.SequenceMatcher(a=other, b=sig).ratio() # prioritize on diff similarity
+ ret += 15*abs(len(other) - len(sig))/float(maxlen) # deprioritize the bigger the length difference is
+ for i in range(minlen):
+ if other[i] == sig[i]: ret -= 5/float(maxlen) # prioritize on identically-placed params
+ ret += 20*len(other) # deprioritize on length
+ return ret
+ sigs.sort(key=keyfunc)
+ for other in sigs:
+ if other != sig:
+ extra += other + ': " + debug_table_' + other + '[x] + " '
+ extra += '"); '
+ asm_setup += '\nfunction nullFunc_' + sig + '(x) { Module["printErr"]("Invalid function pointer' + pointer + 'called with signature \'' + sig + '\'. ' + \
+ 'Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? ' + \
+ 'Or calling a function with an incorrect type, which will fail? ' + \
+ '(it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)' + \
+ '"); ' + extra + ' abort(x) }\n'
+
+ basic_vars = ['STACKTOP', 'STACK_MAX', 'tempDoublePtr', 'ABORT']
+ basic_float_vars = ['NaN', 'Infinity']
+
+ if metadata.get('preciseI64MathUsed') or \
+ forwarded_json['Functions']['libraryFunctions'].get('llvm_cttz_i32') or \
+ forwarded_json['Functions']['libraryFunctions'].get('llvm_ctlz_i32'):
+ basic_vars += ['cttz_i8', 'ctlz_i8']
- basic_vars = ['STACKTOP', 'STACK_MAX', 'tempDoublePtr', 'ABORT']
- basic_float_vars = ['NaN', 'Infinity']
+ if settings.get('DLOPEN_SUPPORT'):
+ for sig in last_forwarded_json['Functions']['tables'].iterkeys():
+ basic_vars.append('F_BASE_%s' % sig)
+ asm_setup += ' var F_BASE_%s = %s;\n' % (sig, 'FUNCTION_TABLE_OFFSET' if settings.get('SIDE_MODULE') else '0') + '\n'
- if metadata.get('preciseI64MathUsed') or \
- forwarded_json['Functions']['libraryFunctions'].get('llvm_cttz_i32') or \
- forwarded_json['Functions']['libraryFunctions'].get('llvm_ctlz_i32'):
- basic_vars += ['cttz_i8', 'ctlz_i8']
+ if '_rand' in exported_implemented_functions or '_srand' in exported_implemented_functions:
+ basic_vars += ['___rand_seed']
+
+ asm_runtime_funcs = ['stackAlloc', 'stackSave', 'stackRestore', 'setThrew', 'setTempRet0', 'getTempRet0']
+ # function tables
+ function_tables = ['dynCall_' + table for table in last_forwarded_json['Functions']['tables']]
+ function_tables_impls = []
- if settings.get('DLOPEN_SUPPORT'):
for sig in last_forwarded_json['Functions']['tables'].iterkeys():
- basic_vars.append('F_BASE_%s' % sig)
- asm_setup += ' var F_BASE_%s = %s;\n' % (sig, 'FUNCTION_TABLE_OFFSET' if settings.get('SIDE_MODULE') else '0') + '\n'
+ args = ','.join(['a' + str(i) for i in range(1, len(sig))])
+ arg_coercions = ' '.join(['a' + str(i) + '=' + shared.JS.make_coercion('a' + str(i), sig[i], settings) + ';' for i in range(1, len(sig))])
+ coerced_args = ','.join([shared.JS.make_coercion('a' + str(i), sig[i], settings) for i in range(1, len(sig))])
+ ret = ('return ' if sig[0] != 'v' else '') + shared.JS.make_coercion('FUNCTION_TABLE_%s[index&{{{ FTM_%s }}}](%s)' % (sig, sig, coerced_args), sig[0], settings)
+ function_tables_impls.append('''
+ function dynCall_%s(index%s%s) {
+ index = index|0;
+ %s
+ %s;
+ }
+ ''' % (sig, ',' if len(sig) > 1 else '', args, arg_coercions, ret))
+
+ ffi_args = ','.join([shared.JS.make_coercion('a' + str(i), sig[i], settings, ffi_arg=True) for i in range(1, len(sig))])
+ for i in range(settings['RESERVED_FUNCTION_POINTERS']):
+ jsret = ('return ' if sig[0] != 'v' else '') + shared.JS.make_coercion('jsCall(%d%s%s)' % (i, ',' if ffi_args else '', ffi_args), sig[0], settings, ffi_result=True)
+ function_tables_impls.append('''
+ function jsCall_%s_%s(%s) {
+ %s
+ %s;
+ }
+
+ ''' % (sig, i, args, arg_coercions, jsret))
+ shared.Settings.copy(settings)
+ asm_setup += '\n' + shared.JS.make_invoke(sig) + '\n'
+ basic_funcs.append('invoke_%s' % sig)
+ if settings.get('DLOPEN_SUPPORT'):
+ asm_setup += '\n' + shared.JS.make_extcall(sig) + '\n'
+ basic_funcs.append('extCall_%s' % sig)
+
+ # calculate exports
+ exported_implemented_functions = list(exported_implemented_functions) + metadata['initializers']
+ exported_implemented_functions.append('runPostSets')
+ exports = []
+ if not simple:
+ for export in exported_implemented_functions + asm_runtime_funcs + function_tables:
+ exports.append("%s: %s" % (export, export))
+ exports = '{ ' + ', '.join(exports) + ' }'
+ else:
+ exports = '_main'
+ # calculate globals
+ try:
+ del forwarded_json['Variables']['globals']['_llvm_global_ctors'] # not a true variable
+ except:
+ pass
+ # If no named globals, only need externals
+ global_vars = metadata['externs'] #+ forwarded_json['Variables']['globals']
+ global_funcs = list(set(['_' + key for key, value in forwarded_json['Functions']['libraryFunctions'].iteritems() if value != 2]).difference(set(global_vars)).difference(implemented_functions))
+ def math_fix(g):
+ return g if not g.startswith('Math_') else g.split('_')[1]
+ asm_global_funcs = ''.join([' var ' + g.replace('.', '_') + '=global.' + g + ';\n' for g in maths]) + \
+ ''.join([' var ' + g + '=env.' + math_fix(g) + ';\n' for g in basic_funcs + global_funcs])
+ asm_global_vars = ''.join([' var ' + g + '=env.' + g + '|0;\n' for g in basic_vars + global_vars])
+ # In linkable modules, we need to add some explicit globals for global variables that can be linked and used across modules
+ if settings.get('MAIN_MODULE') or settings.get('SIDE_MODULE'):
+ assert settings.get('TARGET_ASMJS_UNKNOWN_EMSCRIPTEN'), 'TODO: support x86 target when linking modules (needs offset of 4 and not 8 here)'
+ for key, value in forwarded_json['Variables']['globals'].iteritems():
+ if value.get('linkable'):
+ init = forwarded_json['Variables']['indexedGlobals'][key] + 8 # 8 is Runtime.GLOBAL_BASE / STATIC_BASE
+ if settings.get('SIDE_MODULE'): init = '(H_BASE+' + str(init) + ')|0'
+ asm_global_vars += ' var %s=%s;\n' % (key, str(init))
+
+ # sent data
+ the_global = '{ ' + ', '.join(['"' + math_fix(s) + '": ' + s for s in fundamentals]) + ' }'
+ sending = '{ ' + ', '.join(['"' + math_fix(s) + '": ' + s for s in basic_funcs + global_funcs + basic_vars + basic_float_vars + global_vars]) + ' }'
+ # received
+ if not simple:
+ receiving = ';\n'.join(['var ' + s + ' = Module["' + s + '"] = asm["' + s + '"]' for s in exported_implemented_functions + function_tables])
+ else:
+ receiving = 'var _main = Module["_main"] = asm;'
- if '_rand' in exported_implemented_functions or '_srand' in exported_implemented_functions:
- basic_vars += ['___rand_seed']
+ # finalize
- asm_runtime_funcs = ['stackAlloc', 'stackSave', 'stackRestore', 'setThrew'] + ['setTempRet%d' % i for i in range(10)]
- # function tables
- function_tables = ['dynCall_' + table for table in last_forwarded_json['Functions']['tables']]
- function_tables_impls = []
+ if DEBUG: logging.debug('asm text sizes' + str([map(len, funcs_js), len(asm_setup), len(asm_global_vars), len(asm_global_funcs), len(pre_tables), len('\n'.join(function_tables_impls)), len(function_tables_defs.replace('\n', '\n ')), len(exports), len(the_global), len(sending), len(receiving)]))
- for sig in last_forwarded_json['Functions']['tables'].iterkeys():
- args = ','.join(['a' + str(i) for i in range(1, len(sig))])
- arg_coercions = ' '.join(['a' + str(i) + '=' + shared.JS.make_coercion('a' + str(i), sig[i], settings) + ';' for i in range(1, len(sig))])
- coerced_args = ','.join([shared.JS.make_coercion('a' + str(i), sig[i], settings) for i in range(1, len(sig))])
- ret = ('return ' if sig[0] != 'v' else '') + shared.JS.make_coercion('FUNCTION_TABLE_%s[index&{{{ FTM_%s }}}](%s)' % (sig, sig, coerced_args), sig[0], settings)
- function_tables_impls.append('''
- function dynCall_%s(index%s%s) {
- index = index|0;
- %s
- %s;
+ funcs_js = ['''
+ %s
+ function asmPrintInt(x, y) {
+ Module.print('int ' + x + ',' + y);// + ' ' + new Error().stack);
}
-''' % (sig, ',' if len(sig) > 1 else '', args, arg_coercions, ret))
-
- for i in range(settings['RESERVED_FUNCTION_POINTERS']):
- jsret = ('return ' if sig[0] != 'v' else '') + shared.JS.make_coercion('jsCall(%d%s%s)' % (i, ',' if coerced_args else '', coerced_args), sig[0], settings)
- function_tables_impls.append('''
- function jsCall_%s_%s(%s) {
+ function asmPrintFloat(x, y) {
+ Module.print('float ' + x + ',' + y);// + ' ' + new Error().stack);
+ }
+ // EMSCRIPTEN_START_ASM
+ var asm = (function(global, env, buffer) {
%s
- %s;
+ var HEAP8 = new global.Int8Array(buffer);
+ var HEAP16 = new global.Int16Array(buffer);
+ var HEAP32 = new global.Int32Array(buffer);
+ var HEAPU8 = new global.Uint8Array(buffer);
+ var HEAPU16 = new global.Uint16Array(buffer);
+ var HEAPU32 = new global.Uint32Array(buffer);
+ var HEAPF32 = new global.Float32Array(buffer);
+ var HEAPF64 = new global.Float64Array(buffer);
+ ''' % (asm_setup, "'use asm';" if not metadata.get('hasInlineJS') and not settings['SIDE_MODULE'] and settings['ASM_JS'] == 1 else "'almost asm';") + '\n' + asm_global_vars + '''
+ var __THREW__ = 0;
+ var threwValue = 0;
+ var setjmpId = 0;
+ var undef = 0;
+ var nan = +env.NaN, inf = +env.Infinity;
+ var tempInt = 0, tempBigInt = 0, tempBigIntP = 0, tempBigIntS = 0, tempBigIntR = 0.0, tempBigIntI = 0, tempBigIntD = 0, tempValue = 0, tempDouble = 0.0;
+ ''' + ''.join(['''
+ var tempRet%d = 0;''' % i for i in range(10)]) + '\n' + asm_global_funcs] + [' var tempFloat = %s;\n' % ('Math_fround(0)' if settings.get('PRECISE_F32') else '0.0')] + ([' const f0 = Math_fround(0);\n'] if settings.get('PRECISE_F32') else []) + ['''
+ // EMSCRIPTEN_START_FUNCS
+ function stackAlloc(size) {
+ size = size|0;
+ var ret = 0;
+ ret = STACKTOP;
+ STACKTOP = (STACKTOP + size)|0;
+ ''' + ('STACKTOP = (STACKTOP + 3)&-4;' if settings['TARGET_X86'] else 'STACKTOP = (STACKTOP + 7)&-8;') + '''
+ return ret|0;
}
-
-''' % (sig, i, args, arg_coercions, jsret))
- shared.Settings.copy(settings)
- asm_setup += '\n' + shared.JS.make_invoke(sig) + '\n'
- basic_funcs.append('invoke_%s' % sig)
- if settings.get('DLOPEN_SUPPORT'):
- asm_setup += '\n' + shared.JS.make_extcall(sig) + '\n'
- basic_funcs.append('extCall_%s' % sig)
-
- # calculate exports
- exported_implemented_functions = list(exported_implemented_functions) + metadata['initializers']
- exported_implemented_functions.append('runPostSets')
- exports = []
- if not simple:
- for export in exported_implemented_functions + asm_runtime_funcs + function_tables:
- exports.append("%s: %s" % (export, export))
- exports = '{ ' + ', '.join(exports) + ' }'
- else:
- exports = '_main'
- # calculate globals
- try:
- del forwarded_json['Variables']['globals']['_llvm_global_ctors'] # not a true variable
- except:
- pass
- # If no named globals, only need externals
- global_vars = metadata['externs'] #+ forwarded_json['Variables']['globals']
- global_funcs = list(set(['_' + key for key, value in forwarded_json['Functions']['libraryFunctions'].iteritems() if value != 2]).difference(set(global_vars)).difference(implemented_functions))
- def math_fix(g):
- return g if not g.startswith('Math_') else g.split('_')[1]
- asm_global_funcs = ''.join([' var ' + g.replace('.', '_') + '=global.' + g + ';\n' for g in maths]) + \
- ''.join([' var ' + g + '=env.' + math_fix(g) + ';\n' for g in basic_funcs + global_funcs])
- asm_global_vars = ''.join([' var ' + g + '=env.' + g + '|0;\n' for g in basic_vars + global_vars])
- # In linkable modules, we need to add some explicit globals for global variables that can be linked and used across modules
- if settings.get('MAIN_MODULE') or settings.get('SIDE_MODULE'):
- assert settings.get('TARGET_ASMJS_UNKNOWN_EMSCRIPTEN'), 'TODO: support x86 target when linking modules (needs offset of 4 and not 8 here)'
- for key, value in forwarded_json['Variables']['globals'].iteritems():
- if value.get('linkable'):
- init = forwarded_json['Variables']['indexedGlobals'][key] + 8 # 8 is Runtime.GLOBAL_BASE / STATIC_BASE
- if settings.get('SIDE_MODULE'): init = '(H_BASE+' + str(init) + ')|0'
- asm_global_vars += ' var %s=%s;\n' % (key, str(init))
-
- # sent data
- the_global = '{ ' + ', '.join(['"' + math_fix(s) + '": ' + s for s in fundamentals]) + ' }'
- sending = '{ ' + ', '.join(['"' + math_fix(s) + '": ' + s for s in basic_funcs + global_funcs + basic_vars + basic_float_vars + global_vars]) + ' }'
- # received
- if not simple:
- receiving = ';\n'.join(['var ' + s + ' = Module["' + s + '"] = asm["' + s + '"]' for s in exported_implemented_functions + function_tables])
- else:
- receiving = 'var _main = Module["_main"] = asm;'
-
- # finalize
-
- if DEBUG: logging.debug('asm text sizes' + str([map(len, funcs_js), len(asm_setup), len(asm_global_vars), len(asm_global_funcs), len(pre_tables), len('\n'.join(function_tables_impls)), len(function_tables_defs.replace('\n', '\n ')), len(exports), len(the_global), len(sending), len(receiving)]))
-
- funcs_js = ['''
-%s
-function asmPrintInt(x, y) {
- Module.print('int ' + x + ',' + y);// + ' ' + new Error().stack);
-}
-function asmPrintFloat(x, y) {
- Module.print('float ' + x + ',' + y);// + ' ' + new Error().stack);
-}
-// EMSCRIPTEN_START_ASM
-var asm = (function(global, env, buffer) {
- %s
- var HEAP8 = new global.Int8Array(buffer);
- var HEAP16 = new global.Int16Array(buffer);
- var HEAP32 = new global.Int32Array(buffer);
- var HEAPU8 = new global.Uint8Array(buffer);
- var HEAPU16 = new global.Uint16Array(buffer);
- var HEAPU32 = new global.Uint32Array(buffer);
- var HEAPF32 = new global.Float32Array(buffer);
- var HEAPF64 = new global.Float64Array(buffer);
-''' % (asm_setup, "'use asm';" if not metadata.get('hasInlineJS') and not settings['SIDE_MODULE'] and settings['ASM_JS'] == 1 else "'almost asm';") + '\n' + asm_global_vars + '''
- var __THREW__ = 0;
- var threwValue = 0;
- var setjmpId = 0;
- var undef = 0;
- var nan = +env.NaN, inf = +env.Infinity;
- var tempInt = 0, tempBigInt = 0, tempBigIntP = 0, tempBigIntS = 0, tempBigIntR = 0.0, tempBigIntI = 0, tempBigIntD = 0, tempValue = 0, tempDouble = 0.0;
-''' + ''.join(['''
- var tempRet%d = 0;''' % i for i in range(10)]) + '\n' + asm_global_funcs] + [' var tempFloat = %s;\n' % ('Math_fround(0)' if settings.get('PRECISE_F32') else '0.0')] + ['''
-// EMSCRIPTEN_START_FUNCS
-function stackAlloc(size) {
- size = size|0;
- var ret = 0;
- ret = STACKTOP;
- STACKTOP = (STACKTOP + size)|0;
-''' + ('STACKTOP = (STACKTOP + 3)&-4;' if settings['TARGET_X86'] else 'STACKTOP = (STACKTOP + 7)&-8;') + '''
- return ret|0;
-}
-function stackSave() {
- return STACKTOP|0;
-}
-function stackRestore(top) {
- top = top|0;
- STACKTOP = top;
-}
-function setThrew(threw, value) {
- threw = threw|0;
- value = value|0;
- if ((__THREW__|0) == 0) {
- __THREW__ = threw;
- threwValue = value;
+ function stackSave() {
+ return STACKTOP|0;
}
-}
-function copyTempFloat(ptr) {
- ptr = ptr|0;
- HEAP8[tempDoublePtr] = HEAP8[ptr];
- HEAP8[tempDoublePtr+1|0] = HEAP8[ptr+1|0];
- HEAP8[tempDoublePtr+2|0] = HEAP8[ptr+2|0];
- HEAP8[tempDoublePtr+3|0] = HEAP8[ptr+3|0];
-}
-function copyTempDouble(ptr) {
- ptr = ptr|0;
- HEAP8[tempDoublePtr] = HEAP8[ptr];
- HEAP8[tempDoublePtr+1|0] = HEAP8[ptr+1|0];
- HEAP8[tempDoublePtr+2|0] = HEAP8[ptr+2|0];
- HEAP8[tempDoublePtr+3|0] = HEAP8[ptr+3|0];
- HEAP8[tempDoublePtr+4|0] = HEAP8[ptr+4|0];
- HEAP8[tempDoublePtr+5|0] = HEAP8[ptr+5|0];
- HEAP8[tempDoublePtr+6|0] = HEAP8[ptr+6|0];
- HEAP8[tempDoublePtr+7|0] = HEAP8[ptr+7|0];
-}
-''' + ''.join(['''
-function setTempRet%d(value) {
- value = value|0;
- tempRet%d = value;
-}
-''' % (i, i) for i in range(10)])] + funcs_js + ['''
- %s
+ function stackRestore(top) {
+ top = top|0;
+ STACKTOP = top;
+ }
+ function setThrew(threw, value) {
+ threw = threw|0;
+ value = value|0;
+ if ((__THREW__|0) == 0) {
+ __THREW__ = threw;
+ threwValue = value;
+ }
+ }
+ function copyTempFloat(ptr) {
+ ptr = ptr|0;
+ HEAP8[tempDoublePtr>>0] = HEAP8[ptr>>0];
+ HEAP8[tempDoublePtr+1>>0] = HEAP8[ptr+1>>0];
+ HEAP8[tempDoublePtr+2>>0] = HEAP8[ptr+2>>0];
+ HEAP8[tempDoublePtr+3>>0] = HEAP8[ptr+3>>0];
+ }
+ function copyTempDouble(ptr) {
+ ptr = ptr|0;
+ HEAP8[tempDoublePtr>>0] = HEAP8[ptr>>0];
+ HEAP8[tempDoublePtr+1>>0] = HEAP8[ptr+1>>0];
+ HEAP8[tempDoublePtr+2>>0] = HEAP8[ptr+2>>0];
+ HEAP8[tempDoublePtr+3>>0] = HEAP8[ptr+3>>0];
+ HEAP8[tempDoublePtr+4>>0] = HEAP8[ptr+4>>0];
+ HEAP8[tempDoublePtr+5>>0] = HEAP8[ptr+5>>0];
+ HEAP8[tempDoublePtr+6>>0] = HEAP8[ptr+6>>0];
+ HEAP8[tempDoublePtr+7>>0] = HEAP8[ptr+7>>0];
+ }
+ function setTempRet0(value) {
+ value = value|0;
+ tempRet0 = value;
+ }
+ function getTempRet0() {
+ return tempRet0|0;
+ }
+ '''] + funcs_js + ['''
+ %s
- return %s;
-})
-// EMSCRIPTEN_END_ASM
-(%s, %s, buffer);
-%s;
-''' % (pre_tables + '\n'.join(function_tables_impls) + '\n' + function_tables_defs.replace('\n', '\n '), exports, the_global, sending, receiving)]
+ return %s;
+ })
+ // EMSCRIPTEN_END_ASM
+ (%s, %s, buffer);
+ %s;
+ ''' % (pre_tables + '\n'.join(function_tables_impls) + '\n' + function_tables_defs.replace('\n', '\n '), exports, the_global, sending, receiving)]
+
+ if not settings.get('SIDE_MODULE'):
+ funcs_js.append('''
+ Runtime.stackAlloc = asm['stackAlloc'];
+ Runtime.stackSave = asm['stackSave'];
+ Runtime.stackRestore = asm['stackRestore'];
+ Runtime.setTempRet0 = asm['setTempRet0'];
+ Runtime.getTempRet0 = asm['getTempRet0'];
+ ''')
- if not settings.get('SIDE_MODULE'):
- funcs_js.append('''
-Runtime.stackAlloc = function(size) { return asm['stackAlloc'](size) };
-Runtime.stackSave = function() { return asm['stackSave']() };
-Runtime.stackRestore = function(top) { asm['stackRestore'](top) };
-''')
+ # Set function table masks
+ masks = {}
+ max_mask = 0
+ for sig, table in last_forwarded_json['Functions']['tables'].iteritems():
+ mask = table.count(',')
+ masks[sig] = str(mask)
+ max_mask = max(mask, max_mask)
+ def function_table_maskize(js, masks):
+ def fix(m):
+ sig = m.groups(0)[0]
+ return masks[sig]
+ return re.sub(r'{{{ FTM_([\w\d_$]+) }}}', lambda m: fix(m), js) # masks[m.groups(0)[0]]
+ funcs_js = map(lambda js: function_table_maskize(js, masks), funcs_js)
- # Set function table masks
- masks = {}
- max_mask = 0
- for sig, table in last_forwarded_json['Functions']['tables'].iteritems():
- mask = table.count(',')
- masks[sig] = str(mask)
- max_mask = max(mask, max_mask)
- def function_table_maskize(js, masks):
- def fix(m):
- sig = m.groups(0)[0]
- return masks[sig]
- return re.sub(r'{{{ FTM_([\w\d_$]+) }}}', lambda m: fix(m), js) # masks[m.groups(0)[0]]
- funcs_js = map(lambda js: function_table_maskize(js, masks), funcs_js)
+ if settings.get('DLOPEN_SUPPORT'):
+ funcs_js.append('''
+ asm.maxFunctionIndex = %(max_mask)d;
+ DLFCN.registerFunctions(asm, %(max_mask)d+1, %(sigs)s, Module);
+ Module.SYMBOL_TABLE = SYMBOL_TABLE;
+ ''' % { 'max_mask': max_mask, 'sigs': str(map(str, last_forwarded_json['Functions']['tables'].keys())) })
+ else:
+ function_tables_defs = '\n'.join([table for table in last_forwarded_json['Functions']['tables'].itervalues()])
+ outfile.write(function_tables_defs)
+ funcs_js = ['''
+ // EMSCRIPTEN_START_FUNCS
+ '''] + funcs_js + ['''
+ // EMSCRIPTEN_END_FUNCS
+ ''']
+
+ # Create symbol table for self-dlopen
if settings.get('DLOPEN_SUPPORT'):
- funcs_js.append('''
- asm.maxFunctionIndex = %(max_mask)d;
- DLFCN.registerFunctions(asm, %(max_mask)d+1, %(sigs)s, Module);
- Module.SYMBOL_TABLE = SYMBOL_TABLE;
-''' % { 'max_mask': max_mask, 'sigs': str(map(str, last_forwarded_json['Functions']['tables'].keys())) })
-
- else:
- function_tables_defs = '\n'.join([table for table in last_forwarded_json['Functions']['tables'].itervalues()])
- outfile.write(function_tables_defs)
- funcs_js = ['''
-// EMSCRIPTEN_START_FUNCS
-'''] + funcs_js + ['''
-// EMSCRIPTEN_END_FUNCS
-''']
-
- # Create symbol table for self-dlopen
- if settings.get('DLOPEN_SUPPORT'):
- symbol_table = {}
- for k, v in forwarded_json['Variables']['indexedGlobals'].iteritems():
- if forwarded_json['Variables']['globals'][k]['named']:
- symbol_table[k] = str(v + forwarded_json['Runtime']['GLOBAL_BASE'])
- for raw in last_forwarded_json['Functions']['tables'].itervalues():
- if raw == '': continue
- table = map(string.strip, raw[raw.find('[')+1:raw.find(']')].split(","))
- for i in range(len(table)):
- value = table[i]
- if value != '0':
- if settings.get('SIDE_MODULE'):
- symbol_table[value] = 'FUNCTION_TABLE_OFFSET+' + str(i)
- else:
- symbol_table[value] = str(i)
- outfile.write("var SYMBOL_TABLE = %s;" % json.dumps(symbol_table).replace('"', ''))
-
- for i in range(len(funcs_js)): # do this loop carefully to save memory
- outfile.write(funcs_js[i])
- funcs_js = None
-
- outfile.write(post)
-
- outfile.close()
-
- if DEBUG: logging.debug(' emscript: final python processing took %s seconds' % (time.time() - t))
+ symbol_table = {}
+ for k, v in forwarded_json['Variables']['indexedGlobals'].iteritems():
+ if forwarded_json['Variables']['globals'][k]['named']:
+ symbol_table[k] = str(v + forwarded_json['Runtime']['GLOBAL_BASE'])
+ for raw in last_forwarded_json['Functions']['tables'].itervalues():
+ if raw == '': continue
+ table = map(string.strip, raw[raw.find('[')+1:raw.find(']')].split(","))
+ for i in range(len(table)):
+ value = table[i]
+ if value != '0':
+ if settings.get('SIDE_MODULE'):
+ symbol_table[value] = 'FUNCTION_TABLE_OFFSET+' + str(i)
+ else:
+ symbol_table[value] = str(i)
+ outfile.write("var SYMBOL_TABLE = %s;" % json.dumps(symbol_table).replace('"', ''))
+
+ for i in range(len(funcs_js)): # do this loop carefully to save memory
+ outfile.write(funcs_js[i])
+ funcs_js = None
+
+ outfile.write(post)
+
+ outfile.close()
+
+ if DEBUG: logging.debug(' emscript: final python processing took %s seconds' % (time.time() - t))
+
+ success = True
+
+ finally:
+ if not success:
+ outfile.close()
+ shared.try_delete(outfile.name) # remove partial output
if os.environ.get('EMCC_FAST_COMPILER') != '0':
emscript = emscript_fast
diff --git a/src/embind/embind.js b/src/embind/embind.js
index 6ec07cd9..8c8d73ad 100644
--- a/src/embind/embind.js
+++ b/src/embind/embind.js
@@ -1,13 +1,15 @@
-/*global Module*/
+/*global Module, asm*/
/*global _malloc, _free, _memcpy*/
/*global FUNCTION_TABLE, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64*/
/*global readLatin1String*/
/*global __emval_register, _emval_handle_array, __emval_decref*/
/*global ___getTypeName*/
+/*global requireHandle*/
/*jslint sub:true*/ /* The symbols 'fromWireType' and 'toWireType' must be accessed via array notation to be closure-safe since craftInvokerFunction crafts functions as strings that can't be closured. */
var InternalError = Module['InternalError'] = extendError(Error, 'InternalError');
var BindingError = Module['BindingError'] = extendError(Error, 'BindingError');
var UnboundTypeError = Module['UnboundTypeError'] = extendError(BindingError, 'UnboundTypeError');
+var PureVirtualError = Module['PureVirtualError'] = extendError(BindingError, 'PureVirtualError');
function throwInternalError(message) {
throw new InternalError(message);
@@ -151,6 +153,59 @@ function _embind_repr(v) {
}
}
+// raw pointer -> instance
+var registeredInstances = {};
+
+function getBasestPointer(class_, ptr) {
+ if (ptr === undefined) {
+ throwBindingError('ptr should not be undefined');
+ }
+ while (class_.baseClass) {
+ ptr = class_.upcast(ptr);
+ class_ = class_.baseClass;
+ }
+ return ptr;
+}
+
+function registerInheritedInstance(class_, ptr, instance) {
+ ptr = getBasestPointer(class_, ptr);
+ if (registeredInstances.hasOwnProperty(ptr)) {
+ throwBindingError('Tried to register registered instance: ' + ptr);
+ } else {
+ registeredInstances[ptr] = instance;
+ }
+}
+
+function unregisterInheritedInstance(class_, ptr) {
+ ptr = getBasestPointer(class_, ptr);
+ if (registeredInstances.hasOwnProperty(ptr)) {
+ delete registeredInstances[ptr];
+ } else {
+ throwBindingError('Tried to unregister unregistered instance: ' + ptr);
+ }
+}
+
+function getInheritedInstance(class_, ptr) {
+ ptr = getBasestPointer(class_, ptr);
+ return registeredInstances[ptr];
+}
+
+function getInheritedInstanceCount() {
+ return Object.keys(registeredInstances).length;
+}
+Module['getInheritedInstanceCount'] = getInheritedInstanceCount;
+
+function getLiveInheritedInstances() {
+ var rv = [];
+ for (var k in registeredInstances) {
+ if (registeredInstances.hasOwnProperty(k)) {
+ rv.push(registeredInstances[k]);
+ }
+ }
+ return rv;
+}
+Module['getLiveInheritedInstances'] = getLiveInheritedInstances;
+
// typeID -> { toWireType: ..., fromWireType: ... }
var registeredTypes = {};
@@ -535,6 +590,9 @@ function __embind_register_emval(rawType, name) {
'argPackAdvance': 8,
'readValueFromPointer': simpleReadValueFromPointer,
destructorFunction: null, // This type does not need a destructor
+
+ // TODO: do we need a deleteObject here? write a test where
+ // emval is passed into JS via an interface
});
}
@@ -622,10 +680,6 @@ function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cp
var isClassMethodFunc = (argTypes[1] !== null && classType !== null);
- if (!isClassMethodFunc && !FUNCTION_TABLE[cppTargetFunc]) {
- throwBindingError('Global function '+humanName+' is not defined!');
- }
-
// Free functions with signature "void function()" do not need an invoker that marshalls between wire types.
// TODO: This omits argument count check - enable only at -O3 or similar.
// if (ENABLE_UNSAFE_OPTS && argCount == 2 && argTypes[0].name == "void" && !isClassMethodFunc) {
@@ -634,7 +688,7 @@ function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cp
var argsList = "";
var argsListWired = "";
- for(var i = 0; i < argCount-2; ++i) {
+ for(var i = 0; i < argCount - 2; ++i) {
argsList += (i!==0?", ":"")+"arg"+i;
argsListWired += (i!==0?", ":"")+"arg"+i+"Wired";
}
@@ -662,14 +716,14 @@ function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cp
}
var dtorStack = needsDestructorStack ? "destructors" : "null";
- var args1 = ["throwBindingError", "classType", "invoker", "fn", "runDestructors", "retType", "classParam"];
- var args2 = [throwBindingError, classType, cppInvokerFunc, cppTargetFunc, runDestructors, argTypes[0], argTypes[1]];
+ var args1 = ["throwBindingError", "invoker", "fn", "runDestructors", "retType", "classParam"];
+ var args2 = [throwBindingError, cppInvokerFunc, cppTargetFunc, runDestructors, argTypes[0], argTypes[1]];
if (isClassMethodFunc) {
invokerFnBody += "var thisWired = classParam.toWireType("+dtorStack+", this);\n";
}
- for(var i = 0; i < argCount-2; ++i) {
+ for(var i = 0; i < argCount - 2; ++i) {
invokerFnBody += "var arg"+i+"Wired = argType"+i+".toWireType("+dtorStack+", arg"+i+"); // "+argTypes[i+2].name+"\n";
args1.push("argType"+i);
args2.push(argTypes[i+2]);
@@ -688,7 +742,7 @@ function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cp
invokerFnBody += "runDestructors(destructors);\n";
} else {
for(var i = isClassMethodFunc?1:2; i < argTypes.length; ++i) { // Skip return value at index 0 - it's not deleted here. Also skip class type if not a method.
- var paramName = (i === 1 ? "thisWired" : ("arg"+(i-2)+"Wired"));
+ var paramName = (i === 1 ? "thisWired" : ("arg"+(i - 2)+"Wired"));
if (argTypes[i].destructorFunction !== null) {
invokerFnBody += paramName+"_dtor("+paramName+"); // "+argTypes[i].name+"\n";
args1.push(paramName+"_dtor");
@@ -708,10 +762,50 @@ function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cp
return invokerFunction;
}
-function __embind_register_function(name, argCount, rawArgTypesAddr, rawInvoker, fn) {
+function requireFunction(signature, rawFunction) {
+ signature = readLatin1String(signature);
+ var fp;
+ // asm.js does not define FUNCTION_TABLE
+ if (typeof FUNCTION_TABLE === "undefined") {
+ // asm.js does not give direct access to the function tables,
+ // and thus we must go through the dynCall interface which allows
+ // calling into a signature's function table by pointer value.
+ //
+ // https://github.com/dherman/asm.js/issues/83
+ //
+ // This has three main penalties:
+ // - dynCall is another function call in the path from JavaScript to C++.
+ // - JITs may not predict through the function table indirection at runtime.
+ // - Function.prototype.bind generally benchmarks poorly relative to
+ // function objects, but using 'arguments' would confound JITs and
+ // possibly allocate.
+ var dc = asm['dynCall_' + signature];
+ if (dc === undefined) {
+ // We will always enter this branch if the signature
+ // contains 'f' and PRECISE_F32 is not enabled.
+ //
+ // Try again, replacing 'f' with 'd'.
+ dc = asm['dynCall_' + signature.replace(/f/g, 'd')];
+ if (dc === undefined) {
+ throwBindingError("No dynCall invoker for signature: " + signature);
+ }
+ }
+ fp = dc.bind(undefined, rawFunction);
+ } else {
+ fp = FUNCTION_TABLE[rawFunction];
+ }
+
+ if (typeof fp !== "function") {
+ throwBindingError("unknown function pointer with signature " + signature + ": " + rawFunction);
+ }
+ return fp;
+}
+
+function __embind_register_function(name, argCount, rawArgTypesAddr, signature, rawInvoker, fn) {
var argTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
name = readLatin1String(name);
- rawInvoker = FUNCTION_TABLE[rawInvoker];
+
+ rawInvoker = requireFunction(signature, rawInvoker);
exposePublicSymbol(name, function() {
throwUnboundTypeError('Cannot call ' + name + ' due to unbound types', argTypes);
@@ -726,11 +820,11 @@ function __embind_register_function(name, argCount, rawArgTypesAddr, rawInvoker,
var tupleRegistrations = {};
-function __embind_register_value_array(rawType, name, rawConstructor, rawDestructor) {
+function __embind_register_value_array(rawType, name, constructorSignature, rawConstructor, destructorSignature, rawDestructor) {
tupleRegistrations[rawType] = {
name: readLatin1String(name),
- rawConstructor: FUNCTION_TABLE[rawConstructor],
- rawDestructor: FUNCTION_TABLE[rawDestructor],
+ rawConstructor: requireFunction(constructorSignature, rawConstructor),
+ rawDestructor: requireFunction(destructorSignature, rawDestructor),
elements: [],
};
}
@@ -738,18 +832,20 @@ function __embind_register_value_array(rawType, name, rawConstructor, rawDestruc
function __embind_register_value_array_element(
rawTupleType,
getterReturnType,
+ getterSignature,
getter,
getterContext,
setterArgumentType,
+ setterSignature,
setter,
setterContext
) {
tupleRegistrations[rawTupleType].elements.push({
getterReturnType: getterReturnType,
- getter: FUNCTION_TABLE[getter],
+ getter: requireFunction(getterSignature, getter),
getterContext: getterContext,
setterArgumentType: setterArgumentType,
- setter: FUNCTION_TABLE[setter],
+ setter: requireFunction(setterSignature, setter),
setterContext: setterContext,
});
}
@@ -818,13 +914,15 @@ var structRegistrations = {};
function __embind_register_value_object(
rawType,
name,
+ constructorSignature,
rawConstructor,
+ destructorSignature,
rawDestructor
) {
structRegistrations[rawType] = {
name: readLatin1String(name),
- rawConstructor: FUNCTION_TABLE[rawConstructor],
- rawDestructor: FUNCTION_TABLE[rawDestructor],
+ rawConstructor: requireFunction(constructorSignature, rawConstructor),
+ rawDestructor: requireFunction(destructorSignature, rawDestructor),
fields: [],
};
}
@@ -833,19 +931,21 @@ function __embind_register_value_object_field(
structType,
fieldName,
getterReturnType,
+ getterSignature,
getter,
getterContext,
setterArgumentType,
+ setterSignature,
setter,
setterContext
) {
structRegistrations[structType].fields.push({
fieldName: readLatin1String(fieldName),
getterReturnType: getterReturnType,
- getter: FUNCTION_TABLE[getter],
+ getter: requireFunction(getterSignature, getter),
getterContext: getterContext,
setterArgumentType: setterArgumentType,
- setter: FUNCTION_TABLE[setter],
+ setter: requireFunction(setterSignature, setter),
setterContext: setterContext,
});
}
@@ -1082,14 +1182,14 @@ function RegisteredPointer(
}
}
-RegisteredPointer.prototype.getPointee = function(ptr) {
+RegisteredPointer.prototype.getPointee = function getPointee(ptr) {
if (this.rawGetPointee) {
ptr = this.rawGetPointee(ptr);
}
return ptr;
};
-RegisteredPointer.prototype.destructor = function(ptr) {
+RegisteredPointer.prototype.destructor = function destructor(ptr) {
if (this.rawDestructor) {
this.rawDestructor(ptr);
}
@@ -1098,7 +1198,13 @@ RegisteredPointer.prototype.destructor = function(ptr) {
RegisteredPointer.prototype['argPackAdvance'] = 8;
RegisteredPointer.prototype['readValueFromPointer'] = simpleReadValueFromPointer;
-RegisteredPointer.prototype['fromWireType'] = function(ptr) {
+RegisteredPointer.prototype['deleteObject'] = function deleteObject(handle) {
+ if (handle !== null) {
+ handle['delete']();
+ }
+};
+
+RegisteredPointer.prototype['fromWireType'] = function fromWireType(ptr) {
// ptr is a raw pointer (or a raw smartpointer)
// rawPointer is a maybe-null raw pointer
@@ -1108,6 +1214,22 @@ RegisteredPointer.prototype['fromWireType'] = function(ptr) {
return null;
}
+ var registeredInstance = getInheritedInstance(this.registeredClass, rawPointer);
+ if (undefined !== registeredInstance) {
+ // JS object has been neutered, time to repopulate it
+ if (0 === registeredInstance.$$.count.value) {
+ registeredInstance.$$.ptr = rawPointer;
+ registeredInstance.$$.smartPtr = ptr;
+ return registeredInstance['clone']();
+ } else {
+ // else, just increment reference count on existing object
+ // it already has a reference to the smart pointer
+ var rv = registeredInstance['clone']();
+ this.destructor(ptr);
+ return rv;
+ }
+ }
+
function makeDefaultHandle() {
if (this.isSmartPointer) {
return makeClassHandle(this.registeredClass.instancePrototype, {
@@ -1183,7 +1305,7 @@ function getInstanceTypeName(handle) {
return handle.$$.ptrType.registeredClass.name;
}
-ClassHandle.prototype['isAliasOf'] = function(other) {
+ClassHandle.prototype['isAliasOf'] = function isAliasOf(other) {
if (!(this instanceof ClassHandle)) {
return false;
}
@@ -1213,19 +1335,24 @@ function throwInstanceAlreadyDeleted(obj) {
throwBindingError(getInstanceTypeName(obj) + ' instance already deleted');
}
-ClassHandle.prototype['clone'] = function() {
+ClassHandle.prototype['clone'] = function clone() {
if (!this.$$.ptr) {
throwInstanceAlreadyDeleted(this);
}
- var clone = Object.create(Object.getPrototypeOf(this), {
- $$: {
- value: shallowCopy(this.$$),
- }
- });
+ if (this.$$.preservePointerOnDelete) {
+ this.$$.count.value += 1;
+ return this;
+ } else {
+ var clone = Object.create(Object.getPrototypeOf(this), {
+ $$: {
+ value: shallowCopy(this.$$),
+ }
+ });
- clone.$$.count.value += 1;
- return clone;
+ clone.$$.count.value += 1;
+ return clone;
+ }
};
function runDestructor(handle) {
@@ -1241,16 +1368,20 @@ ClassHandle.prototype['delete'] = function ClassHandle_delete() {
if (!this.$$.ptr) {
throwInstanceAlreadyDeleted(this);
}
- if (this.$$.deleteScheduled) {
+
+ if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) {
throwBindingError('Object already scheduled for deletion');
}
this.$$.count.value -= 1;
- if (0 === this.$$.count.value) {
+ var toDelete = 0 === this.$$.count.value;
+ if (toDelete) {
runDestructor(this);
}
- this.$$.smartPtr = undefined;
- this.$$.ptr = undefined;
+ if (!this.$$.preservePointerOnDelete) {
+ this.$$.smartPtr = undefined;
+ this.$$.ptr = undefined;
+ }
};
var deletionQueue = [];
@@ -1263,7 +1394,7 @@ ClassHandle.prototype['deleteLater'] = function deleteLater() {
if (!this.$$.ptr) {
throwInstanceAlreadyDeleted(this);
}
- if (this.$$.deleteScheduled) {
+ if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) {
throwBindingError('Object already scheduled for deletion');
}
deletionQueue.push(this);
@@ -1309,12 +1440,15 @@ function RegisteredClass(
this.getActualType = getActualType;
this.upcast = upcast;
this.downcast = downcast;
+ this.pureVirtualFunctions = [];
}
function shallowCopy(o) {
var rv = {};
for (var k in o) {
- rv[k] = o[k];
+ if (Object.prototype.hasOwnProperty.call(o, k)) {
+ rv[k] = o[k];
+ }
}
return rv;
}
@@ -1324,17 +1458,25 @@ function __embind_register_class(
rawPointerType,
rawConstPointerType,
baseClassRawType,
+ getActualTypeSignature,
getActualType,
+ upcastSignature,
upcast,
+ downcastSignature,
downcast,
name,
+ destructorSignature,
rawDestructor
) {
name = readLatin1String(name);
- rawDestructor = FUNCTION_TABLE[rawDestructor];
- getActualType = FUNCTION_TABLE[getActualType];
- upcast = FUNCTION_TABLE[upcast];
- downcast = FUNCTION_TABLE[downcast];
+ getActualType = requireFunction(getActualTypeSignature, getActualType);
+ if (upcast) {
+ upcast = requireFunction(upcastSignature, upcast);
+ }
+ if (downcast) {
+ downcast = requireFunction(downcastSignature, downcast);
+ }
+ rawDestructor = requireFunction(destructorSignature, rawDestructor);
var legalFunctionName = makeLegalFunctionName(name);
exposePublicSymbol(legalFunctionName, function() {
@@ -1424,11 +1566,12 @@ function __embind_register_class_constructor(
rawClassType,
argCount,
rawArgTypesAddr,
+ invokerSignature,
invoker,
rawConstructor
) {
var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
- invoker = FUNCTION_TABLE[invoker];
+ invoker = requireFunction(invokerSignature, invoker);
whenDependentTypesAreResolved([], [rawClassType], function(classType) {
classType = classType[0];
@@ -1440,12 +1583,12 @@ function __embind_register_class_constructor(
if (undefined !== classType.registeredClass.constructor_body[argCount - 1]) {
throw new BindingError("Cannot register multiple constructors with identical number of parameters (" + (argCount-1) + ") for class '" + classType.name + "'! Overload resolution is currently only performed using the parameter count, not actual type info!");
}
- classType.registeredClass.constructor_body[argCount - 1] = function() {
+ classType.registeredClass.constructor_body[argCount - 1] = function unboundTypeHandler() {
throwUnboundTypeError('Cannot construct ' + classType.name + ' due to unbound types', rawArgTypes);
};
whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) {
- classType.registeredClass.constructor_body[argCount - 1] = function() {
+ classType.registeredClass.constructor_body[argCount - 1] = function constructor_body() {
if (arguments.length !== argCount - 1) {
throwBindingError(humanName + ' called with ' + arguments.length + ' arguments, expected ' + (argCount-1));
}
@@ -1474,9 +1617,12 @@ function downcastPointer(ptr, ptrClass, desiredClass) {
if (undefined === desiredClass.baseClass) {
return null; // no conversion
}
- // O(depth) stack space used
- return desiredClass.downcast(
- downcastPointer(ptr, ptrClass, desiredClass.baseClass));
+
+ var rv = downcastPointer(ptr, ptrClass, desiredClass.baseClass);
+ if (rv === null) {
+ return null;
+ }
+ return desiredClass.downcast(rv);
}
function upcastPointer(ptr, ptrClass, desiredClass) {
@@ -1513,32 +1659,38 @@ function __embind_register_class_function(
methodName,
argCount,
rawArgTypesAddr, // [ReturnType, ThisType, Args...]
+ invokerSignature,
rawInvoker,
- context
+ context,
+ isPureVirtual
) {
var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
methodName = readLatin1String(methodName);
- rawInvoker = FUNCTION_TABLE[rawInvoker];
+ rawInvoker = requireFunction(invokerSignature, rawInvoker);
whenDependentTypesAreResolved([], [rawClassType], function(classType) {
classType = classType[0];
var humanName = classType.name + '.' + methodName;
- var unboundTypesHandler = function() {
+ if (isPureVirtual) {
+ classType.registeredClass.pureVirtualFunctions.push(methodName);
+ }
+
+ function unboundTypesHandler() {
throwUnboundTypeError('Cannot call ' + humanName + ' due to unbound types', rawArgTypes);
- };
+ }
var proto = classType.registeredClass.instancePrototype;
var method = proto[methodName];
- if (undefined === method || (undefined === method.overloadTable && method.className !== classType.name && method.argCount === argCount-2)) {
+ if (undefined === method || (undefined === method.overloadTable && method.className !== classType.name && method.argCount === argCount - 2)) {
// This is the first overload to be registered, OR we are replacing a function in the base class with a function in the derived class.
- unboundTypesHandler.argCount = argCount-2;
+ unboundTypesHandler.argCount = argCount - 2;
unboundTypesHandler.className = classType.name;
proto[methodName] = unboundTypesHandler;
} else {
// There was an existing function with the same name registered. Set up a function overload routing table.
ensureOverloadTable(proto, methodName, humanName);
- proto[methodName].overloadTable[argCount-2] = unboundTypesHandler;
+ proto[methodName].overloadTable[argCount - 2] = unboundTypesHandler;
}
whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) {
@@ -1550,7 +1702,7 @@ function __embind_register_class_function(
if (undefined === proto[methodName].overloadTable) {
proto[methodName] = memberFunction;
} else {
- proto[methodName].overloadTable[argCount-2] = memberFunction;
+ proto[methodName].overloadTable[argCount - 2] = memberFunction;
}
return [];
@@ -1559,64 +1711,20 @@ function __embind_register_class_function(
});
}
-function __embind_register_class_class_function(
- rawClassType,
- methodName,
- argCount,
- rawArgTypesAddr,
- rawInvoker,
- fn
-) {
- var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
- methodName = readLatin1String(methodName);
- rawInvoker = FUNCTION_TABLE[rawInvoker];
- whenDependentTypesAreResolved([], [rawClassType], function(classType) {
- classType = classType[0];
- var humanName = classType.name + '.' + methodName;
-
- var unboundTypesHandler = function() {
- throwUnboundTypeError('Cannot call ' + humanName + ' due to unbound types', rawArgTypes);
- };
-
- var proto = classType.registeredClass.constructor;
- if (undefined === proto[methodName]) {
- // This is the first function to be registered with this name.
- unboundTypesHandler.argCount = argCount-1;
- proto[methodName] = unboundTypesHandler;
- } else {
- // There was an existing function with the same name registered. Set up a function overload routing table.
- ensureOverloadTable(proto, methodName, humanName);
- proto[methodName].overloadTable[argCount-1] = unboundTypesHandler;
- }
-
- whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) {
- // Replace the initial unbound-types-handler stub with the proper function. If multiple overloads are registered,
- // the function handlers go into an overload table.
- var invokerArgsArray = [argTypes[0] /* return value */, null /* no class 'this'*/].concat(argTypes.slice(1) /* actual params */);
- var func = craftInvokerFunction(humanName, invokerArgsArray, null /* no class 'this'*/, rawInvoker, fn);
- if (undefined === proto[methodName].overloadTable) {
- proto[methodName] = func;
- } else {
- proto[methodName].overloadTable[argCount-1] = func;
- }
- return [];
- });
- return [];
- });
-}
-
function __embind_register_class_property(
classType,
fieldName,
getterReturnType,
+ getterSignature,
getter,
getterContext,
setterArgumentType,
+ setterSignature,
setter,
setterContext
) {
fieldName = readLatin1String(fieldName);
- getter = FUNCTION_TABLE[getter];
+ getter = requireFunction(getterSignature, getter);
whenDependentTypesAreResolved([], [classType], function(classType) {
classType = classType[0];
@@ -1654,7 +1762,7 @@ function __embind_register_class_property(
};
if (setter) {
- setter = FUNCTION_TABLE[setter];
+ setter = requireFunction(setterSignature, setter);
var setterArgumentType = types[1];
desc.set = function(v) {
var ptr = validateThis(this, classType, humanName + ' setter');
@@ -1672,6 +1780,112 @@ function __embind_register_class_property(
});
}
+function __embind_register_class_class_function(
+ rawClassType,
+ methodName,
+ argCount,
+ rawArgTypesAddr,
+ invokerSignature,
+ rawInvoker,
+ fn
+) {
+ var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
+ methodName = readLatin1String(methodName);
+ rawInvoker = requireFunction(invokerSignature, rawInvoker);
+ whenDependentTypesAreResolved([], [rawClassType], function(classType) {
+ classType = classType[0];
+ var humanName = classType.name + '.' + methodName;
+
+ function unboundTypesHandler() {
+ throwUnboundTypeError('Cannot call ' + humanName + ' due to unbound types', rawArgTypes);
+ }
+
+ var proto = classType.registeredClass.constructor;
+ if (undefined === proto[methodName]) {
+ // This is the first function to be registered with this name.
+ unboundTypesHandler.argCount = argCount-1;
+ proto[methodName] = unboundTypesHandler;
+ } else {
+ // There was an existing function with the same name registered. Set up a function overload routing table.
+ ensureOverloadTable(proto, methodName, humanName);
+ proto[methodName].overloadTable[argCount-1] = unboundTypesHandler;
+ }
+
+ whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) {
+ // Replace the initial unbound-types-handler stub with the proper function. If multiple overloads are registered,
+ // the function handlers go into an overload table.
+ var invokerArgsArray = [argTypes[0] /* return value */, null /* no class 'this'*/].concat(argTypes.slice(1) /* actual params */);
+ var func = craftInvokerFunction(humanName, invokerArgsArray, null /* no class 'this'*/, rawInvoker, fn);
+ if (undefined === proto[methodName].overloadTable) {
+ proto[methodName] = func;
+ } else {
+ proto[methodName].overloadTable[argCount-1] = func;
+ }
+ return [];
+ });
+ return [];
+ });
+}
+
+function __embind_create_inheriting_constructor(constructorName, wrapperType, properties) {
+ constructorName = readLatin1String(constructorName);
+ wrapperType = requireRegisteredType(wrapperType, 'wrapper');
+ properties = requireHandle(properties);
+
+ var arraySlice = [].slice;
+
+ var registeredClass = wrapperType.registeredClass;
+ var wrapperPrototype = registeredClass.instancePrototype;
+ var baseClass = registeredClass.baseClass;
+ var baseClassPrototype = baseClass.instancePrototype;
+ var baseConstructor = registeredClass.baseClass.constructor;
+ var ctor = createNamedFunction(constructorName, function() {
+ registeredClass.baseClass.pureVirtualFunctions.forEach(function(name) {
+ if (this[name] === baseClassPrototype[name]) {
+ throw new PureVirtualError('Pure virtual function ' + name + ' must be implemented in JavaScript');
+ }
+ }.bind(this));
+
+ Object.defineProperty(this, '__parent', {
+ value: wrapperPrototype
+ });
+ this.__construct.apply(this, arraySlice.call(arguments));
+ });
+
+ // It's a little nasty that we're modifying the wrapper prototype here.
+
+ wrapperPrototype.__construct = function __construct() {
+ if (this === wrapperPrototype) {
+ throwBindingError("Pass correct 'this' to __construct");
+ }
+
+ var inner = baseConstructor.implement.apply(
+ undefined,
+ [this].concat(arraySlice.call(arguments)));
+ var $$ = inner.$$;
+ inner.notifyOnDestruction();
+ $$.preservePointerOnDelete = true;
+ Object.defineProperty(this, '$$', {
+ value: $$
+ });
+ registerInheritedInstance(registeredClass, $$.ptr, this);
+ };
+
+ wrapperPrototype.__destruct = function __destruct() {
+ if (this === wrapperPrototype) {
+ throwBindingError("Pass correct 'this' to __destruct");
+ }
+
+ unregisterInheritedInstance(registeredClass, this.$$.ptr);
+ };
+
+ ctor.prototype = Object.create(wrapperPrototype);
+ for (var p in properties) {
+ ctor.prototype[p] = properties[p];
+ }
+ return __emval_register(ctor);
+}
+
var char_0 = '0'.charCodeAt(0);
var char_9 = '9'.charCodeAt(0);
function makeLegalFunctionName(name) {
@@ -1689,16 +1903,20 @@ function __embind_register_smart_ptr(
rawPointeeType,
name,
sharingPolicy,
+ getPointeeSignature,
rawGetPointee,
+ constructorSignature,
rawConstructor,
+ shareSignature,
rawShare,
+ destructorSignature,
rawDestructor
) {
name = readLatin1String(name);
- rawGetPointee = FUNCTION_TABLE[rawGetPointee];
- rawConstructor = FUNCTION_TABLE[rawConstructor];
- rawShare = FUNCTION_TABLE[rawShare];
- rawDestructor = FUNCTION_TABLE[rawDestructor];
+ rawGetPointee = requireFunction(getPointeeSignature, rawGetPointee);
+ rawConstructor = requireFunction(constructorSignature, rawConstructor);
+ rawShare = requireFunction(shareSignature, rawShare);
+ rawDestructor = requireFunction(destructorSignature, rawDestructor);
whenDependentTypesAreResolved([rawType], [rawPointeeType], function(pointeeType) {
pointeeType = pointeeType[0];
diff --git a/src/embind/emval.js b/src/embind/emval.js
index 4007701a..1661bc02 100644
--- a/src/embind/emval.js
+++ b/src/embind/emval.js
@@ -265,7 +265,14 @@ function __emval_get_method_caller(argCount, argTypes) {
" args += argType" + i + ".argPackAdvance;\n";
}
functionBody +=
- " var rv = handle[name](" + argsList + ");\n" +
+ " var rv = handle[name](" + argsList + ");\n";
+ for (var i = 0; i < argCount - 1; ++i) {
+ if (types[i + 1]['deleteObject']) {
+ functionBody +=
+ " argType" + i + ".deleteObject(arg" + i + ");\n";
+ }
+ }
+ functionBody +=
" return retType.toWireType(destructors, rv);\n" +
"};\n";
@@ -281,8 +288,16 @@ function __emval_call_method(caller, handle, methodName, destructorsRef, args) {
return caller(handle, methodName, allocateDestructors(destructorsRef), args);
}
-function __emval_has_function(handle, name) {
+function __emval_has_function(handle, name, classType) {
handle = requireHandle(handle);
name = getStringOrSymbol(name);
- return handle[name] instanceof Function;
+ classType = requireRegisteredType(classType, 'class wrapper filter');
+
+ var filter = classType.registeredClass.instancePrototype[name];
+ return (handle[name] instanceof Function) && (filter === undefined || handle[name] !== filter);
+}
+
+function __emval_typeof(handle) {
+ handle = requireHandle(handle);
+ return __emval_register(typeof handle);
}
diff --git a/src/emscripten-source-map.min.js b/src/emscripten-source-map.min.js
index 9151400f..44cb1d84 100644
--- a/src/emscripten-source-map.min.js
+++ b/src/emscripten-source-map.min.js
@@ -4,7 +4,7 @@ var emscripten_sourcemap_xmlHttp = undefined;
function emscripten_sourceMapLoaded() {
if (emscripten_sourcemap_xmlHttp.readyState === 4) {
Module['removeRunDependency']('sourcemap');
- if (emscripten_sourcemap_xmlHttp.status === 200) {
+ if (emscripten_sourcemap_xmlHttp.status === 200 || emscripten_sourcemap_xmlHttp.status === 0) {
emscripten_source_map = new window.sourceMap.SourceMapConsumer(emscripten_sourcemap_xmlHttp.responseText);
console.log('Source map data loaded.');
} else {
@@ -20,6 +20,7 @@ function emscripten_loadSourceMap() {
emscripten_sourcemap_xmlHttp = new XMLHttpRequest();
emscripten_sourcemap_xmlHttp.onreadystatechange = emscripten_sourceMapLoaded;
emscripten_sourcemap_xmlHttp.open("GET", url, true);
+ emscripten_sourcemap_xmlHttp.responseType = "text";
emscripten_sourcemap_xmlHttp.send(null);
}
diff --git a/src/jsifier.js b/src/jsifier.js
index 065c66a8..791273f4 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -1321,10 +1321,10 @@ function JSify(data, functionsOnly) {
// vector load
var native = getVectorNativeType(item.valueType);
var base = getSIMDName(native);
- return base + '32x4(' + makeGetValue(value, 0, native, 0, item.unsigned, 0, item.align) + ',' +
- makeGetValue(value, 4, native, 0, item.unsigned, 0, item.align) + ',' +
- makeGetValue(value, 8, native, 0, item.unsigned, 0, item.align) + ',' +
- makeGetValue(value, 12, native, 0, item.unsigned, 0, item.align) + ');';
+ return 'SIMD.' + base + '32x4(' + makeGetValue(value, 0, native, 0, item.unsigned, 0, item.align) + ',' +
+ makeGetValue(value, 4, native, 0, item.unsigned, 0, item.align) + ',' +
+ makeGetValue(value, 8, native, 0, item.unsigned, 0, item.align) + ',' +
+ makeGetValue(value, 12, native, 0, item.unsigned, 0, item.align) + ');';
}
var impl = item.ident ? getVarImpl(item.funcData, item.ident) : VAR_EMULATED;
switch (impl) {
@@ -1395,7 +1395,7 @@ function JSify(data, functionsOnly) {
}
for (var i = 0; i < 4; i++) assert(mask[0] == 0 || mask == 1);
i = 0;
- return base + '32x4(' + mask.map(function(m) {
+ return 'SIMD.' + base + '32x4(' + mask.map(function(m) {
return (m == 1 ? second : first) + '.' + simdLane[i++];
}).join(',') + ')';
}
diff --git a/src/library.js b/src/library.js
index 1d5a9140..c17952b3 100644
--- a/src/library.js
+++ b/src/library.js
@@ -762,12 +762,18 @@ LibraryManager.library = {
// http://pubs.opengroup.org/onlinepubs/000095399/functions/crypt.html
// TODO: Implement (probably compile from C).
___setErrNo(ERRNO_CODES.ENOSYS);
+#if ASSERTIONS
+ Runtime.warnOnce('crypt() returning an error as we do not support it');
+#endif
return 0;
},
encrypt: function(block, edflag) {
// void encrypt(char block[64], int edflag);
// http://pubs.opengroup.org/onlinepubs/000095399/functions/encrypt.html
// TODO: Implement (probably compile from C).
+#if ASSERTIONS
+ Runtime.warnOnce('encrypt() returning an error as we do not support it');
+#endif
___setErrNo(ERRNO_CODES.ENOSYS);
},
fpathconf__deps: ['__setErrNo', '$ERRNO_CODES'],
@@ -940,6 +946,9 @@ LibraryManager.library = {
// It is possible to implement this using two device streams, but pipes make
// little sense in a single-threaded environment, so we do not support them.
___setErrNo(ERRNO_CODES.ENOSYS);
+#if ASSERTIONS
+ Runtime.warnOnce('pipe() returning an error as we do not support them');
+#endif
return -1;
},
pread__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'],
@@ -1584,7 +1593,6 @@ LibraryManager.library = {
return /^[+-]?[0-9]*\.?[0-9]+([eE][+-]?[0-9]+)?/.exec(text);
},
- // TODO: Document.
_scanString__deps: ['_getFloat'],
_scanString: function(format, get, unget, varargs) {
if (!__scanString.whiteSpace) {
@@ -1726,6 +1734,7 @@ LibraryManager.library = {
}
var long_ = false;
var half = false;
+ var quarter = false;
var longLong = false;
if (format[formatIndex] == 'l') {
long_ = true;
@@ -1737,6 +1746,10 @@ LibraryManager.library = {
} else if (format[formatIndex] == 'h') {
half = true;
formatIndex++;
+ if (format[formatIndex] == 'h') {
+ quarter = true;
+ formatIndex++;
+ }
}
var type = format[formatIndex];
formatIndex++;
@@ -1795,20 +1808,21 @@ LibraryManager.library = {
var text = buffer.join('');
var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}};
argIndex += Runtime.getAlignSize('void*', null, true);
+ var base = 10;
switch (type) {
+ case 'X': case 'x':
+ base = 16;
case 'd': case 'u': case 'i':
- if (half) {
- {{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i16') }}};
+ if (quarter) {
+ {{{ makeSetValue('argPtr', 0, 'parseInt(text, base)', 'i8') }}};
+ } else if (half) {
+ {{{ makeSetValue('argPtr', 0, 'parseInt(text, base)', 'i16') }}};
} else if (longLong) {
- {{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i64') }}};
+ {{{ makeSetValue('argPtr', 0, 'parseInt(text, base)', 'i64') }}};
} else {
- {{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i32') }}};
+ {{{ makeSetValue('argPtr', 0, 'parseInt(text, base)', 'i32') }}};
}
break;
- case 'X':
- case 'x':
- {{{ makeSetValue('argPtr', 0, 'parseInt(text, 16)', 'i32') }}};
- break;
case 'F':
case 'f':
case 'E':
@@ -2788,34 +2802,6 @@ LibraryManager.library = {
var stdin = {{{ makeGetValue(makeGlobalUse('_stdin'), '0', 'void*') }}};
return _fscanf(stdin, format, varargs);
},
- sscanf__deps: ['_scanString'],
- sscanf: function(s, format, varargs) {
- // int sscanf(const char *restrict s, const char *restrict format, ... );
- // http://pubs.opengroup.org/onlinepubs/000095399/functions/scanf.html
- var index = 0;
- function get() { return {{{ makeGetValue('s', 'index++', 'i8') }}}; };
- function unget() { index--; };
- return __scanString(format, get, unget, varargs);
- },
- snprintf__deps: ['_formatString', 'malloc'],
- snprintf: function(s, n, format, varargs) {
- // int snprintf(char *restrict s, size_t n, const char *restrict format, ...);
- // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html
- var result = __formatString(format, varargs);
- var limit = (n === undefined) ? result.length
- : Math.min(result.length, Math.max(n - 1, 0));
- if (s < 0) {
- s = -s;
- var buf = _malloc(limit+1);
- {{{ makeSetValue('s', '0', 'buf', 'i8*') }}};
- s = buf;
- }
- for (var i = 0; i < limit; i++) {
- {{{ makeSetValue('s', 'i', 'result[i]', 'i8') }}};
- }
- if (limit < n || (n === undefined)) {{{ makeSetValue('s', 'i', '0', 'i8') }}};
- return result.length;
- },
fprintf__deps: ['fwrite', '_formatString'],
fprintf: function(stream, format, varargs) {
// int fprintf(FILE *restrict stream, const char *restrict format, ...);
@@ -2833,16 +2819,6 @@ LibraryManager.library = {
var stdout = {{{ makeGetValue(makeGlobalUse('_stdout'), '0', 'void*') }}};
return _fprintf(stdout, format, varargs);
},
- sprintf__deps: ['snprintf'],
- sprintf: function(s, format, varargs) {
- // int sprintf(char *restrict s, const char *restrict format, ...);
- // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html
- return _snprintf(s, undefined, format, varargs);
- },
- asprintf__deps: ['sprintf'],
- asprintf: function(s, format, varargs) {
- return _sprintf(-s, format, varargs);
- },
dprintf__deps: ['_formatString', 'write'],
dprintf: function(fd, format, varargs) {
var result = __formatString(format, varargs);
@@ -2854,14 +2830,10 @@ LibraryManager.library = {
#if TARGET_X86
// va_arg is just like our varargs
vfprintf: 'fprintf',
- vsnprintf: 'snprintf',
vprintf: 'printf',
- vsprintf: 'sprintf',
- vasprintf: 'asprintf',
vdprintf: 'dprintf',
vscanf: 'scanf',
vfscanf: 'fscanf',
- vsscanf: 'sscanf',
#endif
#if TARGET_ASMJS_UNKNOWN_EMSCRIPTEN
@@ -2870,22 +2842,10 @@ LibraryManager.library = {
vfprintf: function(s, f, va_arg) {
return _fprintf(s, f, {{{ makeGetValue('va_arg', 0, '*') }}});
},
- vsnprintf__deps: ['snprintf'],
- vsnprintf: function(s, n, format, va_arg) {
- return _snprintf(s, n, format, {{{ makeGetValue('va_arg', 0, '*') }}});
- },
vprintf__deps: ['printf'],
vprintf: function(format, va_arg) {
return _printf(format, {{{ makeGetValue('va_arg', 0, '*') }}});
},
- vsprintf__deps: ['sprintf'],
- vsprintf: function(s, format, va_arg) {
- return _sprintf(s, format, {{{ makeGetValue('va_arg', 0, '*') }}});
- },
- vasprintf__deps: ['asprintf'],
- vasprintf: function(s, format, va_arg) {
- return _asprintf(s, format, {{{ makeGetValue('va_arg', 0, '*') }}});
- },
vdprintf__deps: ['dprintf'],
vdprintf: function (fd, format, va_arg) {
return _dprintf(fd, format, {{{ makeGetValue('va_arg', 0, '*') }}});
@@ -2898,10 +2858,6 @@ LibraryManager.library = {
vfscanf: function(s, format, va_arg) {
return _fscanf(s, format, {{{ makeGetValue('va_arg', 0, '*') }}});
},
- vsscanf__deps: ['sscanf'],
- vsscanf: function(s, format, va_arg) {
- return _sscanf(s, format, {{{ makeGetValue('va_arg', 0, '*') }}});
- },
#endif
// ==========================================================================
@@ -3208,39 +3164,6 @@ LibraryManager.library = {
{{{ makeStructuralReturn([makeGetTempDouble(0, 'i32'), makeGetTempDouble(1, 'i32')]) }}};
},
#endif
- strtoll__deps: ['_parseInt64'],
- strtoll: function(str, endptr, base) {
- return __parseInt64(str, endptr, base, '-9223372036854775808', '9223372036854775807'); // LLONG_MIN, LLONG_MAX.
- },
- strtoll_l__deps: ['strtoll'],
- strtoll_l: function(str, endptr, base) {
- return _strtoll(str, endptr, base); // no locale support yet
- },
- strtol__deps: ['_parseInt'],
- strtol: function(str, endptr, base) {
- return __parseInt(str, endptr, base, -2147483648, 2147483647, 32); // LONG_MIN, LONG_MAX.
- },
- strtol_l__deps: ['strtol'],
- strtol_l: function(str, endptr, base) {
- return _strtol(str, endptr, base); // no locale support yet
- },
- strtoul__deps: ['_parseInt'],
- strtoul: function(str, endptr, base) {
- return __parseInt(str, endptr, base, 0, 4294967295, 32, true); // ULONG_MAX.
- },
- strtoul_l__deps: ['strtoul'],
- strtoul_l: function(str, endptr, base) {
- return _strtoul(str, endptr, base); // no locale support yet
- },
- strtoull__deps: ['_parseInt64'],
- strtoull: function(str, endptr, base) {
- return __parseInt64(str, endptr, base, 0, '18446744073709551615', true); // ULONG_MAX.
- },
- strtoull_l__deps: ['strtoull'],
- strtoull_l: function(str, endptr, base) {
- return _strtoull(str, endptr, base); // no locale support yet
- },
-
environ: 'allocate(1, "i32*", ALLOC_STATIC)',
__environ__deps: ['environ'],
__environ: '_environ',
@@ -3430,6 +3353,7 @@ LibraryManager.library = {
return 0;
} else {
var size = Math.min(4095, absolute.path.length); // PATH_MAX - 1.
+ if (resolved_name === 0) resolved_name = _malloc(size+1);
for (var i = 0; i < size; i++) {
{{{ makeSetValue('resolved_name', 'i', 'absolute.path.charCodeAt(i)', 'i8') }}};
}
@@ -3605,28 +3529,6 @@ 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;
- {{{ 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;
- {{{ makeSetValue('pstr', 'i', '_toupper(x)', 'i8') }}};
- i++;
- }
- },
-
strcat__asm: true,
strcat__sig: 'iii',
strcat__deps: ['strlen'],
@@ -3667,132 +3569,6 @@ LibraryManager.library = {
// ctype.h
// ==========================================================================
- isascii: function(chr) {
- return chr >= 0 && (chr & 0x80) == 0;
- },
- toascii: function(chr) {
- return chr & 0x7F;
- },
- toupper: function(chr) {
- if (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) {
- return chr - {{{ charCode('a') }}} + {{{ charCode('A') }}};
- } else {
- return chr;
- }
- },
- _toupper: 'toupper',
- toupper_l__deps: ['toupper'],
- toupper_l: function(str, endptr, base) {
- return _toupper(str, endptr, base); // no locale support yet
- },
-
- tolower__asm: true,
- tolower__sig: 'ii',
- tolower: function(chr) {
- chr = chr|0;
- if ((chr|0) < {{{ charCode('A') }}}) return chr|0;
- if ((chr|0) > {{{ charCode('Z') }}}) return chr|0;
- return (chr - {{{ charCode('A') }}} + {{{ charCode('a') }}})|0;
- },
- _tolower: 'tolower',
- tolower_l__deps: ['tolower'],
- tolower_l: function(chr) {
- return _tolower(chr); // no locale support yet
- },
-
- // The following functions are defined as macros in glibc.
- islower: function(chr) {
- return chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}};
- },
- islower_l__deps: ['islower'],
- islower_l: function(chr) {
- return _islower(chr); // no locale support yet
- },
- isupper: function(chr) {
- return chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}};
- },
- isupper_l__deps: ['isupper'],
- isupper_l: function(chr) {
- return _isupper(chr); // no locale support yet
- },
- isalpha: function(chr) {
- return (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) ||
- (chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}});
- },
- isalpha_l__deps: ['isalpha'],
- isalpha_l: function(chr) {
- return _isalpha(chr); // no locale support yet
- },
- isdigit: function(chr) {
- return chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}};
- },
- isdigit_l__deps: ['isdigit'],
- isdigit_l: function(chr) {
- return _isdigit(chr); // no locale support yet
- },
- isxdigit: function(chr) {
- return (chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}) ||
- (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('f') }}}) ||
- (chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('F') }}});
- },
- isxdigit_l__deps: ['isxdigit'],
- isxdigit_l: function(chr) {
- return _isxdigit(chr); // no locale support yet
- },
- isalnum: function(chr) {
- return (chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}) ||
- (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) ||
- (chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}});
- },
- isalnum_l__deps: ['isalnum'],
- isalnum_l: function(chr) {
- return _isalnum(chr); // no locale support yet
- },
- ispunct: function(chr) {
- return (chr >= {{{ charCode('!') }}} && chr <= {{{ charCode('/') }}}) ||
- (chr >= {{{ charCode(':') }}} && chr <= {{{ charCode('@') }}}) ||
- (chr >= {{{ charCode('[') }}} && chr <= {{{ charCode('`') }}}) ||
- (chr >= {{{ charCode('{') }}} && chr <= {{{ charCode('~') }}});
- },
- ispunct_l__deps: ['ispunct'],
- ispunct_l: function(chr) {
- return _ispunct(chr); // no locale support yet
- },
- isspace: function(chr) {
- return (chr == 32) || (chr >= 9 && chr <= 13);
- },
- isspace_l__deps: ['isspace'],
- isspace_l: function(chr) {
- return _isspace(chr); // no locale support yet
- },
- isblank: function(chr) {
- return chr == {{{ charCode(' ') }}} || chr == {{{ charCode('\t') }}};
- },
- isblank_l__deps: ['isblank'],
- isblank_l: function(chr) {
- return _isblank(chr); // no locale support yet
- },
- iscntrl: function(chr) {
- return (0 <= chr && chr <= 0x1F) || chr === 0x7F;
- },
- iscntrl_l__deps: ['iscntrl'],
- iscntrl_l: function(chr) {
- return _iscntrl(chr); // no locale support yet
- },
- isprint: function(chr) {
- return 0x1F < chr && chr < 0x7F;
- },
- isprint_l__deps: ['isprint'],
- isprint_l: function(chr) {
- return _isprint(chr); // no locale support yet
- },
- isgraph: function(chr) {
- return 0x20 < chr && chr < 0x7F;
- },
- isgraph_l__deps: ['isgraph'],
- isgraph_l: function(chr) {
- return _isgraph(chr); // no locale support yet
- },
// Lookup tables for glibc ctype implementation.
__ctype_b_loc__deps: ['malloc'],
__ctype_b_loc: function() {
@@ -3908,12 +3684,18 @@ LibraryManager.library = {
{{{ makeCopyValues('(ppdest+'+Runtime.QUANTUM_SIZE+')', '(ppsrc+'+Runtime.QUANTUM_SIZE+')', Runtime.QUANTUM_SIZE, 'null', null, 1) }}};
},
+ llvm_bswap_i16__asm: true,
+ llvm_bswap_i16__sig: 'ii',
llvm_bswap_i16: function(x) {
- return ((x&0xff)<<8) | ((x>>8)&0xff);
+ x = x|0;
+ return (((x&0xff)<<8) | ((x>>8)&0xff))|0;
},
+ llvm_bswap_i32__asm: true,
+ llvm_bswap_i32__sig: 'ii',
llvm_bswap_i32: function(x) {
- return ((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24);
+ x = x|0;
+ return (((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24))|0;
},
llvm_bswap_i64__deps: ['llvm_bswap_i32'],
@@ -4670,23 +4452,6 @@ LibraryManager.library = {
{{{ makeSetValue('intpart', 0, 'Math.floor(x)', 'float') }}};
return x - {{{ makeGetValue('intpart', 0, 'float') }}};
},
- 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 = sign*x/Math.pow(2, exp_);
- }
- {{{ makeSetValue('exp_addr', 0, 'exp_', 'i32') }}};
- return sig;
- },
- frexpf: 'frexp',
finite: function(x) {
return isFinite(x);
},
@@ -5771,7 +5536,7 @@ LibraryManager.library = {
pattern = pattern.replace(new RegExp('\\%'+pattern[i+1], 'g'), '');
}
- var matches = new RegExp('^'+pattern).exec(Pointer_stringify(buf))
+ var matches = new RegExp('^'+pattern, "i").exec(Pointer_stringify(buf))
// Module['print'](Pointer_stringify(buf)+ ' is matched by '+((new RegExp('^'+pattern)).source)+' into: '+JSON.stringify(matches));
function initDate() {
@@ -6084,15 +5849,15 @@ LibraryManager.library = {
var i = 0;
setjmpId = (setjmpId+1)|0;
{{{ makeSetValueAsm('env', '0', 'setjmpId', 'i32') }}};
- while ((i|0) < {{{ 2*MAX_SETJMPS }}}) {
- if ({{{ makeGetValueAsm('table', '(i<<2)', 'i32') }}} == 0) {
- {{{ makeSetValueAsm('table', '(i<<2)', 'setjmpId', 'i32') }}};
- {{{ makeSetValueAsm('table', '(i<<2)+4', 'label', 'i32') }}};
+ while ((i|0) < {{{ MAX_SETJMPS }}}) {
+ if ({{{ makeGetValueAsm('table', '(i<<3)', 'i32') }}} == 0) {
+ {{{ makeSetValueAsm('table', '(i<<3)', 'setjmpId', 'i32') }}};
+ {{{ makeSetValueAsm('table', '(i<<3)+4', 'label', 'i32') }}};
// prepare next slot
- {{{ makeSetValueAsm('table', '(i<<2)+8', '0', 'i32') }}};
+ {{{ makeSetValueAsm('table', '(i<<3)+8', '0', 'i32') }}};
return 0;
}
- i = (i+2)|0;
+ i = i+1|0;
}
{{{ makePrintChars('too many setjmps in a function call, build with a higher value for MAX_SETJMPS') }}};
abort(0);
@@ -6106,12 +5871,12 @@ LibraryManager.library = {
table = table|0;
var i = 0, curr = 0;
while ((i|0) < {{{ MAX_SETJMPS }}}) {
- curr = {{{ makeGetValueAsm('table', '(i<<2)', 'i32') }}};
+ curr = {{{ makeGetValueAsm('table', '(i<<3)', 'i32') }}};
if ((curr|0) == 0) break;
if ((curr|0) == (id|0)) {
- return {{{ makeGetValueAsm('table', '(i<<2)+4', 'i32') }}};
+ return {{{ makeGetValueAsm('table', '(i<<3)+4', 'i32') }}};
}
- i = (i+2)|0;
+ i = i+1|0;
}
return 0;
},
@@ -6197,8 +5962,10 @@ LibraryManager.library = {
raise__deps: ['$ERRNO_CODES', '__setErrNo'],
raise: function(sig) {
- // TODO:
___setErrNo(ERRNO_CODES.ENOSYS);
+#if ASSERTIONS
+ Runtime.warnOnce('raise() returning an error as we do not support it');
+#endif
return -1;
},
diff --git a/src/library_browser.js b/src/library_browser.js
index 4be7315e..57ca5a24 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -196,41 +196,42 @@ mergeInto(LibraryManager.library, {
// Canvas event setup
var canvas = Module['canvas'];
-
- // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module
- // Module['forcedAspectRatio'] = 4 / 3;
-
- canvas.requestPointerLock = canvas['requestPointerLock'] ||
- canvas['mozRequestPointerLock'] ||
- canvas['webkitRequestPointerLock'] ||
- canvas['msRequestPointerLock'] ||
- function(){};
- canvas.exitPointerLock = document['exitPointerLock'] ||
- document['mozExitPointerLock'] ||
- document['webkitExitPointerLock'] ||
- document['msExitPointerLock'] ||
- function(){}; // no-op if function does not exist
- canvas.exitPointerLock = canvas.exitPointerLock.bind(document);
-
- function pointerLockChange() {
- Browser.pointerLock = document['pointerLockElement'] === canvas ||
- document['mozPointerLockElement'] === canvas ||
- document['webkitPointerLockElement'] === canvas ||
- document['msPointerLockElement'] === canvas;
- }
+ if (canvas) {
+ // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module
+ // Module['forcedAspectRatio'] = 4 / 3;
+
+ canvas.requestPointerLock = canvas['requestPointerLock'] ||
+ canvas['mozRequestPointerLock'] ||
+ canvas['webkitRequestPointerLock'] ||
+ canvas['msRequestPointerLock'] ||
+ function(){};
+ canvas.exitPointerLock = document['exitPointerLock'] ||
+ document['mozExitPointerLock'] ||
+ document['webkitExitPointerLock'] ||
+ document['msExitPointerLock'] ||
+ function(){}; // no-op if function does not exist
+ canvas.exitPointerLock = canvas.exitPointerLock.bind(document);
+
+ function pointerLockChange() {
+ Browser.pointerLock = document['pointerLockElement'] === canvas ||
+ document['mozPointerLockElement'] === canvas ||
+ document['webkitPointerLockElement'] === canvas ||
+ document['msPointerLockElement'] === canvas;
+ }
- document.addEventListener('pointerlockchange', pointerLockChange, false);
- document.addEventListener('mozpointerlockchange', pointerLockChange, false);
- document.addEventListener('webkitpointerlockchange', pointerLockChange, false);
- document.addEventListener('mspointerlockchange', pointerLockChange, false);
+ document.addEventListener('pointerlockchange', pointerLockChange, false);
+ document.addEventListener('mozpointerlockchange', pointerLockChange, false);
+ document.addEventListener('webkitpointerlockchange', pointerLockChange, false);
+ document.addEventListener('mspointerlockchange', pointerLockChange, false);
- if (Module['elementPointerLock']) {
- canvas.addEventListener("click", function(ev) {
- if (!Browser.pointerLock && canvas.requestPointerLock) {
- canvas.requestPointerLock();
- ev.preventDefault();
- }
- }, false);
+ if (Module['elementPointerLock']) {
+ canvas.addEventListener("click", function(ev) {
+ if (!Browser.pointerLock && canvas.requestPointerLock) {
+ canvas.requestPointerLock();
+ ev.preventDefault();
+ }
+ }, false);
+ }
}
},
@@ -321,11 +322,6 @@ mergeInto(LibraryManager.library, {
#endif
// Set the background of the WebGL canvas to black
canvas.style.backgroundColor = "black";
-
- // Warn on context loss
- canvas.addEventListener('webglcontextlost', function(event) {
- alert('WebGL context lost. You will need to reload the page.');
- }, false);
}
if (setInModule) {
GLctx = Module.ctx = ctx;
@@ -429,11 +425,13 @@ mergeInto(LibraryManager.library, {
});
},
safeSetTimeout: function(func, timeout) {
+ Module['noExitRuntime'] = true;
return setTimeout(function() {
if (!ABORT) func();
}, timeout);
},
safeSetInterval: function(func, timeout) {
+ Module['noExitRuntime'] = true;
return setInterval(function() {
if (!ABORT) func();
}, timeout);
@@ -475,7 +473,21 @@ mergeInto(LibraryManager.library, {
},
getMouseWheelDelta: function(event) {
- return Math.max(-1, Math.min(1, event.type === 'DOMMouseScroll' ? event.detail : -event.wheelDelta));
+ var delta = 0;
+ switch (event.type) {
+ case 'DOMMouseScroll':
+ delta = event.detail;
+ break;
+ case 'mousewheel':
+ delta = -event.wheelDelta;
+ break;
+ case 'wheel':
+ delta = event.deltaY;
+ break;
+ default:
+ throw 'unrecognized mouse wheel event: ' + event.type;
+ }
+ return Math.max(-1, Math.min(1, delta));
},
mouseX: 0,
@@ -685,15 +697,22 @@ mergeInto(LibraryManager.library, {
emscripten_async_wget: function(url, file, onload, onerror) {
var _url = Pointer_stringify(url);
var _file = Pointer_stringify(file);
+ function doCallback(callback) {
+ if (callback) {
+ var stack = Runtime.stackSave();
+ Runtime.dynCall('vi', callback, [allocate(intArrayFromString(_file), 'i8', ALLOC_STACK)]);
+ Runtime.stackRestore(stack);
+ }
+ }
FS.createPreloadedFile(
PATH.dirname(_file),
PATH.basename(_file),
_url, true, true,
function() {
- if (onload) Runtime.dynCall('vi', onload, [file]);
+ doCallback(onload);
},
function() {
- if (onerror) Runtime.dynCall('vi', onerror, [file]);
+ doCallback(onerror);
}
);
},
@@ -724,7 +743,11 @@ mergeInto(LibraryManager.library, {
http.onload = function http_onload(e) {
if (http.status == 200) {
FS.createDataFile( _file.substr(0, index), _file.substr(index + 1), new Uint8Array(http.response), true, true);
- if (onload) Runtime.dynCall('vii', onload, [arg, file]);
+ if (onload) {
+ var stack = Runtime.stackSave();
+ Runtime.dynCall('vii', onload, [arg, allocate(intArrayFromString(_file), 'i8', ALLOC_STACK)]);
+ Runtime.stackRestore(stack);
+ }
} else {
if (onerror) Runtime.dynCall('vii', onerror, [arg, http.status]);
}
@@ -737,8 +760,8 @@ mergeInto(LibraryManager.library, {
// PROGRESS
http.onprogress = function http_onprogress(e) {
- if (e.lengthComputable || (e.lengthComputable === undefined && e.totalSize != 0)) {
- var percentComplete = (e.position / e.totalSize)*100;
+ if (e.lengthComputable || (e.lengthComputable === undefined && e.total != 0)) {
+ var percentComplete = (e.loaded / e.total)*100;
if (onprogress) Runtime.dynCall('vii', onprogress, [arg, percentComplete]);
}
};
@@ -886,6 +909,8 @@ mergeInto(LibraryManager.library, {
emscripten_set_main_loop: function(func, fps, simulateInfiniteLoop, arg) {
Module['noExitRuntime'] = true;
+ assert(!Browser.mainLoop.scheduler, 'there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one, if you want to');
+
Browser.mainLoop.runner = function Browser_mainLoop_runner() {
if (ABORT) return;
if (Browser.mainLoop.queue.length > 0) {
@@ -1150,6 +1175,39 @@ mergeInto(LibraryManager.library, {
var info = Browser.workers[id];
if (!info) return -1;
return info.awaited;
+ },
+
+ emscripten_get_preloaded_image_data: function(path, w, h) {
+ if (typeof path === "number") {
+ path = Pointer_stringify(path);
+ }
+
+ path = PATH.resolve(path);
+
+ var canvas = Module["preloadedImages"][path];
+ if (canvas) {
+ var ctx = canvas.getContext("2d");
+ var image = ctx.getImageData(0, 0, canvas.width, canvas.height);
+ var buf = _malloc(canvas.width * canvas.height * 4);
+
+ HEAPU8.set(image.data, buf);
+
+ {{{ makeSetValue('w', '0', 'canvas.width', 'i32') }}};
+ {{{ makeSetValue('h', '0', 'canvas.height', 'i32') }}};
+ return buf;
+ }
+
+ return 0;
+ },
+
+ emscripten_get_preloaded_image_data_from_FILE__deps: ['emscripten_get_preloaded_image_data'],
+ emscripten_get_preloaded_image_data_from_FILE: function(file, w, h) {
+ var stream = FS.getStreamFromPtr(file);
+ if (stream) {
+ return _emscripten_get_preloaded_image_data(stream.path, w, h);
+ }
+
+ return 0;
}
});
diff --git a/src/library_fs.js b/src/library_fs.js
index 3d0036ee..5f7f1dea 100644
--- a/src/library_fs.js
+++ b/src/library_fs.js
@@ -26,7 +26,13 @@ mergeInto(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,
-
+ trackingDelegate: {},
+ tracking: {
+ openFlags: {
+ READ: 1 << 0,
+ WRITE: 1 << 1
+ }
+ },
ErrnoError: null, // set during init
genericErrors: {},
@@ -394,16 +400,12 @@ mergeInto(LibraryManager.library, {
}
});
}
- if (stream.__proto__) {
- // reuse the object
- stream.__proto__ = FS.FSStream.prototype;
- } else {
- var newStream = new FS.FSStream();
- for (var p in stream) {
- newStream[p] = stream[p];
- }
- stream = newStream;
+ // clone it, so we can return an instance of FSStream
+ var newStream = new FS.FSStream();
+ for (var p in stream) {
+ newStream[p] = stream[p];
}
+ stream = newStream;
var fd = FS.nextfd(fd_start, fd_end);
stream.fd = fd;
FS.streams[fd] = stream;
@@ -717,6 +719,13 @@ mergeInto(LibraryManager.library, {
throw new FS.ErrnoError(err);
}
}
+ try {
+ if (FS.trackingDelegate['willMovePath']) {
+ FS.trackingDelegate['willMovePath'](old_path, new_path);
+ }
+ } catch(e) {
+ console.log("FS.trackingDelegate['willMovePath']('"+old_path+"', '"+new_path+"') threw an exception: " + e.message);
+ }
// remove the node from the lookup hash
FS.hashRemoveNode(old_node);
// do the underlying fs rename
@@ -729,6 +738,11 @@ mergeInto(LibraryManager.library, {
// changed its name)
FS.hashAddNode(old_node);
}
+ try {
+ if (FS.trackingDelegate['onMovePath']) FS.trackingDelegate['onMovePath'](old_path, new_path);
+ } catch(e) {
+ console.log("FS.trackingDelegate['onMovePath']('"+old_path+"', '"+new_path+"') threw an exception: " + e.message);
+ }
},
rmdir: function(path) {
var lookup = FS.lookupPath(path, { parent: true });
@@ -745,8 +759,20 @@ mergeInto(LibraryManager.library, {
if (FS.isMountpoint(node)) {
throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
}
+ try {
+ if (FS.trackingDelegate['willDeletePath']) {
+ FS.trackingDelegate['willDeletePath'](path);
+ }
+ } catch(e) {
+ console.log("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: " + e.message);
+ }
parent.node_ops.rmdir(parent, name);
FS.destroyNode(node);
+ try {
+ if (FS.trackingDelegate['onDeletePath']) FS.trackingDelegate['onDeletePath'](path);
+ } catch(e) {
+ console.log("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: " + e.message);
+ }
},
readdir: function(path) {
var lookup = FS.lookupPath(path, { follow: true });
@@ -773,8 +799,20 @@ mergeInto(LibraryManager.library, {
if (FS.isMountpoint(node)) {
throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
}
+ try {
+ if (FS.trackingDelegate['willDeletePath']) {
+ FS.trackingDelegate['willDeletePath'](path);
+ }
+ } catch(e) {
+ console.log("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: " + e.message);
+ }
parent.node_ops.unlink(parent, name);
FS.destroyNode(node);
+ try {
+ if (FS.trackingDelegate['onDeletePath']) FS.trackingDelegate['onDeletePath'](path);
+ } catch(e) {
+ console.log("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: " + e.message);
+ }
},
readlink: function(path) {
var lookup = FS.lookupPath(path);
@@ -969,6 +1007,20 @@ mergeInto(LibraryManager.library, {
Module['printErr']('read file: ' + path);
}
}
+ try {
+ if (FS.trackingDelegate['onOpenFile']) {
+ var trackingFlags = 0;
+ if ((flags & {{{ cDefine('O_ACCMODE') }}}) !== {{{ cDefine('O_WRONLY') }}}) {
+ trackingFlags |= FS.tracking.openFlags.READ;
+ }
+ if ((flags & {{{ cDefine('O_ACCMODE') }}}) !== {{{ cDefine('O_RDONLY') }}}) {
+ trackingFlags |= FS.tracking.openFlags.WRITE;
+ }
+ FS.trackingDelegate['onOpenFile'](path, trackingFlags);
+ }
+ } catch(e) {
+ console.log("FS.trackingDelegate['onOpenFile']('"+path+"', flags) threw an exception: " + e.message);
+ }
return stream;
},
close: function(stream) {
@@ -1038,6 +1090,11 @@ mergeInto(LibraryManager.library, {
}
var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);
if (!seeking) stream.position += bytesWritten;
+ try {
+ if (stream.path && FS.trackingDelegate['onWriteToFile']) FS.trackingDelegate['onWriteToFile'](stream.path);
+ } catch(e) {
+ console.log("FS.trackingDelegate['onWriteToFile']('"+path+"') threw an exception: " + e.message);
+ }
return bytesWritten;
},
allocate: function(stream, offset, length) {
diff --git a/src/library_gl.js b/src/library_gl.js
index 851b01b1..2659a9d9 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -431,21 +431,42 @@ var LibraryGL = {
sizePerPixel = 2;
break;
default:
- throw 'Invalid format (' + format + ')';
+ GL.recordError(0x0500); // GL_INVALID_ENUM
+#if GL_ASSERTIONS
+ Module.printErr('GL_INVALID_ENUM in glTex[Sub]Image, type: ' + type + ', format: ' + format);
+#endif
+ return {
+ pixels: null,
+ internalFormat: 0x0
+ };
}
break;
case 0x1403 /* GL_UNSIGNED_SHORT */:
if (format == 0x1902 /* GL_DEPTH_COMPONENT */) {
sizePerPixel = 2;
} else {
- throw 'Invalid format (' + format + ')';
+ GL.recordError(0x0500); // GL_INVALID_ENUM
+#if GL_ASSERTIONS
+ Module.printErr('GL_INVALID_ENUM in glTex[Sub]Image, type: ' + type + ', format: ' + format);
+#endif
+ return {
+ pixels: null,
+ internalFormat: 0x0
+ };
}
break;
case 0x1405 /* GL_UNSIGNED_INT */:
if (format == 0x1902 /* GL_DEPTH_COMPONENT */) {
sizePerPixel = 4;
} else {
- throw 'Invalid format (' + format + ')';
+ GL.recordError(0x0500); // GL_INVALID_ENUM
+#if GL_ASSERTIONS
+ Module.printErr('GL_INVALID_ENUM in glTex[Sub]Image, type: ' + type + ', format: ' + format);
+#endif
+ return {
+ pixels: null,
+ internalFormat: 0x0
+ };
}
break;
case 0x84FA /* UNSIGNED_INT_24_8_WEBGL */:
@@ -468,12 +489,26 @@ var LibraryGL = {
sizePerPixel = 4*4;
break;
default:
- throw 'Invalid format (' + format + ')';
+ GL.recordError(0x0500); // GL_INVALID_ENUM
+#if GL_ASSERTIONS
+ Module.printErr('GL_INVALID_ENUM in glTex[Sub]Image, type: ' + type + ', format: ' + format);
+#endif
+ return {
+ pixels: null,
+ internalFormat: 0x0
+ };
}
internalFormat = GLctx.RGBA;
break;
default:
- throw 'Invalid type (' + type + ')';
+ GL.recordError(0x0500); // GL_INVALID_ENUM
+#if GL_ASSERTIONS
+ Module.printErr('GL_INVALID_ENUM in glTex[Sub]Image, type: ' + type + ', format: ' + format);
+#endif
+ return {
+ pixels: null,
+ internalFormat: 0x0
+ };
}
var bytes = GL.computeImageSize(width, height, sizePerPixel, GL.unpackAlignment);
if (type == 0x1401 /* GL_UNSIGNED_BYTE */) {
@@ -488,7 +523,7 @@ var LibraryGL = {
return {
pixels: pixels,
internalFormat: internalFormat
- }
+ };
},
#if GL_FFP_ONLY
diff --git a/src/library_glfw.js b/src/library_glfw.js
index 04dd4a0a..6dfea101 100644
--- a/src/library_glfw.js
+++ b/src/library_glfw.js
@@ -211,7 +211,7 @@ var LibraryGLFW = {
},
onMouseWheel: function(event) {
- GLFW.wheelPos += Browser.getMouseWheelDelta(event);
+ GLFW.wheelPos -= Browser.getMouseWheelDelta(event);
if (GLFW.mouseWheelFunc && event.target == Module["canvas"]) {
Runtime.dynCall('vi', GLFW.mouseWheelFunc, [GLFW.wheelPos]);
diff --git a/src/library_html5.js b/src/library_html5.js
index d9376c2a..d5d0cd66 100644
--- a/src/library_html5.js
+++ b/src/library_html5.js
@@ -1307,6 +1307,12 @@ var LibraryJSEvents = {
JSEvents.registerWebGlEventCallback(target, userData, useCapture, callbackfunc, {{{ cDefine('EMSCRIPTEN_EVENT_WEBGLCONTEXTRESTORED') }}}, "webglcontextrestored");
return {{{ cDefine('EMSCRIPTEN_RESULT_SUCCESS') }}};
},
+
+ emscripten_is_webgl_context_lost: function(target) {
+ // TODO: In the future if multiple GL contexts are supported, use the 'target' parameter to find the canvas to query.
+ if (!Module['ctx']) return true; // No context ~> lost context.
+ return Module['ctx'].isContextLost();
+ }
};
autoAddDeps(LibraryJSEvents, '$JSEvents');
diff --git a/src/library_sdl.js b/src/library_sdl.js
index eedb8c48..a01b3c6c 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -430,6 +430,15 @@ var LibrarySDL = {
savedKeydown: null,
receiveEvent: function(event) {
+ function unpressAllPressedKeys() {
+ // Un-press all pressed keys: TODO
+ for (var code in SDL.keyboardMap) {
+ SDL.events.push({
+ type: 'keyup',
+ keyCode: SDL.keyboardMap[code]
+ });
+ }
+ };
switch(event.type) {
case 'touchstart': case 'touchmove': {
event.preventDefault();
@@ -532,7 +541,7 @@ var LibrarySDL = {
}
}
// fall through
- case 'keydown': case 'keyup': case 'keypress': case 'mousedown': case 'mouseup': case 'DOMMouseScroll': case 'mousewheel':
+ case 'keydown': case 'keyup': case 'keypress': case 'mousedown': case 'mouseup': case 'DOMMouseScroll': case 'mousewheel': case 'wheel':
// If we preventDefault on keydown events, the subsequent keypress events
// won't fire. However, it's fine (and in some cases necessary) to
// preventDefault for keys that don't generate a character. Otherwise,
@@ -541,21 +550,40 @@ var LibrarySDL = {
event.preventDefault();
}
- if (event.type == 'DOMMouseScroll' || event.type == 'mousewheel') {
+ if (event.type == 'DOMMouseScroll' || event.type == 'mousewheel' || event.type == 'wheel') {
+ // Simulate old-style SDL events representing mouse wheel input as buttons
var button = Browser.getMouseWheelDelta(event) > 0 ? 4 : 3;
- var event2 = {
+ var event1 = {
type: 'mousedown',
button: button,
pageX: event.pageX,
pageY: event.pageY
};
- SDL.events.push(event2);
- event = {
+ SDL.events.push(event1);
+ var event2 = {
type: 'mouseup',
button: button,
pageX: event.pageX,
pageY: event.pageY
};
+ SDL.events.push(event2);
+
+ // Convert DOMMouseScroll events to wheel events for new style SDL events.
+ if (event.type == 'DOMMouseScroll') {
+ SDL.events.push({
+ type: 'wheel',
+ deltaX: 0,
+ deltaY: -event.detail,
+ });
+ break;
+ } else if (event.type == 'mousewheel') {
+ SDL.events.push({
+ type: 'wheel',
+ deltaX: 0,
+ deltaY: event.wheelDelta,
+ });
+ break;
+ }
} else if (event.type == 'mousedown') {
SDL.DOMButtons[event.button] = 1;
SDL.events.push({
@@ -635,18 +663,23 @@ var LibrarySDL = {
}
event.preventDefault();
break;
+ case 'focus':
+ SDL.events.push(event);
+ event.preventDefault();
+ break;
case 'blur':
- case 'visibilitychange': {
- // Un-press all pressed keys: TODO
- for (var code in SDL.keyboardMap) {
- SDL.events.push({
- type: 'keyup',
- keyCode: SDL.keyboardMap[code]
- });
- }
+ SDL.events.push(event);
+ unpressAllPressedKeys();
+ event.preventDefault();
+ break;
+ case 'visibilitychange':
+ SDL.events.push({
+ type: 'visibilitychange',
+ visible: !document.hidden
+ });
+ unpressAllPressedKeys();
event.preventDefault();
break;
- }
case 'unload':
if (Browser.mainLoop.runner) {
SDL.events.push(event);
@@ -686,7 +719,6 @@ var LibrarySDL = {
} else {
code = SDL.keyCodes[event.keyCode] || event.keyCode;
}
-
{{{ makeSetValue('SDL.keyboardState', 'code', 'down', 'i8') }}};
// TODO: lmeta, rmeta, numlock, capslock, KMOD_MODE, KMOD_RESERVED
SDL.modState = ({{{ makeGetValue('SDL.keyboardState', '1248', 'i8') }}} ? 0x0040 | 0x0080 : 0) | // KMOD_LCTRL & KMOD_RCTRL
@@ -788,8 +820,15 @@ var LibrarySDL = {
}
break;
}
+ case 'wheel': {
+ {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseWheelEvent.type, 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}};
+ {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseWheelEvent.x, 'event.deltaX', 'i32') }}};
+ {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseWheelEvent.y, 'event.deltaY', 'i32') }}};
+ break;
+ }
case 'touchstart': case 'touchend': case 'touchmove': {
var touch = event.touch;
+ if (!Browser.touches[touch.identifier]) break;
var w = Module['canvas'].width;
var h = Module['canvas'].height;
var x = Browser.touches[touch.identifier].x / w;
@@ -840,6 +879,29 @@ var LibrarySDL = {
{{{ makeSetValue('ptr', C_STRUCTS.SDL_JoyAxisEvent.value, 'SDL.joystickAxisValueConversion(event.value)', 'i32') }}};
break;
}
+ case 'focus': {
+ var SDL_WINDOWEVENT_FOCUS_GAINED = 12 /* SDL_WINDOWEVENT_FOCUS_GAINED */;
+ {{{ makeSetValue('ptr', C_STRUCTS.SDL_WindowEvent.type, 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}};
+ {{{ makeSetValue('ptr', C_STRUCTS.SDL_WindowEvent.windowID, '0', 'i32') }}};
+ {{{ makeSetValue('ptr', C_STRUCTS.SDL_WindowEvent.event, 'SDL_WINDOWEVENT_FOCUS_GAINED', 'i8') }}};
+ break;
+ }
+ case 'blur': {
+ var SDL_WINDOWEVENT_FOCUS_LOST = 13 /* SDL_WINDOWEVENT_FOCUS_LOST */;
+ {{{ makeSetValue('ptr', C_STRUCTS.SDL_WindowEvent.type, 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}};
+ {{{ makeSetValue('ptr', C_STRUCTS.SDL_WindowEvent.windowID, '0', 'i32') }}};
+ {{{ makeSetValue('ptr', C_STRUCTS.SDL_WindowEvent.event, 'SDL_WINDOWEVENT_FOCUS_LOST', 'i8') }}};
+ break;
+ }
+ case 'visibilitychange': {
+ var SDL_WINDOWEVENT_SHOWN = 1 /* SDL_WINDOWEVENT_SHOWN */;
+ var SDL_WINDOWEVENT_HIDDEN = 2 /* SDL_WINDOWEVENT_HIDDEN */;
+ var visibilityEventID = event.visible ? SDL_WINDOWEVENT_SHOWN : SDL_WINDOWEVENT_HIDDEN;
+ {{{ makeSetValue('ptr', C_STRUCTS.SDL_WindowEvent.type, 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}};
+ {{{ makeSetValue('ptr', C_STRUCTS.SDL_WindowEvent.windowID, 0, 'i32') }}};
+ {{{ makeSetValue('ptr', C_STRUCTS.SDL_WindowEvent.event, 'visibilityEventID' , 'i8') }}};
+ break;
+ }
default: throw 'Unhandled SDL event: ' + event.type;
}
},
@@ -880,12 +942,80 @@ var LibrarySDL = {
if (!info) return 0;
var ret = info.volume * 128; // MIX_MAX_VOLUME
if (volume != -1) {
- info.volume = volume / 128;
- if (info.audio) info.audio.volume = info.volume;
+ info.volume = Math.min(Math.max(volume, 0), 128) / 128;
+ if (info.audio) {
+ try {
+ info.audio.volume = info.volume; // For <audio> element
+ if (info.audio.webAudioGainNode) info.audio.webAudioGainNode['gain']['value'] = info.volume; // For WebAudio playback
+ } catch(e) {
+ Module.printErr('setGetVolume failed to set audio volume: ' + e);
+ }
+ }
}
return ret;
},
+ // Plays out an SDL audio resource that was loaded with the Mix_Load APIs, when using Web Audio..
+ playWebAudio: function(audio) {
+ if (!audio) return;
+ if (audio.webAudioNode) return; // This instance is already playing, don't start again.
+ if (!SDL.webAudioAvailable()) return;
+ try {
+ var webAudio = audio.resource.webAudio;
+ audio.paused = false;
+ if (!webAudio.decodedBuffer) {
+ if (webAudio.onDecodeComplete === undefined) abort("Cannot play back audio object that was not loaded");
+ webAudio.onDecodeComplete.push(function() { if (!audio.paused) SDL.playWebAudio(audio); });
+ return;
+ }
+ audio.webAudioNode = SDL.audioContext['createBufferSource']();
+ audio.webAudioNode['buffer'] = webAudio.decodedBuffer;
+ audio.webAudioNode['loop'] = audio.loop;
+ audio.webAudioNode['onended'] = function() { audio.onended(); } // For <media> element compatibility, route the onended signal to the instance.
+
+ // Add an intermediate gain node to control volume.
+ audio.webAudioGainNode = SDL.audioContext['createGain']();
+ audio.webAudioGainNode['gain']['value'] = audio.volume;
+ audio.webAudioNode['connect'](audio.webAudioGainNode);
+ audio.webAudioGainNode['connect'](SDL.audioContext['destination']);
+ audio.webAudioNode['start'](0, audio.currentPosition);
+ audio.startTime = SDL.audioContext['currentTime'] - audio.currentPosition;
+ } catch(e) {
+ Module.printErr('playWebAudio failed: ' + e);
+ }
+ },
+
+ // Pausea an SDL audio resource that was played with Web Audio..
+ pauseWebAudio: function(audio) {
+ if (!audio) return;
+ if (audio.webAudioNode) {
+ try {
+ // Remember where we left off, so that if/when we resume, we can restart the playback at a proper place.
+ audio.currentPosition = (SDL.audioContext['currentTime'] - audio.startTime) % audio.resource.webAudio.decodedBuffer.duration;
+ // Important: When we reach here, the audio playback is stopped by the user. But when calling .stop() below, the Web Audio
+ // graph will send the onended signal, but we don't want to process that, since pausing should not clear/destroy the audio
+ // channel.
+ audio.webAudioNode['onended'] = undefined;
+ audio.webAudioNode.stop();
+ audio.webAudioNode = undefined;
+ } catch(e) {
+ Module.printErr('pauseWebAudio failed: ' + e);
+ }
+ }
+ audio.paused = true;
+ },
+
+ openAudioContext: function() {
+ // Initialize Web Audio API if we haven't done so yet. Note: Only initialize Web Audio context ever once on the web page,
+ // since initializing multiple times fails on Chrome saying 'audio resources have been exhausted'.
+ if (!SDL.audioContext) {
+ if (typeof(AudioContext) !== 'undefined') SDL.audioContext = new AudioContext();
+ else if (typeof(webkitAudioContext) !== 'undefined') SDL.audioContext = new webkitAudioContext();
+ }
+ },
+
+ webAudioAvailable: function() { return !!SDL.audioContext; },
+
fillWebAudioBufferFromHeap: function(heapPtr, sizeSamplesPerChannel, dstAudioBuffer) {
// The input audio data is interleaved across the channels, i.e. [L, R, L, R, L, R, ...] and is either 8-bit or 16-bit as
// supported by the SDL API. The output audio wave data for Web Audio API must be in planar buffers of [-1,1]-normalized Float32 data,
@@ -1043,6 +1173,7 @@ var LibrarySDL = {
document.addEventListener("keydown", SDL.receiveEvent);
document.addEventListener("keyup", SDL.receiveEvent);
document.addEventListener("keypress", SDL.receiveEvent);
+ window.addEventListener("focus", SDL.receiveEvent);
window.addEventListener("blur", SDL.receiveEvent);
document.addEventListener("visibilitychange", SDL.receiveEvent);
}
@@ -1065,11 +1196,16 @@ var LibrarySDL = {
SDL.DOMEventToSDLEvent['mousedown'] = 0x401 /* SDL_MOUSEBUTTONDOWN */;
SDL.DOMEventToSDLEvent['mouseup'] = 0x402 /* SDL_MOUSEBUTTONUP */;
SDL.DOMEventToSDLEvent['mousemove'] = 0x400 /* SDL_MOUSEMOTION */;
+ SDL.DOMEventToSDLEvent['wheel'] = 0x403 /* SDL_MOUSEWHEEL */;
SDL.DOMEventToSDLEvent['touchstart'] = 0x700 /* SDL_FINGERDOWN */;
SDL.DOMEventToSDLEvent['touchend'] = 0x701 /* SDL_FINGERUP */;
SDL.DOMEventToSDLEvent['touchmove'] = 0x702 /* SDL_FINGERMOTION */;
SDL.DOMEventToSDLEvent['unload'] = 0x100 /* SDL_QUIT */;
SDL.DOMEventToSDLEvent['resize'] = 0x7001 /* SDL_VIDEORESIZE/SDL_EVENT_COMPAT2 */;
+ SDL.DOMEventToSDLEvent['visibilitychange'] = 0x200 /* SDL_WINDOWEVENT */;
+ SDL.DOMEventToSDLEvent['focus'] = 0x200 /* SDL_WINDOWEVENT */;
+ SDL.DOMEventToSDLEvent['blur'] = 0x200 /* SDL_WINDOWEVENT */;
+
// These are not technically DOM events; the HTML gamepad API is poll-based.
// However, we define them here, as the rest of the SDL code assumes that
// all SDL events originate as DOM events.
@@ -1139,7 +1275,7 @@ var LibrarySDL = {
},
SDL_SetVideoMode: function(width, height, depth, flags) {
- ['touchstart', 'touchend', 'touchmove', 'mousedown', 'mouseup', 'mousemove', 'DOMMouseScroll', 'mousewheel', 'mouseout'].forEach(function(event) {
+ ['touchstart', 'touchend', 'touchmove', 'mousedown', 'mouseup', 'mousemove', 'DOMMouseScroll', 'mousewheel', 'wheel', 'mouseout'].forEach(function(event) {
Module['canvas'].addEventListener(event, SDL.receiveEvent, true);
});
@@ -1182,11 +1318,11 @@ var LibrarySDL = {
for (var i = 0; i < SDL.numChannels; ++i) {
if (SDL.channels[i].audio) {
SDL.channels[i].audio.pause();
+ SDL.channels[i].audio = undefined;
}
}
- if (SDL.music.audio) {
- SDL.music.audio.pause();
- }
+ if (SDL.music.audio) SDL.music.audio.pause();
+ SDL.music.audio = undefined;
Module.print('SDL_Quit called (and ignored)');
},
@@ -1936,15 +2072,8 @@ var LibrarySDL = {
} else {
// Initialize Web Audio API if we haven't done so yet. Note: Only initialize Web Audio context ever once on the web page,
// since initializing multiple times fails on Chrome saying 'audio resources have been exhausted'.
- if (!SDL.audioContext) {
- if (typeof(AudioContext) !== 'undefined') {
- SDL.audioContext = new AudioContext();
- } else if (typeof(webkitAudioContext) !== 'undefined') {
- SDL.audioContext = new webkitAudioContext();
- } else {
- throw 'Web Audio API is not available!';
- }
- }
+ SDL.openAudioContext();
+ if (!SDL.audioContext) throw 'Web Audio API is not available!';
SDL.audio.soundSource = new Array(); // Use an array of sound sources as a ring buffer to queue blocks of synthesized audio to Web Audio API.
SDL.audio.nextSoundSource = 0; // Index of the next sound buffer in the ring buffer queue to play.
SDL.audio.nextPlayTime = 0; // Time in seconds when the next audio block is due to start.
@@ -2127,6 +2256,7 @@ var LibrarySDL = {
Mix_Quit: function(){},
Mix_OpenAudio: function(frequency, format, channels, chunksize) {
+ SDL.openAudioContext();
SDL.allocateChannels(32);
// Just record the values for a later call to Mix_QuickLoad_RAW
SDL.mixerFrequency = frequency;
@@ -2169,6 +2299,7 @@ var LibrarySDL = {
var filename = '';
var audio;
+ var webAudio;
var bytes;
if (rwops.filename !== undefined) {
@@ -2176,7 +2307,7 @@ var LibrarySDL = {
var raw = Module["preloadedAudios"][filename];
if (!raw) {
if (raw === null) Module.printErr('Trying to reuse preloaded audio, but freePreloadedMediaOnUse is set!');
- Runtime.warnOnce('Cannot find preloaded audio ' + filename);
+ if (!Module.noAudioDecoding) Runtime.warnOnce('Cannot find preloaded audio ' + filename);
// see if we can read the file-contents from the in-memory FS
try {
@@ -2192,45 +2323,84 @@ var LibrarySDL = {
audio = raw;
}
else if (rwops.bytes !== undefined) {
- bytes = HEAPU8.subarray(rwops.bytes, rwops.bytes + rwops.count);
+ // For Web Audio context buffer decoding, we must make a clone of the audio data, but for <media> element,
+ // a view to existing data is sufficient.
+ if (SDL.webAudioAvailable()) bytes = HEAPU8.buffer.slice(rwops.bytes, rwops.bytes + rwops.count);
+ else bytes = HEAPU8.subarray(rwops.bytes, rwops.bytes + rwops.count);
}
else {
return 0;
}
- // Here, we didn't find a preloaded audio but we either were passed a filepath for
- // which we loaded bytes, or we were passed some bytes
- if (audio === undefined && bytes) {
+ var arrayBuffer = bytes ? bytes.buffer || bytes : bytes;
+
+ // To allow user code to work around browser bugs with audio playback on <audio> elements an Web Audio, enable
+ // the user code to hook in a callback to decide on a file basis whether each file should use Web Audio or <audio> for decoding and playback.
+ // In particular, see https://bugzilla.mozilla.org/show_bug.cgi?id=654787 and ?id=1012801 for tradeoffs.
+ var canPlayWithWebAudio = Module['SDL_canPlayWithWebAudio'] === undefined || Module['SDL_canPlayWithWebAudio'](filename, arrayBuffer);
+
+ if (bytes !== undefined && SDL.webAudioAvailable() && canPlayWithWebAudio) {
+ audio = undefined;
+ webAudio = {};
+ // The audio decoding process is asynchronous, which gives trouble if user code plays the audio data back immediately
+ // after loading. Therefore prepare an array of callback handlers to run when this audio decoding is complete, which
+ // will then start the playback (with some delay).
+ webAudio.onDecodeComplete = []; // While this member array exists, decoding hasn't finished yet.
+ function onDecodeComplete(data) {
+ webAudio.decodedBuffer = data;
+ // Call all handlers that were waiting for this decode to finish, and clear the handler list.
+ webAudio.onDecodeComplete.forEach(function(e) { e(); });
+ webAudio.onDecodeComplete = undefined; // Don't allow more callback handlers since audio has finished decoding.
+ }
+
+ SDL.audioContext['decodeAudioData'](arrayBuffer, onDecodeComplete);
+ } else if (audio === undefined && bytes) {
+ // Here, we didn't find a preloaded audio but we either were passed a filepath for
+ // which we loaded bytes, or we were passed some bytes
var blob = new Blob([bytes], {type: rwops.mimetype});
var url = URL.createObjectURL(blob);
audio = new Audio();
audio.src = url;
+ audio.mozAudioChannelType = 'content'; // bugzilla 910340
}
var id = SDL.audios.length;
// Keep the loaded audio in the audio arrays, ready for playback
SDL.audios.push({
source: filename,
- audio: audio
+ audio: audio, // Points to the <audio> element, if loaded
+ webAudio: webAudio // Points to a Web Audio -specific resource object, if loaded
});
return id;
},
Mix_QuickLoad_RAW: function(mem, len) {
- var audio = new Audio();
- // Record the number of channels and frequency for later usage
- audio.numChannels = SDL.mixerNumChannels;
- audio.frequency = SDL.mixerFrequency;
+ var audio;
+ var webAudio;
+
var numSamples = len >> 1; // len is the length in bytes, and the array contains 16-bit PCM values
var buffer = new Float32Array(numSamples);
for (var i = 0; i < numSamples; ++i) {
buffer[i] = ({{{ makeGetValue('mem', 'i*2', 'i16', 0, 0) }}}) / 0x8000; // hardcoded 16-bit audio, signed (TODO: reSign if not ta2?)
}
- // FIXME: doesn't make sense to keep the audio element in the buffer
+
+ if (SDL.webAudioAvailable()) {
+ webAudio = {};
+ webAudio.decodedBuffer = buffer;
+ } else {
+ var audio = new Audio();
+ audio.mozAudioChannelType = 'content'; // bugzilla 910340
+ // Record the number of channels and frequency for later usage
+ audio.numChannels = SDL.mixerNumChannels;
+ audio.frequency = SDL.mixerFrequency;
+ // FIXME: doesn't make sense to keep the audio element in the buffer
+ }
+
var id = SDL.audios.length;
SDL.audios.push({
source: '',
audio: audio,
+ webAudio: webAudio,
buffer: buffer
});
return id;
@@ -2243,13 +2413,12 @@ var LibrarySDL = {
SDL.channelMinimumNumber = num;
},
Mix_PlayChannel: function(channel, id, loops) {
- // TODO: handle loops
+ // TODO: handle fixed amount of N loops. Currently loops either 0 or infinite times.
// Get the audio element associated with the ID
var info = SDL.audios[id];
if (!info) return -1;
- var audio = info.audio;
- if (!audio) return -1;
+ if (!info.audio && !info.webAudio) return -1;
// If the user asks us to allocate a channel automatically, get the first
// free one.
@@ -2265,73 +2434,33 @@ var LibrarySDL = {
return -1;
}
}
- // We clone the audio node to utilize the preloaded audio buffer, since
- // the browser has already preloaded the audio file.
var channelInfo = SDL.channels[channel];
- 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;
- audio['onended'] = function SDL_audio_onended() { // TODO: cache these
- channelInfo.audio = null;
- if (SDL.channelFinished) {
- Runtime.getFuncWrapper(SDL.channelFinished, 'vi')(channel);
- }
- }
- // Either play the element, or load the dynamic data into it
- if (info.buffer) {
- var contextCtor = null;
- if (audio && ('mozSetup' in audio)) { // Audio Data API
- try {
- audio['mozSetup'](audio.numChannels, audio.frequency);
- audio["mozWriteAudio"](info.buffer);
- } catch (e) {
- // Workaround for Firefox bug 783052
- // ignore this exception!
- }
- /*
- } else if (contextCtor = (window.AudioContext || // WebAudio API
- window.webkitAudioContext)) {
- var currentIndex = 0;
- var numChannels = parseInt(audio.numChannels);
- var context = new contextCtor();
- var source = context.createBufferSource();
- source.loop = false;
- source.buffer = context.createBuffer(numChannels, 1, audio.frequency);
- var jsNode = context.createJavaScriptNode(2048, numChannels, numChannels);
- jsNode.onaudioprocess = function jsNode_onaudioprocess(event) {
- var buffers = new Array(numChannels);
- for (var i = 0; i < numChannels; ++i) {
- buffers[i] = event.outputBuffer.getChannelData(i);
- }
- var remaining = info.buffer.length - currentIndex;
- if (remaining > 2048) {
- remaining = 2048;
- }
- for (var i = 0; i < remaining;) {
- for (var j = 0; j < numChannels; ++j) {
- buffers[j][i] = info.buffer[currentIndex + i + j] * audio.volume;
- }
- i += j;
- }
- currentIndex += remaining * numChannels;
- for (var i = remaining; i < 2048;) {
- for (var j = 0; j < numChannels; ++j) {
- buffers[j][i] = 0; // silence
- }
- i += j;
- }
- };
- source.connect(jsNode);
- jsNode.connect(context.destination);
- source.noteOn(0);
- */
- }
+ var audio;
+ if (info.webAudio) {
+ // Create an instance of the WebAudio object.
+ audio = {};
+ audio.resource = info; // This new object is an instance that refers to this existing resource.
+ audio.paused = false;
+ audio.currentPosition = 0;
+ // Make our instance look similar to the instance of a <media> to make api simple.
+ audio.play = function() { SDL.playWebAudio(this); }
+ audio.pause = function() { SDL.pauseWebAudio(this); }
} else {
- audio.play();
+ // We clone the audio node to utilize the preloaded audio buffer, since
+ // the browser has already preloaded the audio file.
+ audio = info.audio.cloneNode(true);
+ audio.numChannels = info.audio.numChannels;
+ audio.frequency = info.audio.frequency;
}
+ audio['onended'] = function SDL_audio_onended() { // TODO: cache these
+ if (channelInfo.audio == this) { channelInfo.audio.paused = true; channelInfo.audio = null; }
+ if (SDL.channelFinished) Runtime.getFuncWrapper(SDL.channelFinished, 'vi')(channel);
+ }
+ channelInfo.audio = audio;
+ // TODO: handle N loops. Behavior matches Mix_PlayMusic
+ audio.loop = loops != 0;
audio.volume = channelInfo.volume;
+ audio.play();
return channel;
},
Mix_PlayChannelTimed: 'Mix_PlayChannel', // XXX ignore Timing
@@ -2384,46 +2513,51 @@ var LibrarySDL = {
Mix_PlayMusic__deps: ['Mix_HaltMusic'],
Mix_PlayMusic: function(id, loops) {
- loops = Math.max(loops, 1);
- var audio = SDL.audios[id].audio;
- if (!audio) return 0;
- audio.loop = loops != 0; // TODO: handle N loops for finite N
- if (SDL.audios[id].buffer) {
- audio["mozWriteAudio"](SDL.audios[id].buffer);
- } else {
- audio.play();
- }
- audio.volume = SDL.music.volume;
- audio['onended'] = _Mix_HaltMusic; // will send callback
+ // Pause old music if it exists.
if (SDL.music.audio) {
- if (!SDL.music.audio.paused) {
- Module.printErr('Music is already playing. ' + SDL.music.source);
- }
+ if (!SDL.music.audio.paused) Module.printErr('Music is already playing. ' + SDL.music.source);
SDL.music.audio.pause();
}
+ var info = SDL.audios[id];
+ var audio;
+ if (info.webAudio) { // Play via Web Audio API
+ // Create an instance of the WebAudio object.
+ audio = {};
+ audio.resource = info; // This new webAudio object is an instance that refers to this existing resource.
+ audio.paused = false;
+ audio.currentPosition = 0;
+ audio.play = function() { SDL.playWebAudio(this); }
+ audio.pause = function() { SDL.pauseWebAudio(this); }
+ } else if (info.audio) { // Play via the <audio> element
+ audio = info.audio;
+ }
+ audio['onended'] = function() { if (SDL.music.audio == this) _Mix_HaltMusic(); } // will send callback
+ audio.loop = loops != 0; // TODO: handle N loops for finite N
+ audio.volume = SDL.music.volume;
SDL.music.audio = audio;
+ audio.play();
return 0;
},
Mix_PauseMusic: function() {
var audio = SDL.music.audio;
- if (!audio) return 0;
- audio.pause();
+ if (audio) audio.pause();
return 0;
},
Mix_ResumeMusic: function() {
var audio = SDL.music.audio;
- if (!audio) return 0;
- audio.play();
+ if (audio) audio.play();
return 0;
},
Mix_HaltMusic: function() {
var audio = SDL.music.audio;
- if (!audio) return 0;
- audio.src = audio.src; // rewind
- audio.pause();
+ if (audio) {
+ audio.src = audio.src; // rewind <media> element
+ audio.currentPosition = 0; // rewind Web Audio graph playback.
+ audio.pause();
+ }
SDL.music.audio = null;
if (SDL.hookMusicFinished) {
Runtime.dynCall('v', SDL.hookMusicFinished);
@@ -2500,9 +2634,7 @@ var LibrarySDL = {
return;
}
var info = SDL.channels[channel];
- if (info && info.audio) {
- info.audio.play();
- }
+ if (info && info.audio) info.audio.play();
},
// SDL TTF
diff --git a/src/modules.js b/src/modules.js
index 2d2a75d0..fd5c23cd 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -21,6 +21,7 @@ var LLVM = {
CONVERSIONS: set('inttoptr', 'ptrtoint', 'uitofp', 'sitofp', 'fptosi', 'fptoui', 'fpext', 'fptrunc'),
INTRINSICS_32: set('_llvm_memcpy_p0i8_p0i8_i64', '_llvm_memmove_p0i8_p0i8_i64', '_llvm_memset_p0i8_i64'), // intrinsics that need args converted to i32 in USE_TYPED_ARRAYS == 2
MATHOP_IGNORABLES: set('exact', 'nnan', 'ninf', 'nsz', 'arcp', 'fast'),
+ PARAM_IGNORABLES: set('nocapture', 'readonly', 'readnone'),
};
LLVM.GLOBAL_MODIFIERS = set(keys(LLVM.LINKAGES).concat(['constant', 'global', 'hidden']));
diff --git a/src/parseTools.js b/src/parseTools.js
index 4fb76196..ececf477 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -467,7 +467,7 @@ function parseParamTokens(params) {
// handle 'byval' and 'byval align X'. We store the alignment in 'byVal'
byVal = QUANTUM_SIZE;
segment.splice(1, 1);
- if (segment[1] && (segment[1].text === 'nocapture' || segment[1].text === 'readonly')) {
+ if (segment[1] && (segment[1].text in LLVM.PARAM_IGNORABLES)) {
segment.splice(1, 1);
}
if (segment[1] && segment[1].text === 'align') {
@@ -476,7 +476,7 @@ function parseParamTokens(params) {
segment.splice(1, 2);
}
}
- if (segment[1] && (segment[1].text === 'nocapture' || segment[1].text === 'readonly')) {
+ if (segment[1] && (segment[1].text in LLVM.PARAM_IGNORABLES)) {
segment.splice(1, 1);
}
if (segment.length == 1) {
@@ -1168,15 +1168,10 @@ function getHeapOffset(offset, type, forceAsm) {
var sz = Runtime.getNativeTypeSize(type);
var shifts = Math.log(sz)/Math.LN2;
offset = '(' + offset + ')';
- if (shifts != 0) {
- if (CHECK_HEAP_ALIGN) {
- return '((CHECK_ALIGN_' + sz + '(' + offset + '|0)|0)>>' + shifts + ')';
- } else {
- return '(' + offset + '>>' + shifts + ')';
- }
+ if (CHECK_HEAP_ALIGN && shifts > 0) {
+ return '((CHECK_ALIGN_' + sz + '(' + offset + '|0)|0)>>' + shifts + ')';
} else {
- // we need to guard against overflows here, HEAP[U]8 expects a guaranteed int
- return isJSVar(offset) ? offset : '(' + offset + '|0)';
+ return '(' + offset + '>>' + shifts + ')';
}
}
@@ -2040,7 +2035,7 @@ function finalizeLLVMParameter(param, noIndexizeFunctions) {
} else if (param.intertype == 'mathop') {
return processMathop(param);
} else if (param.intertype === 'vector') {
- return getVectorBaseType(param.type) + '32x4(' + param.idents.join(',') + ')';
+ return 'SIMD.' + getVectorBaseType(param.type) + '32x4(' + param.idents.join(',') + ')';
} else {
throw 'invalid llvm parameter: ' + param.intertype;
}
@@ -2705,7 +2700,7 @@ var simdLane = ['x', 'y', 'z', 'w'];
function ensureVector(ident, base) {
Types.usesSIMD = true;
- return ident == 0 ? base + '32x4.splat(0)' : ident;
+ return ident == 0 ? 'SIMD.' + base + '32x4.splat(0)' : ident;
}
function ensureValidFFIType(type) {
diff --git a/src/preamble.js b/src/preamble.js
index 89ab5026..ae58e7e0 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -41,13 +41,13 @@ var ACCEPTABLE_SAFE_HEAP_ERRORS = 0;
function SAFE_HEAP_ACCESS(dest, type, store, ignore, storeValue) {
//if (dest === A_NUMBER) Module.print ([dest, type, store, ignore, storeValue] + ' ' + stackTrace()); // Something like this may be useful, in debugging
- assert(dest > 0, 'segmentation fault');
+ if (dest <= 0) abort('segmentation fault ' + (store ? ('storing value ' + storeValue) : 'loading') + ' type ' + type + ' at address ' + dest);
#if USE_TYPED_ARRAYS
// When using typed arrays, reads over the top of TOTAL_MEMORY will fail silently, so we must
// correct that by growing TOTAL_MEMORY as needed. Without typed arrays, memory is a normal
// JS array so it will work (potentially slowly, depending on the engine).
- assert(ignore || dest < Math.max(DYNAMICTOP, STATICTOP));
+ if (!ignore && dest >= Math.max(DYNAMICTOP, STATICTOP)) abort('segmentation fault ' + (store ? ('storing value ' + storeValue) : 'loading') + ' type ' + type + ' at address ' + dest + '. Heap ends at address ' + Math.max(DYNAMICTOP, STATICTOP));
assert(ignore || DYNAMICTOP <= TOTAL_MEMORY);
#endif
@@ -186,17 +186,17 @@ function SAFE_HEAP_STORE(dest, value, bytes, isFloat) {
#if SAFE_HEAP_LOG
Module.print('SAFE_HEAP store: ' + [dest, value, bytes, isFloat]);
#endif
- assert(dest > 0, 'segmentation fault');
- assert(dest % bytes === 0, 'alignment error');
- assert(dest < Math.max(DYNAMICTOP, STATICTOP), 'segmentation fault (high)');
+ if (dest <= 0) abort('segmentation fault storing ' + bytes + ' bytes to address ' + dest);
+ if (dest % bytes !== 0) abort('alignment error storing to address ' + dest + ', which was expected to be aligned to a multiple of ' + bytes);
+ if (dest + bytes > Math.max(DYNAMICTOP, STATICTOP)) abort('segmentation fault, exceeded the top of the available heap when storing ' + bytes + ' bytes to address ' + dest + '. STATICTOP=' + STATICTOP + ', DYNAMICTOP=' + DYNAMICTOP);
assert(DYNAMICTOP <= TOTAL_MEMORY);
setValue(dest, value, getSafeHeapType(bytes, isFloat), 1);
}
function SAFE_HEAP_LOAD(dest, bytes, isFloat, unsigned) {
- assert(dest > 0, 'segmentation fault');
- assert(dest % bytes === 0, 'alignment error');
- assert(dest < Math.max(DYNAMICTOP, STATICTOP), 'segmentation fault (high)');
+ if (dest <= 0) abort('segmentation fault loading ' + bytes + ' bytes from address ' + dest);
+ if (dest % bytes !== 0) abort('alignment error loading from address ' + dest + ', which was expected to be aligned to a multiple of ' + bytes);
+ if (dest + bytes > Math.max(DYNAMICTOP, STATICTOP)) abort('segmentation fault, exceeded the top of the available heap when loading ' + bytes + ' bytes from address ' + dest + '. STATICTOP=' + STATICTOP + ', DYNAMICTOP=' + DYNAMICTOP);
assert(DYNAMICTOP <= TOTAL_MEMORY);
var type = getSafeHeapType(bytes, isFloat);
var ret = getValue(dest, type, 1);
@@ -207,6 +207,14 @@ function SAFE_HEAP_LOAD(dest, bytes, isFloat, unsigned) {
return ret;
}
+function SAFE_FT_MASK(value, mask) {
+ var ret = value & mask;
+ if (ret !== value) {
+ abort('Function table mask error: function pointer is ' + value + ' which is masked by ' + mask + ', the likely cause of this is that the function pointer is being called by the wrong type.');
+ }
+ return ret;
+}
+
#endif
#endif
@@ -302,86 +310,168 @@ function assert(condition, text) {
var globalScope = this;
-// C calling interface. A convenient way to call C functions (in C files, or
-// defined with extern "C").
-//
-// Note: LLVM optimizations can inline and remove functions, after which you will not be
-// able to call them. Closure can also do so. To avoid that, add your function to
-// the exports using something like
-//
-// -s EXPORTED_FUNCTIONS='["_main", "_myfunc"]'
-//
-// @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C")
-// @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and
-// 'array' for JavaScript arrays and typed arrays; note that arrays are 8-bit).
-// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType,
-// except that 'array' is not possible (there is no way for us to know the length of the array)
-// @param args An array of the arguments to the function, as native JS values (as in returnType)
-// Note that string arguments will be stored on the stack (the JS string will become a C string on the stack).
-// @return The return value, as a native JS value (as in returnType)
-function ccall(ident, returnType, argTypes, args) {
- return ccallFunc(getCFunc(ident), returnType, argTypes, args);
-}
-Module["ccall"] = ccall;
-
// Returns the C function with a specified identifier (for C++, you need to do manual name mangling)
function getCFunc(ident) {
- try {
- var func = Module['_' + ident]; // closure exported function
- if (!func) func = eval('_' + ident); // explicit lookup
- } catch(e) {
+ var func = Module['_' + ident]; // closure exported function
+ if (!func) {
+#if NO_DYNAMIC_EXECUTION == 0
+ try {
+ func = eval('_' + ident); // explicit lookup
+ } catch(e) {}
+#else
+ abort('NO_DYNAMIC_EXECUTION was set, cannot eval - ccall/cwrap are not functional');
+#endif
}
assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)');
return func;
}
-// Internal function that does a C call using a function, not an identifier
-function ccallFunc(func, returnType, argTypes, args) {
+var cwrap, ccall;
+(function(){
var stack = 0;
- function toC(value, type) {
- if (type == 'string') {
- if (value === null || value === undefined || value === 0) return 0; // null string
- value = intArrayFromString(value);
- type = 'array';
- }
- if (type == 'array') {
- if (!stack) stack = Runtime.stackSave();
- var ret = Runtime.stackAlloc(value.length);
- writeArrayToMemory(value, ret);
+ var JSfuncs = {
+ 'stackSave' : function() {
+ stack = Runtime.stackSave();
+ },
+ 'stackRestore' : function() {
+ Runtime.stackRestore(stack);
+ },
+ // type conversion from js to c
+ 'arrayToC' : function(arr) {
+ var ret = Runtime.stackAlloc(arr.length);
+ writeArrayToMemory(arr, ret);
+ return ret;
+ },
+ 'stringToC' : function(str) {
+ var ret = 0;
+ if (str !== null && str !== undefined && str !== 0) { // null string
+ ret = Runtime.stackAlloc(str.length + 1); // +1 for the trailing '\0'
+ writeStringToMemory(str, ret);
+ }
return ret;
}
- return value;
- }
- function fromC(value, type) {
- if (type == 'string') {
- return Pointer_stringify(value);
+ };
+ // For fast lookup of conversion functions
+ var toC = {'string' : JSfuncs['stringToC'], 'array' : JSfuncs['arrayToC']};
+
+ // C calling interface. A convenient way to call C functions (in C files, or
+ // defined with extern "C").
+ //
+ // Note: ccall/cwrap use the C stack for temporary values. If you pass a string
+ // then it is only alive until the call is complete. If the code being
+ // called saves the pointer to be used later, it may point to invalid
+ // data. If you need a string to live forever, you can create it (and
+ // must later delete it manually!) using malloc and writeStringToMemory,
+ // for example.
+ //
+ // Note: LLVM optimizations can inline and remove functions, after which you will not be
+ // able to call them. Closure can also do so. To avoid that, add your function to
+ // the exports using something like
+ //
+ // -s EXPORTED_FUNCTIONS='["_main", "_myfunc"]'
+ //
+ // @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C")
+ // @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and
+ // 'array' for JavaScript arrays and typed arrays; note that arrays are 8-bit).
+ // @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType,
+ // except that 'array' is not possible (there is no way for us to know the length of the array)
+ // @param args An array of the arguments to the function, as native JS values (as in returnType)
+ // Note that string arguments will be stored on the stack (the JS string will become a C string on the stack).
+ // @return The return value, as a native JS value (as in returnType)
+ ccall = function ccallFunc(ident, returnType, argTypes, args) {
+ var func = getCFunc(ident);
+ var cArgs = [];
+#if ASSERTIONS
+ assert(returnType !== 'array', 'Return type should not be "array".');
+#endif
+ if (args) {
+ for (var i = 0; i < args.length; i++) {
+ var converter = toC[argTypes[i]];
+ if (converter) {
+ if (stack === 0) stack = Runtime.stackSave();
+ cArgs[i] = converter(args[i]);
+ } else {
+ cArgs[i] = args[i];
+ }
+ }
}
- assert(type != 'array');
- return value;
+ var ret = func.apply(null, cArgs);
+ if (returnType === 'string') ret = Pointer_stringify(ret);
+ if (stack !== 0) JSfuncs['stackRestore']();
+ return ret;
}
- var i = 0;
- var cArgs = args ? args.map(function(arg) {
- return toC(arg, argTypes[i++]);
- }) : [];
- var ret = fromC(func.apply(null, cArgs), returnType);
- if (stack) Runtime.stackRestore(stack);
- return ret;
-}
-// Returns a native JS wrapper for a C function. This is similar to ccall, but
-// returns a function you can call repeatedly in a normal way. For example:
-//
-// var my_function = cwrap('my_c_function', 'number', ['number', 'number']);
-// alert(my_function(5, 22));
-// alert(my_function(99, 12));
-//
-function cwrap(ident, returnType, argTypes) {
- var func = getCFunc(ident);
- return function() {
- return ccallFunc(func, returnType, argTypes, Array.prototype.slice.call(arguments));
+ var sourceRegex = /^function\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/;
+ function parseJSFunc(jsfunc) {
+ // Match the body and the return value of a javascript function source
+ var parsed = jsfunc.toString().match(sourceRegex).slice(1);
+ return {arguments : parsed[0], body : parsed[1], returnValue: parsed[2]}
}
-}
+ var JSsource = {};
+ for (var fun in JSfuncs) {
+ if (JSfuncs.hasOwnProperty(fun)) {
+ // Elements of toCsource are arrays of three items:
+ // the code, and the return value
+ JSsource[fun] = parseJSFunc(JSfuncs[fun]);
+ }
+ }
+ // Returns a native JS wrapper for a C function. This is similar to ccall, but
+ // returns a function you can call repeatedly in a normal way. For example:
+ //
+ // var my_function = cwrap('my_c_function', 'number', ['number', 'number']);
+ // alert(my_function(5, 22));
+ // alert(my_function(99, 12));
+ //
+ cwrap = function cwrap(ident, returnType, argTypes) {
+ var cfunc = getCFunc(ident);
+ // When the function takes numbers and returns a number, we can just return
+ // the original function
+ var numericArgs = argTypes.every(function(type){ return type === 'number'});
+ var numericRet = (returnType !== 'string');
+ if ( numericRet && numericArgs) {
+ return cfunc;
+ }
+ // Creation of the arguments list (["$1","$2",...,"$nargs"])
+ var argNames = argTypes.map(function(x,i){return '$'+i});
+ var funcstr = "(function(" + argNames.join(',') + ") {";
+ var nargs = argTypes.length;
+ if (!numericArgs) {
+ // Generate the code needed to convert the arguments from javascript
+ // values to pointers
+ funcstr += JSsource['stackSave'].body + ';';
+ for (var i = 0; i < nargs; i++) {
+ var arg = argNames[i], type = argTypes[i];
+ if (type === 'number') continue;
+ var convertCode = JSsource[type + 'ToC']; // [code, return]
+ funcstr += 'var ' + convertCode.arguments + ' = ' + arg + ';';
+ funcstr += convertCode.body + ';';
+ funcstr += arg + '=' + convertCode.returnValue + ';';
+ }
+ }
+
+ // When the code is compressed, the name of cfunc is not literally 'cfunc' anymore
+ var cfuncname = parseJSFunc(function(){return cfunc}).returnValue;
+ // Call the function
+ funcstr += 'var ret = ' + cfuncname + '(' + argNames.join(',') + ');';
+ if (!numericRet) { // Return type can only by 'string' or 'number'
+ // Convert the result to a string
+ var strgfy = parseJSFunc(function(){return Pointer_stringify}).returnValue;
+ funcstr += 'ret = ' + strgfy + '(ret);';
+ }
+ if (!numericArgs) {
+ // If we had a stack, restore it
+ funcstr += JSsource['stackRestore'].body + ';';
+ }
+ funcstr += 'return ret})';
+#if NO_DYNAMIC_EXECUTION == 0
+ return eval(funcstr);
+#else
+ abort('NO_DYNAMIC_EXECUTION was set, cannot eval - ccall is not functional');
+#endif
+ };
+})();
Module["cwrap"] = cwrap;
+Module["ccall"] = ccall;
// Sets a value in memory in a dynamic way at run-time. Uses the
// type data. This is the same as makeSetValue, except that
diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp
index 780a6d59..9e469ec4 100644
--- a/src/relooper/Relooper.cpp
+++ b/src/relooper/Relooper.cpp
@@ -17,6 +17,10 @@
typedef std::string ministring;
#endif
+// uncomment these out to get LLVM errs() debugging support
+//#include <llvm/Support/raw_ostream.h>
+//using namespace llvm;
+
template <class T, class U> static bool contains(const T& container, const U& contained) {
return container.count(contained);
}
@@ -202,6 +206,7 @@ void Block::Render(bool InLoop) {
if (Fused) {
PrintDebug("Fusing Multiple to Simple\n");
Parent->Next = Parent->Next->Next;
+ Fused->UseSwitch = false; // TODO: emit switches here
Fused->RenderLoopPrefix();
// When the Multiple has the same number of groups as we have branches,
@@ -243,7 +248,7 @@ void Block::Render(bool InLoop) {
Details = ProcessedBranchesOut[DefaultTarget];
}
bool SetCurrLabel = (SetLabel && Target->IsCheckedMultipleEntry) || ForceSetLabel;
- bool HasFusedContent = Fused && contains(Fused->InnerMap, Target);
+ bool HasFusedContent = Fused && contains(Fused->InnerMap, Target->Id);
bool HasContent = SetCurrLabel || Details->Type != Branch::Direct || HasFusedContent || Details->Code;
if (iter != ProcessedBranchesOut.end()) {
// If there is nothing to show in this branch, omit the condition
@@ -286,7 +291,7 @@ void Block::Render(bool InLoop) {
if (!First) Indenter::Indent();
Details->Render(Target, SetCurrLabel);
if (HasFusedContent) {
- Fused->InnerMap.find(Target)->second->Render(InLoop);
+ Fused->InnerMap.find(Target->Id)->second->Render(InLoop);
} else if (Details->Type == Branch::Nested) {
// Nest the parent content here, and remove it from showing up afterwards as Next
assert(Parent->Next);
@@ -312,18 +317,24 @@ void Block::Render(bool InLoop) {
// MultipleShape
void MultipleShape::RenderLoopPrefix() {
- if (NeedLoop) {
- if (Labeled) {
- PrintIndented("L%d: do {\n", Id);
+ if (Breaks) {
+ if (UseSwitch) {
+ if (Labeled) {
+ PrintIndented("L%d: ", Id);
+ }
} else {
- PrintIndented("do {\n");
+ if (Labeled) {
+ PrintIndented("L%d: do {\n", Id);
+ } else {
+ PrintIndented("do {\n");
+ }
+ Indenter::Indent();
}
- Indenter::Indent();
}
}
void MultipleShape::RenderLoopPostfix() {
- if (NeedLoop) {
+ if (Breaks && !UseSwitch) {
Indenter::Unindent();
PrintIndented("} while(0);\n");
}
@@ -332,32 +343,41 @@ void MultipleShape::RenderLoopPostfix() {
void MultipleShape::Render(bool InLoop) {
RenderLoopPrefix();
- // We know that blocks with the same Id were split from the same source, so their contents are identical and they are logically the same, so re-merge them here
- typedef std::map<int, Shape*> IdShapeMap;
- IdShapeMap IdMap;
- for (BlockShapeMap::iterator iter = InnerMap.begin(); iter != InnerMap.end(); iter++) {
- int Id = iter->first->Id;
- IdShapeMap::iterator Test = IdMap.find(Id);
- if (Test != IdMap.end()) {
- assert(Shape::IsSimple(iter->second) && Shape::IsSimple(Test->second)); // we can only merge simple blocks, something horrible has gone wrong if we see anything else
- continue;
+ if (!UseSwitch) {
+ // emit an if-else chain
+ bool First = true;
+ for (IdShapeMap::iterator iter = InnerMap.begin(); iter != InnerMap.end(); iter++) {
+ if (AsmJS) {
+ PrintIndented("%sif ((label|0) == %d) {\n", First ? "" : "else ", iter->first);
+ } else {
+ PrintIndented("%sif (label == %d) {\n", First ? "" : "else ", iter->first);
+ }
+ First = false;
+ Indenter::Indent();
+ iter->second->Render(InLoop);
+ Indenter::Unindent();
+ PrintIndented("}\n");
}
- IdMap[iter->first->Id] = iter->second;
- }
-
- bool First = true;
- for (IdShapeMap::iterator iter = IdMap.begin(); iter != IdMap.end(); iter++) {
+ } else {
+ // emit a switch
if (AsmJS) {
- PrintIndented("%sif ((label|0) == %d) {\n", First ? "" : "else ", iter->first);
+ PrintIndented("switch (label|0) {\n");
} else {
- PrintIndented("%sif (label == %d) {\n", First ? "" : "else ", iter->first);
+ PrintIndented("switch (label) {\n");
}
- First = false;
Indenter::Indent();
- iter->second->Render(InLoop);
+ for (IdShapeMap::iterator iter = InnerMap.begin(); iter != InnerMap.end(); iter++) {
+ PrintIndented("case %d: {\n", iter->first);
+ Indenter::Indent();
+ iter->second->Render(InLoop);
+ PrintIndented("break;\n");
+ Indenter::Unindent();
+ PrintIndented("}\n");
+ }
Indenter::Unindent();
PrintIndented("}\n");
}
+
RenderLoopPostfix();
if (Next) Next->Render(InLoop);
}
@@ -547,7 +567,7 @@ void Relooper::Calculate(Block *Entry) {
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
+ Multiple->Breaks++; // We are breaking out of this Multiple, so need a loop
}
iter++; // carefully increment iter before erasing
Target->BranchesIn.erase(Prior);
@@ -853,7 +873,7 @@ void Relooper::Calculate(Block *Entry) {
iter = Next; // increment carefully because Solipsize can remove us
}
}
- Multiple->InnerMap[CurrEntry] = Process(CurrBlocks, CurrEntries, NULL);
+ Multiple->InnerMap[CurrEntry->Id] = Process(CurrBlocks, CurrEntries, NULL);
// If we are not fused, then our entries will actually be checked
if (!Fused) {
CurrEntry->IsCheckedMultipleEntry = true;
@@ -867,6 +887,11 @@ void Relooper::Calculate(Block *Entry) {
NextEntries.insert(Entry);
}
}
+ // The multiple has been created, we can decide how to implement it
+ if (Multiple->InnerMap.size() >= 10) {
+ Multiple->UseSwitch = true;
+ Multiple->Breaks++; // switch captures breaks
+ }
return Multiple;
}
@@ -1021,7 +1046,7 @@ void Relooper::Calculate(Block *Entry) {
PostOptimizer(Relooper *ParentInit) : Parent(ParentInit), Closure(NULL) {}
#define RECURSE_Multiple(shape, func) \
- for (BlockShapeMap::iterator iter = shape->InnerMap.begin(); iter != shape->InnerMap.end(); iter++) { \
+ for (IdShapeMap::iterator iter = shape->InnerMap.begin(); iter != shape->InnerMap.end(); iter++) { \
func(iter->second); \
}
#define RECURSE_Loop(shape, func) \
@@ -1042,7 +1067,7 @@ void Relooper::Calculate(Block *Entry) {
SHAPE_SWITCH(S, {
Out.insert(Simple->Inner);
}, {
- for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
+ for (IdShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
FollowNaturalFlow(iter->second, Out);
}
FollowNaturalFlow(Multiple->Next, Out);
@@ -1061,7 +1086,7 @@ void Relooper::Calculate(Block *Entry) {
SHAPE_SWITCH(Root, {
}, {
- for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
+ for (IdShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
FindNaturals(iter->second, Root->Natural);
}
}, {
@@ -1072,7 +1097,7 @@ void Relooper::Calculate(Block *Entry) {
// 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, LoopShape *LastLoop=NULL) {
+ void RemoveUnneededFlows(Shape *Root, Shape *Natural=NULL, LoopShape *LastLoop=NULL, unsigned Depth=0) {
BlockSet NaturalBlocks;
FollowNaturalFlow(Natural, NaturalBlocks);
Shape *Next = Root;
@@ -1083,7 +1108,7 @@ void Relooper::Calculate(Block *Entry) {
if (Simple->Inner->BranchVar) LastLoop = NULL; // a switch clears out the loop (TODO: only for breaks, not continue)
if (Simple->Next) {
- if (!Simple->Inner->BranchVar && Simple->Inner->ProcessedBranchesOut.size() == 2) {
+ if (!Simple->Inner->BranchVar && Simple->Inner->ProcessedBranchesOut.size() == 2 && Depth < 20) {
// If there is a next block, we already know at Simple creation time to make direct branches,
// and we can do nothing more in general. But, we try to optimize the case of a break and
// a direct: This would normally be if (break?) { break; } .. but if we
@@ -1111,7 +1136,7 @@ void Relooper::Calculate(Block *Entry) {
if (Details->Type == Branch::Break) {
Details->Type = Branch::Direct;
if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) {
- Multiple->NeedLoop--;
+ Multiple->Breaks--;
}
} else {
assert(Details->Type == Branch::Direct);
@@ -1119,6 +1144,7 @@ void Relooper::Calculate(Block *Entry) {
}
}
}
+ Depth++; // this optimization increases depth, for us and all our next chain (i.e., until this call returns)
}
Next = Simple->Next;
} else {
@@ -1130,24 +1156,24 @@ void Relooper::Calculate(Block *Entry) {
if (Details->Type != Branch::Direct && contains(NaturalBlocks, Target)) { // note: cannot handle split blocks
Details->Type = Branch::Direct;
if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) {
- Multiple->NeedLoop--;
+ Multiple->Breaks--;
}
} else if (Details->Type == Branch::Break && LastLoop && LastLoop->Natural == Details->Ancestor->Natural) {
// it is important to simplify breaks, as simpler breaks enable other optimizations
Details->Labeled = false;
if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) {
- Multiple->NeedLoop--;
+ Multiple->Breaks--;
}
}
}
}
}, {
- for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
- RemoveUnneededFlows(iter->second, Multiple->Next, Multiple->NeedLoop ? NULL : LastLoop);
+ for (IdShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
+ RemoveUnneededFlows(iter->second, Multiple->Next, Multiple->Breaks ? NULL : LastLoop, Depth+1);
}
Next = Multiple->Next;
}, {
- RemoveUnneededFlows(Loop->Inner, Loop->Inner, Loop);
+ RemoveUnneededFlows(Loop->Inner, Loop->Inner, Loop, Depth+1);
Next = Loop->Next;
});
}
@@ -1169,13 +1195,16 @@ void Relooper::Calculate(Block *Entry) {
SHAPE_SWITCH(Root, {
MultipleShape *Fused = Shape::IsMultiple(Root->Next);
// If we are fusing a Multiple with a loop into this Simple, then visit it now
- if (Fused && Fused->NeedLoop) {
+ if (Fused && Fused->Breaks) {
LoopStack.push(Fused);
}
if (Simple->Inner->BranchVar) {
LoopStack.push(NULL); // a switch means breaks are now useless, push a dummy
}
if (Fused) {
+ if (Fused->UseSwitch) {
+ LoopStack.push(NULL); // a switch means breaks are now useless, push a dummy
+ }
RECURSE_Multiple(Fused, FindLabeledLoops);
}
for (BlockBranchMap::iterator iter = Simple->Inner->ProcessedBranchesOut.begin(); iter != Simple->Inner->ProcessedBranchesOut.end(); iter++) {
@@ -1191,10 +1220,13 @@ void Relooper::Calculate(Block *Entry) {
}
}
}
+ if (Fused && Fused->UseSwitch) {
+ LoopStack.pop();
+ }
if (Simple->Inner->BranchVar) {
LoopStack.pop();
}
- if (Fused && Fused->NeedLoop) {
+ if (Fused && Fused->Breaks) {
LoopStack.pop();
}
if (Fused) {
@@ -1203,11 +1235,11 @@ void Relooper::Calculate(Block *Entry) {
Next = Root->Next;
}
}, {
- if (Multiple->NeedLoop) {
+ if (Multiple->Breaks) {
LoopStack.push(Multiple);
}
RECURSE(Multiple, FindLabeledLoops);
- if (Multiple->NeedLoop) {
+ if (Multiple->Breaks) {
LoopStack.pop();
}
Next = Root->Next;
@@ -1290,8 +1322,8 @@ void Debugging::Dump(Shape *S, const char *prefix) {
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);
+ for (IdShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
+ printf(" with entry %d\n", iter->first);
}
}, {
printf("<< Loop\n");
diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h
index 152bae0e..c86e63ac 100644
--- a/src/relooper/Relooper.h
+++ b/src/relooper/Relooper.h
@@ -132,8 +132,6 @@ struct SimpleShape : public Shape {
}
};
-typedef std::map<Block*, Shape*> BlockShapeMap;
-
// A shape that may be implemented with a labeled loop.
struct LabeledShape : public Shape {
bool Labeled; // If we have a loop, whether it needs to be labeled
@@ -141,12 +139,16 @@ struct LabeledShape : public Shape {
LabeledShape(ShapeType TypeInit) : Shape(TypeInit), Labeled(false) {}
};
+// Blocks with the same id were split and are identical, so we just care about ids in Multiple entries
+typedef std::map<int, Shape*> IdShapeMap;
+
struct MultipleShape : public LabeledShape {
- BlockShapeMap InnerMap; // entry block -> shape
- int NeedLoop; // If we have branches, we need a loop. This is a counter of loop requirements,
- // if we optimize it to 0, the loop is unneeded
+ IdShapeMap InnerMap; // entry block ID -> shape
+ int Breaks; // If we have branches on us, we need a loop (or a switch). This is a counter of requirements,
+ // if we optimize it to 0, the loop is unneeded
+ bool UseSwitch; // Whether to switch on label as opposed to an if-else chain
- MultipleShape() : LabeledShape(Multiple), NeedLoop(0) {}
+ MultipleShape() : LabeledShape(Multiple), Breaks(0), UseSwitch(false) {}
void RenderLoopPrefix();
void RenderLoopPostfix();
diff --git a/src/relooper/fuzzer.py b/src/relooper/fuzzer.py
index 18db997e..313f4d5e 100644
--- a/src/relooper/fuzzer.py
+++ b/src/relooper/fuzzer.py
@@ -3,7 +3,7 @@ import random, subprocess, difflib
while True:
# Random decisions
- num = random.randint(2, 250)
+ num = random.randint(2, 500)
density = random.random() * random.random()
decisions = [random.randint(1, num*20) for x in range(num*3)]
branches = [0]*num
@@ -123,14 +123,14 @@ int main() {
open('fuzz.slow.js', 'w').write(slow)
open('fuzz.cpp', 'w').write(fast)
print '_'
- slow_out = subprocess.Popen(['mozjs', '-m', '-n', 'fuzz.slow.js'], stdout=subprocess.PIPE).communicate()[0]
+ slow_out = subprocess.Popen(['mozjs', '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(['mozjs', '-m', '-n', 'fuzz.fast.js'], stdout=subprocess.PIPE).communicate()[0]
+ fast_out = subprocess.Popen(['mozjs', '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 9f3ddceb..f319757b 100644
--- a/src/relooper/test.cpp
+++ b/src/relooper/test.cpp
@@ -1,4 +1,6 @@
+#include <vector>
+
#include "Relooper.h"
int main() {
@@ -435,5 +437,34 @@ int main() {
puts(r.GetOutputBuffer());
}
+
+ if (1) {
+ Relooper::MakeOutputBuffer(10);
+
+ printf("\n\n-- lots of exits to an unwind block, possible nesting --\n\n");
+
+ const int DEPTH = 40;
+
+ std::vector<Block*> blocks;
+ for (int i = 0; i < DEPTH; i++) blocks.push_back(new Block("// block\n", NULL));
+ Block *last = new Block("// last\nreturn;\n", NULL);
+ Block *UW = new Block("// UW\nresumeException();\n\n", NULL);
+
+ for (int i = 0; i < DEPTH; i++) {
+ Block *b = blocks[i];
+ b->AddBranchTo(i+1 < DEPTH ? blocks[i+1] : last, "check()", NULL);
+ b->AddBranchTo(UW, NULL, NULL);
+ }
+
+ Relooper r;
+ for (int i = 0; i < DEPTH; i++) r.AddBlock(blocks[i]);
+ r.AddBlock(last);
+ r.AddBlock(UW);
+
+ r.Calculate(blocks[0]);
+ r.Render();
+
+ puts(r.GetOutputBuffer());
+ }
}
diff --git a/src/relooper/test.txt b/src/relooper/test.txt
index d53aeeb1..2ae331c0 100644
--- a/src/relooper/test.txt
+++ b/src/relooper/test.txt
@@ -417,3 +417,156 @@
}
// block D
+
+
+-- lots of exits to an unwind block, possible nesting --
+
+ // block
+ do {
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (check()) {
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // block
+ if (!(check())) {
+ break;
+ }
+ // last
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } while(0);
+ // UW
+ resumeException();
+
+
diff --git a/src/runtime.js b/src/runtime.js
index 63610d3b..96b12294 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -96,6 +96,15 @@ function unInline(name_, params) {
}
var Runtime = {
+ // When a 64 bit long is returned from a compiled function the least significant
+ // 32 bit word is passed in the return value, but the most significant 32 bit
+ // word is placed in tempRet0. This provides an accessor for that value.
+ setTempRet0: function(value) {
+ tempRet0 = value;
+ },
+ getTempRet0: function() {
+ return tempRet0;
+ },
stackSave: function() {
return STACKTOP;
},
@@ -409,12 +418,16 @@ var Runtime = {
abort('invalid EM_ASM input |' + source + '|. Please use EM_ASM(..code..) (no quotes) or EM_ASM({ ..code($0).. }, input) (to input values)');
}
}
+#if NO_DYNAMIC_EXECUTION == 0
try {
var evalled = eval('(function(' + args.join(',') + '){ ' + source + ' })'); // new Function does not allow upvars in node
} catch(e) {
Module.printErr('error in executing inline EM_ASM code: ' + e + ' on: \n\n' + source + '\n\nwith args |' + args + '| (make sure to use the right one out of EM_ASM, EM_ASM_ARGS, etc.)');
throw e;
}
+#else
+ abort('NO_DYNAMIC_EXECUTION was set, cannot eval, so EM_ASM is not functional');
+#endif
return Runtime.asmConstCache[code] = evalled;
},
diff --git a/src/settings.js b/src/settings.js
index 8b046e95..bdb149e3 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -39,7 +39,7 @@ var CHECK_SIGNS = 0; // Runtime errors for signing issues that need correcting.
var ASSERTIONS = 1; // Whether we should add runtime assertions, for example to
// check that each allocation to the stack does not
- // exceed it's size, whether all allocations (stack and static) are
+ // exceed its 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
@@ -124,13 +124,20 @@ var PRECISE_I32_MUL = 1; // If enabled, i32 multiplication is done with full pre
var PRECISE_F32 = 0; // 0: Use JS numbers for floating-point values. These are 64-bit and do not model C++
// floats exactly, which are 32-bit.
// 1: Model C++ floats precisely, using Math.fround, polyfilling when necessary. This
- // can be slow if the polyfill is used on heavy float32 computation.
+ // can be slow if the polyfill is used on heavy float32 computation. See note on
+ // browser support below.
// 2: Model C++ floats precisely using Math.fround if available in the JS engine, otherwise
// use an empty polyfill. This will have much less of a speed penalty than using the full
// polyfill in cases where engine support is not present. In addition, we can
// remove the empty polyfill calls themselves on the client when generating html,
// which should mean that this gives you the best of both worlds of 0 and 1, and is
// therefore recommended.
+ // XXX Note: To optimize float32-using code, we use the 'const' keyword in the emitted
+ // code. This allows us to avoid unnecessary calls to Math.fround, which would
+ // slow down engines not yet supporting that function. 'const' is present in
+ // all modern browsers, including Firefox, Chrome and Safari, but in IE is only
+ // present in IE11 and above. Therefore if you need to support legacy versions of
+ // IE, you should not enable PRECISE_F32 1 or 2.
var SIMD = 0; // Whether to emit SIMD code ( https://github.com/johnmccutchan/ecmascript_simd )
var CLOSURE_COMPILER = 0; // Whether closure compiling is being run on this output
@@ -338,7 +345,7 @@ var EXPORTED_FUNCTIONS = ['_main', '_malloc'];
var EXPORT_ALL = 0; // If true, we export all the symbols. Note that this does *not* affect LLVM, so it can
// still eliminate functions as dead. This just exports them on the Module object.
var EXPORT_BINDINGS = 0; // Export all bindings generator functions (prefixed with emscripten_bind_). This
- // is necessary to use the bindings generator with asm.js
+ // is necessary to use the WebIDL binder or bindings generator with asm.js
var RETAIN_COMPILER_SETTINGS = 0; // Remembers the values of these settings, and makes them accessible
// through Runtime.getCompilerSetting and emscripten_get_compiler_setting.
// To see what is retained, look for compilerSettings in the generated code.
@@ -495,6 +502,11 @@ var JS_CHUNK_SIZE = 10240; // Used as a maximum size before breaking up expressi
var EXPORT_NAME = 'Module'; // Global variable to export the module as for environments without a standardized module
// loading system (e.g. the browser and SM shell).
+var NO_DYNAMIC_EXECUTION = 0; // When enabled, we do not emit eval() and new Function(), which disables some functionality
+ // (causing runtime errors if attempted to be used), but allows the emitted code to be
+ // acceptable in places that disallow dynamic code execution (chrome packaged app, non-
+ // privileged firefox app, etc.)
+
var RUNNING_JS_OPTS = 0; // whether js opts will be run, after the main compiler
var COMPILER_ASSERTIONS = 0; // costly (slow) compile-time assertions
diff --git a/src/shell.html b/src/shell.html
index 226f12b9..d204bfa6 100644
--- a/src/shell.html
+++ b/src/shell.html
@@ -1245,7 +1245,16 @@
console.error(text);
}
},
- canvas: document.getElementById('canvas'),
+ canvas: (function() {
+ var canvas = document.getElementById('canvas');
+
+ // As a default initial behavior, pop up an alert when webgl context is lost. To make your
+ // application robust, you may want to override this behavior before shipping!
+ // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
+ canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
+
+ return canvas;
+ })(),
setStatus: function(text) {
if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
if (text === Module.setStatus.text) return;
@@ -1273,6 +1282,13 @@
}
};
Module.setStatus('Downloading...');
+ window.onerror = function() {
+ Module.setStatus('Exception thrown, see JavaScript console');
+ spinnerElement.style.display = 'none';
+ Module.setStatus = function(text) {
+ if (text) Module.printErr('[post-exception status] ' + text);
+ };
+ };
</script>
{{{ SCRIPT }}}
</body>
diff --git a/src/shell.js b/src/shell.js
index e1c0eb54..279a3461 100644
--- a/src/shell.js
+++ b/src/shell.js
@@ -96,7 +96,9 @@ else if (ENVIRONMENT_IS_SHELL) {
this['{{{ EXPORT_NAME }}}'] = Module;
+#if CLOSURE_COMPILER
eval("if (typeof gc === 'function' && gc.toString().indexOf('[native code]') > 0) var gc = undefined"); // wipe out the SpiderMonkey shell 'gc' function, which can confuse closure (uses it as a minified name, and it is then initted to a non-falsey value unexpectedly)
+#endif
}
else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
Module['read'] = function read(url) {
@@ -139,7 +141,11 @@ else {
}
function globalEval(x) {
+#if NO_DYNAMIC_EXECUTION == 0
eval.call(null, x);
+#else
+ throw 'NO_DYNAMIC_EXECUTION was set, cannot eval';
+#endif
}
if (!Module['load'] == 'undefined' && Module['read']) {
Module['load'] = function load(f) {
diff --git a/src/shell_minimal.html b/src/shell_minimal.html
index 6f483719..b67c6fdd 100644
--- a/src/shell_minimal.html
+++ b/src/shell_minimal.html
@@ -101,7 +101,16 @@
console.error(text);
}
},
- canvas: document.getElementById('canvas'),
+ canvas: (function() {
+ var canvas = document.getElementById('canvas');
+
+ // As a default initial behavior, pop up an alert when webgl context is lost. To make your
+ // application robust, you may want to override this behavior before shipping!
+ // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
+ canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
+
+ return canvas;
+ })(),
setStatus: function(text) {
if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
if (text === Module.setStatus.text) return;
@@ -129,6 +138,13 @@
}
};
Module.setStatus('Downloading...');
+ window.onerror = function() {
+ Module.setStatus('Exception thrown, see JavaScript console');
+ spinnerElement.style.display = 'none';
+ Module.setStatus = function(text) {
+ if (text) Module.printErr('[post-exception status] ' + text);
+ };
+ };
</script>
{{{ SCRIPT }}}
</body>
diff --git a/src/simd.js b/src/simd.js
index 6e3e3675..d5ff8b15 100644
--- a/src/simd.js
+++ b/src/simd.js
@@ -22,6 +22,9 @@
"use strict";
+// SIMD module.
+var SIMD = {};
+
/**
* Construct a new instance of float32x4 number.
* @param {double} value used for x lane.
@@ -30,9 +33,9 @@
* @param {double} value used for w lane.
* @constructor
*/
-function float32x4(x, y, z, w) {
- if (!(this instanceof float32x4)) {
- return new float32x4(x, y, z, w);
+SIMD.float32x4 = function(x, y, z, w) {
+ if (!(this instanceof SIMD.float32x4)) {
+ return new SIMD.float32x4(x, y, z, w);
}
this.storage_ = new Float32Array(4);
this.storage_[0] = x;
@@ -45,8 +48,8 @@ function float32x4(x, y, z, w) {
* Construct a new instance of float32x4 number with 0.0 in all lanes.
* @constructor
*/
-float32x4.zero = function() {
- return float32x4(0.0, 0.0, 0.0, 0.0);
+SIMD.float32x4.zero = function() {
+ return SIMD.float32x4(0.0, 0.0, 0.0, 0.0);
}
/**
@@ -55,38 +58,10 @@ float32x4.zero = function() {
* @param {double} value used for all lanes.
* @constructor
*/
-float32x4.splat = function(s) {
- return float32x4(s, s, s, s);
+SIMD.float32x4.splat = function(s) {
+ return SIMD.float32x4(s, s, s, s);
}
-Object.defineProperty(float32x4.prototype, 'x', {
- get: function() { return this.storage_[0]; }
-});
-
-Object.defineProperty(float32x4.prototype, 'y', {
- get: function() { return this.storage_[1]; }
-});
-
-Object.defineProperty(float32x4.prototype, 'z', {
- get: function() { return this.storage_[2]; }
-});
-
-Object.defineProperty(float32x4.prototype, 'w',
- { get: function() { return this.storage_[3]; }
-});
-
-/**
- * Extract the sign bit from each lane return them in the first 4 bits.
- */
-Object.defineProperty(float32x4.prototype, 'signMask', {
- get: function() {
- var mx = this.x < 0.0 ? 1 : 0;
- var my = this.y < 0.0 ? 1 : 0;
- var mz = this.z < 0.0 ? 1 : 0;
- var mw = this.w < 0.0 ? 1 : 0;
- return mx | my << 1 | mz << 2 | mw << 3;
- }
-});
/**
* Construct a new instance of int32x4 number.
@@ -96,9 +71,9 @@ Object.defineProperty(float32x4.prototype, 'signMask', {
* @param {integer} 32-bit unsigned value used for w lane.
* @constructor
*/
-function int32x4(x, y, z, w) {
- if (!(this instanceof int32x4)) {
- return new int32x4(x, y, z, w);
+SIMD.int32x4 = function(x, y, z, w) {
+ if (!(this instanceof SIMD.int32x4)) {
+ return new SIMD.int32x4(x, y, z, w);
}
this.storage_ = new Int32Array(4);
this.storage_[0] = x;
@@ -108,6 +83,14 @@ function int32x4(x, y, z, w) {
}
/**
+ * Construct a new instance of int32x4 number with 0 in all lanes.
+ * @constructor
+ */
+SIMD.int32x4.zero = function() {
+ return SIMD.int32x4(0, 0, 0, 0);
+}
+
+/**
* Construct a new instance of int32x4 number with 0xFFFFFFFF or 0x0 in each
* lane, depending on the truth value in x, y, z, and w.
* @param {boolean} flag used for x lane.
@@ -116,11 +99,11 @@ function int32x4(x, y, z, w) {
* @param {boolean} flag used for w lane.
* @constructor
*/
-int32x4.bool = function(x, y, z, w) {
- return int32x4(x ? -1 : 0x0,
- y ? -1 : 0x0,
- z ? -1 : 0x0,
- w ? -1 : 0x0);
+SIMD.int32x4.bool = function(x, y, z, w) {
+ return SIMD.int32x4(x ? -1 : 0x0,
+ y ? -1 : 0x0,
+ z ? -1 : 0x0,
+ w ? -1 : 0x0);
}
/**
@@ -129,746 +112,637 @@ int32x4.bool = function(x, y, z, w) {
* @param {integer} value used for all lanes.
* @constructor
*/
-int32x4.splat = function(s) {
- return int32x4(s, s, s, s);
+SIMD.int32x4.splat = function(s) {
+ return SIMD.int32x4(s, s, s, s);
}
-Object.defineProperty(int32x4.prototype, 'x', {
- get: function() { return this.storage_[0]; }
-});
+/**
+* @return {float32x4} New instance of float32x4 with absolute values of
+* t.
+*/
+SIMD.float32x4.abs = function(t) {
+ return SIMD.float32x4(Math.abs(t.x), Math.abs(t.y), Math.abs(t.z),
+ Math.abs(t.w));
+}
-Object.defineProperty(int32x4.prototype, 'y', {
- get: function() { return this.storage_[1]; }
-});
+/**
+ * @return {float32x4} New instance of float32x4 with negated values of
+ * t.
+ */
+SIMD.float32x4.neg = function(t) {
+ return SIMD.float32x4(-t.x, -t.y, -t.z, -t.w);
+}
-Object.defineProperty(int32x4.prototype, 'z', {
- get: function() { return this.storage_[2]; }
-});
+/**
+ * @return {float32x4} New instance of float32x4 with a + b.
+ */
+SIMD.float32x4.add = function(a, b) {
+ return SIMD.float32x4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
+}
-Object.defineProperty(int32x4.prototype, 'w',
- { get: function() { return this.storage_[3]; }
-});
+/**
+ * @return {float32x4} New instance of float32x4 with a - b.
+ */
+SIMD.float32x4.sub = function(a, b) {
+ return SIMD.float32x4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
+}
-Object.defineProperty(int32x4.prototype, 'flagX', {
- get: function() { return this.storage_[0] != 0x0; }
-});
+/**
+ * @return {float32x4} New instance of float32x4 with a * b.
+ */
+SIMD.float32x4.mul = function(a, b) {
+ return SIMD.float32x4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
+}
-Object.defineProperty(int32x4.prototype, 'flagY', {
- get: function() { return this.storage_[1] != 0x0; }
-});
+/**
+ * @return {float32x4} New instance of float32x4 with a / b.
+ */
+SIMD.float32x4.div = function(a, b) {
+ return SIMD.float32x4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w);
+}
-Object.defineProperty(int32x4.prototype, 'flagZ', {
- get: function() { return this.storage_[2] != 0x0; }
-});
+/**
+ * @return {float32x4} New instance of float32x4 with t's values clamped
+ * between lowerLimit and upperLimit.
+ */
+SIMD.float32x4.clamp = function(t, lowerLimit, upperLimit) {
+ var cx = t.x < lowerLimit.x ? lowerLimit.x : t.x;
+ var cy = t.y < lowerLimit.y ? lowerLimit.y : t.y;
+ var cz = t.z < lowerLimit.z ? lowerLimit.z : t.z;
+ var cw = t.w < lowerLimit.w ? lowerLimit.w : t.w;
+ cx = cx > upperLimit.x ? upperLimit.x : cx;
+ cy = cy > upperLimit.y ? upperLimit.y : cy;
+ cz = cz > upperLimit.z ? upperLimit.z : cz;
+ cw = cw > upperLimit.w ? upperLimit.w : cw;
+ return SIMD.float32x4(cx, cy, cz, cw);
+}
-Object.defineProperty(int32x4.prototype, 'flagW',
- { get: function() { return this.storage_[3] != 0x0; }
-});
+/**
+ * @return {float32x4} New instance of float32x4 with the minimum value of
+ * t and other.
+ */
+SIMD.float32x4.min = function(t, other) {
+ var cx = t.x > other.x ? other.x : t.x;
+ var cy = t.y > other.y ? other.y : t.y;
+ var cz = t.z > other.z ? other.z : t.z;
+ var cw = t.w > other.w ? other.w : t.w;
+ return SIMD.float32x4(cx, cy, cz, cw);
+}
/**
- * Extract the sign bit from each lane return them in the first 4 bits.
+ * @return {float32x4} New instance of float32x4 with the maximum value of
+ * t and other.
*/
-Object.defineProperty(int32x4.prototype, 'signMask', {
- get: function() {
- var mx = (this.storage_[0] & 0x80000000) >>> 31;
- var my = (this.storage_[1] & 0x80000000) >>> 31;
- var mz = (this.storage_[2] & 0x80000000) >>> 31;
- var mw = (this.storage_[3] & 0x80000000) >>> 31;
- return mx | my << 1 | mz << 2 | mw << 3;
- }
-});
+SIMD.float32x4.max = function(t, other) {
+ var cx = t.x < other.x ? other.x : t.x;
+ var cy = t.y < other.y ? other.y : t.y;
+ var cz = t.z < other.z ? other.z : t.z;
+ var cw = t.w < other.w ? other.w : t.w;
+ return SIMD.float32x4(cx, cy, cz, cw);
+}
-function isNumber(o) {
- return typeof o == "number" || (typeof o == "object" && o.constructor === Number);
+/**
+ * @return {float32x4} New instance of float32x4 with reciprocal value of
+ * t.
+ */
+SIMD.float32x4.reciprocal = function(t) {
+ return SIMD.float32x4(1.0 / t.x, 1.0 / t.y, 1.0 / t.z, 1.0 / t.w);
}
-function isTypedArray(o) {
- return (o instanceof Int8Array) ||
- (o instanceof Uint8Array) ||
- (o instanceof Uint8ClampedArray) ||
- (o instanceof Int16Array) ||
- (o instanceof Uint16Array) ||
- (o instanceof Int32Array) ||
- (o instanceof Uint32Array) ||
- (o instanceof Float32Array) ||
- (o instanceof Float64Array) ||
- (o instanceof Float32x4Array);
+/**
+ * @return {float32x4} New instance of float32x4 with square root of the
+ * reciprocal value of t.
+ */
+SIMD.float32x4.reciprocalSqrt = function(t) {
+ return SIMD.float32x4(Math.sqrt(1.0 / t.x), Math.sqrt(1.0 / t.y),
+ Math.sqrt(1.0 / t.z), Math.sqrt(1.0 / t.w));
+}
+/**
+ * @return {float32x4} New instance of float32x4 with values of t
+ * scaled by s.
+ */
+SIMD.float32x4.scale = function(t, s) {
+ return SIMD.float32x4(s * t.x, s * t.y, s * t.z, s * t.w);
}
-function isArrayBuffer(o) {
- return (o instanceof ArrayBuffer);
+/**
+ * @return {float32x4} New instance of float32x4 with square root of
+ * values of t.
+ */
+SIMD.float32x4.sqrt = function(t) {
+ return SIMD.float32x4(Math.sqrt(t.x), Math.sqrt(t.y),
+ Math.sqrt(t.z), Math.sqrt(t.w));
}
-function Float32x4Array(a, b, c) {
- if (isNumber(a)) {
- this.storage_ = new Float32Array(a*4);
- this.length_ = a;
- this.byteOffset_ = 0;
- return;
- } else if (isTypedArray(a)) {
- if (!(a instanceof Float32x4Array)) {
- throw "Copying typed array of non-Float32x4Array is unimplemented.";
- }
- this.storage_ = new Float32Array(a.length * 4);
- this.length_ = a.length;
- this.byteOffset_ = 0;
- // Copy floats.
- for (var i = 0; i < a.length*4; i++) {
- this.storage_[i] = a.storage_[i];
- }
- } else if (isArrayBuffer(a)) {
- if ((b != undefined) && (b % Float32x4Array.BYTES_PER_ELEMENT) != 0) {
- throw "byteOffset must be a multiple of 16.";
- }
- if (c != undefined) {
- c *= 4;
- this.storage_ = new Float32Array(a, b, c);
- }
- else {
- // Note: new Float32Array(a, b) is NOT equivalent to new Float32Array(a, b, undefined)
- this.storage_ = new Float32Array(a, b);
- }
- this.length_ = this.storage_.length / 4;
- this.byteOffset_ = b != undefined ? b : 0;
- } else {
- throw "Unknown type of first argument.";
- }
+/**
+ * @param {float32x4} t An instance of float32x4 to be shuffled.
+ * @param {integer} mask One of the 256 shuffle masks, for example, SIMD.XXXX.
+ * @return {float32x4} New instance of float32x4 with lanes shuffled.
+ */
+SIMD.float32x4.shuffle = function(t, mask) {
+ var _x = (mask) & 0x3;
+ var _y = (mask >> 2) & 0x3;
+ var _z = (mask >> 4) & 0x3;
+ var _w = (mask >> 6) & 0x3;
+ return SIMD.float32x4(t.storage_[_x], t.storage_[_y], t.storage_[_z],
+ t.storage_[_w]);
}
-Object.defineProperty(Float32x4Array.prototype, 'length',
- { get: function() { return this.length_; }
-});
+/**
+ * @param {float32x4} t1 An instance of float32x4 to be shuffled. XY lanes in result
+ * @param {float32x4} t2 An instance of float32x4 to be shuffled. ZW lanes in result
+ * @param {integer} mask One of the 256 shuffle masks, for example, SIMD.XXXX.
+ * @return {float32x4} New instance of float32x4 with lanes shuffled.
+ */
+SIMD.float32x4.shuffleMix = function(t1, t2, mask) {
+ var _x = (mask) & 0x3;
+ var _y = (mask >> 2) & 0x3;
+ var _z = (mask >> 4) & 0x3;
+ var _w = (mask >> 6) & 0x3;
+ return SIMD.float32x4(t1.storage_[_x], t1.storage_[_y], t2.storage_[_z],
+ t2.storage_[_w]);
+}
-Object.defineProperty(Float32x4Array.prototype, 'byteLength',
- { get: function() { return this.length_ * Float32x4Array.BYTES_PER_ELEMENT; }
-});
+/**
+ * @param {double} value used for x lane.
+ * @return {float32x4} New instance of float32x4 with the values in t and
+ * x replaced with {x}.
+ */
+SIMD.float32x4.withX = function(t, x) {
+ return SIMD.float32x4(x, t.y, t.z, t.w);
+}
-Object.defineProperty(Float32x4Array, 'BYTES_PER_ELEMENT',
- { get: function() { return 16; }
-});
+/**
+ * @param {double} value used for y lane.
+ * @return {float32x4} New instance of float32x4 with the values in t and
+ * y replaced with {y}.
+ */
+SIMD.float32x4.withY = function(t, y) {
+ return SIMD.float32x4(t.x, y, t.z, t.w);
+}
-Object.defineProperty(Float32x4Array.prototype, 'BYTES_PER_ELEMENT',
- { get: function() { return 16; }
-});
+/**
+ * @param {double} value used for z lane.
+ * @return {float32x4} New instance of float32x4 with the values in t and
+ * z replaced with {z}.
+ */
+SIMD.float32x4.withZ = function(t, z) {
+ return SIMD.float32x4(t.x, t.y, z, t.w);
+}
-Object.defineProperty(Float32x4Array.prototype, 'byteOffset',
- { get: function() { return this.byteOffset_; }
-});
+/**
+ * @param {double} value used for w lane.
+ * @return {float32x4} New instance of float32x4 with the values in t and
+ * w replaced with {w}.
+ */
+SIMD.float32x4.withW = function(t, w) {
+ return SIMD.float32x4(t.x, t.y, t.z, w);
+}
-Object.defineProperty(Float32x4Array.prototype, 'buffer',
- { get: function() { return this.storage_.buffer; }
-});
+/**
+ * @param {float32x4} t An instance of float32x4.
+ * @param {float32x4} other An instance of float32x4.
+ * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on
+ * the result of t < other.
+ */
+SIMD.float32x4.lessThan = function(t, other) {
+ var cx = t.x < other.x;
+ var cy = t.y < other.y;
+ var cz = t.z < other.z;
+ var cw = t.w < other.w;
+ return SIMD.int32x4.bool(cx, cy, cz, cw);
+}
-Float32x4Array.prototype.getAt = function(i) {
- if (i < 0) {
- throw "Index must be >= 0.";
- }
- if (i >= this.length) {
- throw "Index out of bounds.";
- }
- var x = this.storage_[i*4+0];
- var y = this.storage_[i*4+1];
- var z = this.storage_[i*4+2];
- var w = this.storage_[i*4+3];
- return float32x4(x, y, z, w);
+/**
+ * @param {float32x4} t An instance of float32x4.
+ * @param {float32x4} other An instance of float32x4.
+ * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on
+ * the result of t <= other.
+ */
+SIMD.float32x4.lessThanOrEqual = function(t, other) {
+ var cx = t.x <= other.x;
+ var cy = t.y <= other.y;
+ var cz = t.z <= other.z;
+ var cw = t.w <= other.w;
+ return SIMD.int32x4.bool(cx, cy, cz, cw);
}
-Float32x4Array.prototype.setAt = function(i, v) {
- if (i < 0) {
- throw "Index must be >= 0.";
- }
- if (i >= this.length) {
- throw "Index out of bounds.";
- }
- if (!(v instanceof float32x4)) {
- throw "Value is not a float32x4.";
- }
- this.storage_[i*4+0] = v.x;
- this.storage_[i*4+1] = v.y;
- this.storage_[i*4+2] = v.z;
- this.storage_[i*4+3] = v.w;
+/**
+ * @param {float32x4} t An instance of float32x4.
+ * @param {float32x4} other An instance of float32x4.
+ * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on
+ * the result of t == other.
+ */
+SIMD.float32x4.equal = function(t, other) {
+ var cx = t.x == other.x;
+ var cy = t.y == other.y;
+ var cz = t.z == other.z;
+ var cw = t.w == other.w;
+ return SIMD.int32x4.bool(cx, cy, cz, cw);
}
+/**
+ * @param {float32x4} t An instance of float32x4.
+ * @param {float32x4} other An instance of float32x4.
+ * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on
+ * the result of t != other.
+ */
+SIMD.float32x4.notEqual = function(t, other) {
+ var cx = t.x != other.x;
+ var cy = t.y != other.y;
+ var cz = t.z != other.z;
+ var cw = t.w != other.w;
+ return SIMD.int32x4.bool(cx, cy, cz, cw);
+}
-function Int32x4Array(a, b, c) {
+/**
+ * @param {float32x4} t An instance of float32x4.
+ * @param {float32x4} other An instance of float32x4.
+ * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on
+ * the result of t >= other.
+ */
+SIMD.float32x4.greaterThanOrEqual = function(t, other) {
+ var cx = t.x >= other.x;
+ var cy = t.y >= other.y;
+ var cz = t.z >= other.z;
+ var cw = t.w >= other.w;
+ return SIMD.int32x4.bool(cx, cy, cz, cw);
+}
- function isNumber(o) {
- return typeof o == "number" || (typeof o == "object" && o.constructor === Number);
- }
+/**
+ * @param {float32x4} t An instance of float32x4.
+ * @param {float32x4} other An instance of float32x4.
+ * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on
+ * the result of t > other.
+ */
+SIMD.float32x4.greaterThan = function(t, other) {
+ var cx = t.x > other.x;
+ var cy = t.y > other.y;
+ var cz = t.z > other.z;
+ var cw = t.w > other.w;
+ return SIMD.int32x4.bool(cx, cy, cz, cw);
+}
- function isTypedArray(o) {
- return (o instanceof Int8Array) ||
- (o instanceof Uint8Array) ||
- (o instanceof Uint8ClampedArray) ||
- (o instanceof Int16Array) ||
- (o instanceof Uint16Array) ||
- (o instanceof Int32Array) ||
- (o instanceof Uint32Array) ||
- (o instanceof Float32Array) ||
- (o instanceof Float64Array) ||
- (o instanceof Int32x4Array) ||
- (o instanceof Float32x4Array);
- }
+/**
+ * @param {float32x4} t An instance of float32x4.
+ * @return {int32x4} a bit-wise copy of t as a int32x4.
+ */
+SIMD.float32x4.bitsToInt32x4 = function(t) {
+ var alias = new Int32Array(t.storage_.buffer);
+ return SIMD.int32x4(alias[0], alias[1], alias[2], alias[3]);
+}
- function isArrayBuffer(o) {
- return (o instanceof ArrayBuffer);
- }
+/**
+ * @param {float32x4} t An instance of float32x4.
+ * @return {int32x4} with a integer to float conversion of t.
+ */
+SIMD.float32x4.toInt32x4 = function(t) {
+ var a = SIMD.int32x4(t.storage_[0], t.storage_[1], t.storage_[2],
+ t.storage_[3]);
+ return a;
+}
- if (isNumber(a)) {
- this.storage_ = new Int32Array(a*4);
- this.length_ = a;
- this.byteOffset_ = 0;
- return;
- } else if (isTypedArray(a)) {
- if (!(a instanceof Int32x4Array)) {
- throw "Copying typed array of non-Int32x4Array is unimplemented.";
- }
- this.storage_ = new Int32Array(a.length * 4);
- this.length_ = a.length;
- this.byteOffset_ = 0;
- // Copy floats.
- for (var i = 0; i < a.length*4; i++) {
- this.storage_[i] = a.storage_[i];
- }
- } else if (isArrayBuffer(a)) {
- if ((b != undefined) && (b % Int32x4Array.BYTES_PER_ELEMENT) != 0) {
- throw "byteOffset must be a multiple of 16.";
- }
- if (c != undefined) {
- c *= 4;
- this.storage_ = new Int32Array(a, b, c);
- }
- else {
- // Note: new Int32Array(a, b) is NOT equivalent to new Float32Array(a, b, undefined)
- this.storage_ = new Int32Array(a, b);
- }
- this.length_ = this.storage_.length / 4;
- this.byteOffset_ = b != undefined ? b : 0;
- } else {
- throw "Unknown type of first argument.";
- }
+/**
+ * @param {float32x4} a An instance of float32x4.
+ * @param {float32x4} b An instance of float32x4.
+ * @return {float32x4} New instance of float32x4 with values of a & b.
+ */
+SIMD.float32x4.and = function(a, b) {
+ var aInt = SIMD.float32x4.bitsToInt32x4(a);
+ var bInt = SIMD.float32x4.bitsToInt32x4(b);
+ return SIMD.int32x4.bitsToFloat32x4(SIMD.int32x4.and(aInt, bInt));
}
-Object.defineProperty(Int32x4Array.prototype, 'length',
- { get: function() { return this.length_; }
-});
+/**
+ * @param {float32x4} a An instance of float32x4.
+ * @param {float32x4} b An instance of float32x4.
+ * @return {float32x4} New instance of float32x4 with values of a | b.
+ */
+SIMD.float32x4.or = function(a, b) {
+ var aInt = SIMD.float32x4.bitsToInt32x4(a);
+ var bInt = SIMD.float32x4.bitsToInt32x4(b);
+ return SIMD.int32x4.bitsToFloat32x4(SIMD.int32x4.or(aInt, bInt));
+}
-Object.defineProperty(Int32x4Array.prototype, 'byteLength',
- { get: function() { return this.length_ * Int32x4Array.BYTES_PER_ELEMENT; }
-});
+/**
+ * @param {float32x4} a An instance of float32x4.
+ * @param {float32x4} b An instance of float32x4.
+ * @return {float32x4} New instance of float32x4 with values of a ^ b.
+ */
+SIMD.float32x4.xor = function(a, b) {
+ var aInt = SIMD.float32x4.bitsToInt32x4(a);
+ var bInt = SIMD.float32x4.bitsToInt32x4(b);
+ return SIMD.int32x4.bitsToFloat32x4(SIMD.int32x4.xor(aInt, bInt));
+}
-Object.defineProperty(Int32x4Array, 'BYTES_PER_ELEMENT',
- { get: function() { return 16; }
-});
+/**
+ * @param {float32x4} a An instance of float32x4.
+ * @return {float32x4} New instance of float32x4 with values of ~a.
+ */
+SIMD.float32x4.not = function(a) {
+ var aInt = SIMD.float32x4.bitsToInt32x4(a);
+ return SIMD.int32x4.bitsToFloat32x4(SIMD.int32x4.not(aInt));
+}
-Object.defineProperty(Int32x4Array.prototype, 'BYTES_PER_ELEMENT',
- { get: function() { return 16; }
-});
+/**
+ * @param {int32x4} a An instance of int32x4.
+ * @param {int32x4} b An instance of int32x4.
+ * @return {int32x4} New instance of int32x4 with values of a & b.
+ */
+SIMD.int32x4.and = function(a, b) {
+ return SIMD.int32x4(a.x & b.x, a.y & b.y, a.z & b.z, a.w & b.w);
+}
-Object.defineProperty(Int32x4Array.prototype, 'byteOffset',
- { get: function() { return this.byteOffset_; }
-});
+/**
+ * @param {int32x4} a An instance of int32x4.
+ * @param {int32x4} b An instance of int32x4.
+ * @return {int32x4} New instance of int32x4 with values of a | b.
+ */
+SIMD.int32x4.or = function(a, b) {
+ return SIMD.int32x4(a.x | b.x, a.y | b.y, a.z | b.z, a.w | b.w);
+}
-Object.defineProperty(Int32x4Array.prototype, 'buffer',
- { get: function() { return this.storage_.buffer; }
-});
+/**
+ * @param {int32x4} a An instance of int32x4.
+ * @param {int32x4} b An instance of int32x4.
+ * @return {int32x4} New instance of int32x4 with values of a ^ b.
+ */
+SIMD.int32x4.xor = function(a, b) {
+ return SIMD.int32x4(a.x ^ b.x, a.y ^ b.y, a.z ^ b.z, a.w ^ b.w);
+}
-Int32x4Array.prototype.getAt = function(i) {
- if (i < 0) {
- throw "Index must be >= 0.";
- }
- if (i >= this.length) {
- throw "Index out of bounds.";
- }
- var x = this.storage_[i*4+0];
- var y = this.storage_[i*4+1];
- var z = this.storage_[i*4+2];
- var w = this.storage_[i*4+3];
- return float32x4(x, y, z, w);
+/**
+ * @param {int32x4} t An instance of int32x4.
+ * @return {int32x4} New instance of int32x4 with values of ~t
+ */
+SIMD.int32x4.not = function(t) {
+ return SIMD.int32x4(~t.x, ~t.y, ~t.z, ~t.w);
}
-Int32x4Array.prototype.setAt = function(i, v) {
- if (i < 0) {
- throw "Index must be >= 0.";
- }
- if (i >= this.length) {
- throw "Index out of bounds.";
- }
- if (!(v instanceof int32x4)) {
- throw "Value is not a int32x4.";
- }
- this.storage_[i*4+0] = v.x;
- this.storage_[i*4+1] = v.y;
- this.storage_[i*4+2] = v.z;
- this.storage_[i*4+3] = v.w;
+/**
+ * @param {int32x4} t An instance of int32x4.
+ * @return {int32x4} New instance of int32x4 with values of -t
+ */
+SIMD.int32x4.neg = function(t) {
+ return SIMD.int32x4(-t.x, -t.y, -t.z, -t.w);
}
-var SIMD = (function () {
- return {
- float32x4: {
- /**
- * @return {float32x4} New instance of float32x4 with absolute values of
- * t.
- */
- abs: function(t) {
- return new float32x4(Math.abs(t.x), Math.abs(t.y), Math.abs(t.z),
- Math.abs(t.w));
- },
- /**
- * @return {float32x4} New instance of float32x4 with negated values of
- * t.
- */
- neg: function(t) {
- return new float32x4(-t.x, -t.y, -t.z, -t.w);
- },
- /**
- * @return {float32x4} New instance of float32x4 with a + b.
- */
- add: function(a, b) {
- return new float32x4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
- },
- /**
- * @return {float32x4} New instance of float32x4 with a - b.
- */
- sub: function(a, b) {
- return new float32x4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
- },
- /**
- * @return {float32x4} New instance of float32x4 with a * b.
- */
- mul: function(a, b) {
- return new float32x4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
- },
- /**
- * @return {float32x4} New instance of float32x4 with a / b.
- */
- div: function(a, b) {
- return new float32x4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w);
- },
- /**
- * @return {float32x4} New instance of float32x4 with t's values clamped
- * between lowerLimit and upperLimit.
- */
- clamp: function(t, lowerLimit, upperLimit) {
- var cx = t.x < lowerLimit.x ? lowerLimit.x : t.x;
- var cy = t.y < lowerLimit.y ? lowerLimit.y : t.y;
- var cz = t.z < lowerLimit.z ? lowerLimit.z : t.z;
- var cw = t.w < lowerLimit.w ? lowerLimit.w : t.w;
- cx = cx > upperLimit.x ? upperLimit.x : cx;
- cy = cy > upperLimit.y ? upperLimit.y : cy;
- cz = cz > upperLimit.z ? upperLimit.z : cz;
- cw = cw > upperLimit.w ? upperLimit.w : cw;
- return new float32x4(cx, cy, cz, cw);
- },
- /**
- * @return {float32x4} New instance of float32x4 with the minimum value of
- * t and other.
- */
- min: function(t, other) {
- var cx = t.x > other.x ? other.x : t.x;
- var cy = t.y > other.y ? other.y : t.y;
- var cz = t.z > other.z ? other.z : t.z;
- var cw = t.w > other.w ? other.w : t.w;
- return new float32x4(cx, cy, cz, cw);
- },
- /**
- * @return {float32x4} New instance of float32x4 with the maximum value of
- * t and other.
- */
- max: function(t, other) {
- var cx = t.x < other.x ? other.x : t.x;
- var cy = t.y < other.y ? other.y : t.y;
- var cz = t.z < other.z ? other.z : t.z;
- var cw = t.w < other.w ? other.w : t.w;
- return new float32x4(cx, cy, cz, cw);
- },
- /**
- * @return {float32x4} New instance of float32x4 with reciprocal value of
- * t.
- */
- reciprocal: function(t) {
- return new float32x4(1.0 / t.x, 1.0 / t.y, 1.0 / t.z, 1.0 / t.w);
- },
- /**
- * @return {float32x4} New instance of float32x4 with square root of the
- * reciprocal value of t.
- */
- reciprocalSqrt: function(t) {
- return new float32x4(Math.sqrt(1.0 / t.x), Math.sqrt(1.0 / t.y),
- Math.sqrt(1.0 / t.z), Math.sqrt(1.0 / t.w));
- },
- /**
- * @return {float32x4} New instance of float32x4 with values of t
- * scaled by s.
- */
- scale: function(t, s) {
- return new float32x4(s * t.x, s * t.y, s * t.z, s * t.w);
- },
- /**
- * @return {float32x4} New instance of float32x4 with square root of
- * values of t.
- */
- sqrt: function(t) {
- return new float32x4(Math.sqrt(t.x), Math.sqrt(t.y),
- Math.sqrt(t.z), Math.sqrt(t.w));
- },
- /**
- * @param {float32x4} t An instance of float32x4 to be shuffled.
- * @param {integer} mask One of the 256 shuffle masks, for example, SIMD.XXXX.
- * @return {float32x4} New instance of float32x4 with lanes shuffled.
- */
- shuffle: function(t, mask) {
- var _x = (mask) & 0x3;
- var _y = (mask >> 2) & 0x3;
- var _z = (mask >> 4) & 0x3;
- var _w = (mask >> 6) & 0x3;
- return new float32x4(t.storage_[_x], t.storage_[_y], t.storage_[_z],
- t.storage_[_w]);
- },
- /**
- * @param {float32x4} t1 An instance of float32x4 to be shuffled. XY lanes in result
- * @param {float32x4} t2 An instance of float32x4 to be shuffled. ZW lanes in result
- * @param {integer} mask One of the 256 shuffle masks, for example, SIMD.XXXX.
- * @return {float32x4} New instance of float32x4 with lanes shuffled.
- */
- shuffleMix: function(t1, t2, mask) {
- var _x = (mask) & 0x3;
- var _y = (mask >> 2) & 0x3;
- var _z = (mask >> 4) & 0x3;
- var _w = (mask >> 6) & 0x3;
- return new float32x4(t1.storage_[_x], t1.storage_[_y], t2.storage_[_z],
- t2.storage_[_w]);
- },
- /**
- * @param {double} value used for x lane.
- * @return {float32x4} New instance of float32x4 with the values in t and
- * x replaced with {x}.
- */
- withX: function(t, x) {
- return new float32x4(x, t.y, t.z, t.w);
- },
- /**
- * @param {double} value used for y lane.
- * @return {float32x4} New instance of float32x4 with the values in t and
- * y replaced with {y}.
- */
- withY: function(t, y) {
- return new float32x4(t.x, y, t.z, t.w);
- },
- /**
- * @param {double} value used for z lane.
- * @return {float32x4} New instance of float32x4 with the values in t and
- * z replaced with {z}.
- */
- withZ: function(t, z) {
- return new float32x4(t.x, t.y, z, t.w);
- },
- /**
- * @param {double} value used for w lane.
- * @return {float32x4} New instance of float32x4 with the values in t and
- * w replaced with {w}.
- */
- withW: function(t, w) {
- return new float32x4(t.x, t.y, t.z, w);
- },
- /**
- * @param {float32x4} t An instance of float32x4.
- * @param {float32x4} other An instance of float32x4.
- * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on
- * the result of t < other.
- */
- lessThan: function(t, other) {
- var cx = t.x < other.x;
- var cy = t.y < other.y;
- var cz = t.z < other.z;
- var cw = t.w < other.w;
- return int32x4.bool(cx, cy, cz, cw);
- },
- /**
- * @param {float32x4} t An instance of float32x4.
- * @param {float32x4} other An instance of float32x4.
- * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on
- * the result of t <= other.
- */
- lessThanOrEqual: function(t, other) {
- var cx = t.x <= other.x;
- var cy = t.y <= other.y;
- var cz = t.z <= other.z;
- var cw = t.w <= other.w;
- return int32x4.bool(cx, cy, cz, cw);
- },
- /**
- * @param {float32x4} t An instance of float32x4.
- * @param {float32x4} other An instance of float32x4.
- * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on
- * the result of t == other.
- */
- equal: function(t, other) {
- var cx = t.x == other.x;
- var cy = t.y == other.y;
- var cz = t.z == other.z;
- var cw = t.w == other.w;
- return int32x4.bool(cx, cy, cz, cw);
- },
- /**
- * @param {float32x4} t An instance of float32x4.
- * @param {float32x4} other An instance of float32x4.
- * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on
- * the result of t != other.
- */
- notEqual: function(t, other) {
- var cx = t.x != other.x;
- var cy = t.y != other.y;
- var cz = t.z != other.z;
- var cw = t.w != other.w;
- return int32x4.bool(cx, cy, cz, cw);
- },
- /**
- * @param {float32x4} t An instance of float32x4.
- * @param {float32x4} other An instance of float32x4.
- * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on
- * the result of t >= other.
- */
- greaterThanOrEqual: function(t, other) {
- var cx = t.x >= other.x;
- var cy = t.y >= other.y;
- var cz = t.z >= other.z;
- var cw = t.w >= other.w;
- return int32x4.bool(cx, cy, cz, cw);
- },
- /**
- * @param {float32x4} t An instance of float32x4.
- * @param {float32x4} other An instance of float32x4.
- * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on
- * the result of t > other.
- */
- greaterThan: function(t, other) {
- var cx = t.x > other.x;
- var cy = t.y > other.y;
- var cz = t.z > other.z;
- var cw = t.w > other.w;
- return int32x4.bool(cx, cy, cz, cw);
- },
- /**
- * @param {float32x4} t An instance of float32x4.
- * @return {int32x4} a bit-wise copy of t as a int32x4.
- */
- bitsToInt32x4: function(t) {
- var alias = new Int32Array(t.storage_.buffer);
- return new int32x4(alias[0], alias[1], alias[2], alias[3]);
- },
- /**
- * @param {float32x4} t An instance of float32x4.
- * @return {int32x4} with a integer to float conversion of t.
- */
- toInt32x4: function(t) {
- var a = new int32x4(t.storage_[0], t.storage_[1], t.storage_[2],
- t.storage_[3]);
- return a;
- }
- },
- int32x4: {
- /**
- * @param {int32x4} a An instance of int32x4.
- * @param {int32x4} b An instance of int32x4.
- * @return {int32x4} New instance of int32x4 with values of a & b.
- */
- and: function(a, b) {
- return new int32x4(a.x & b.x, a.y & b.y, a.z & b.z, a.w & b.w);
- },
- /**
- * @param {int32x4} a An instance of int32x4.
- * @param {int32x4} b An instance of int32x4.
- * @return {int32x4} New instance of int32x4 with values of a | b.
- */
- or: function(a, b) {
- return new int32x4(a.x | b.x, a.y | b.y, a.z | b.z, a.w | b.w);
- },
- /**
- * @param {int32x4} a An instance of int32x4.
- * @param {int32x4} b An instance of int32x4.
- * @return {int32x4} New instance of int32x4 with values of a ^ b.
- */
- xor: function(a, b) {
- return new int32x4(a.x ^ b.x, a.y ^ b.y, a.z ^ b.z, a.w ^ b.w);
- },
- /**
- * @param {int32x4} t An instance of int32x4.
- * @return {int32x4} New instance of int32x4 with values of ~t
- */
- not: function(t) {
- return new int32x4(~t.x, ~t.y, ~t.z, ~t.w);
- },
- /**
- * @param {int32x4} t An instance of int32x4.
- * @return {int32x4} New instance of int32x4 with values of -t
- */
- neg: function(t) {
- return new int32x4(-t.x, -t.y, -t.z, -t.w);
- },
- /**
- * @param {int32x4} a An instance of int32x4.
- * @param {int32x4} b An instance of int32x4.
- * @return {int32x4} New instance of int32x4 with values of a + b.
- */
- add: function(a, b) {
- return new int32x4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
- },
- /**
- * @param {int32x4} a An instance of int32x4.
- * @param {int32x4} b An instance of int32x4.
- * @return {int32x4} New instance of int32x4 with values of a - b.
- */
- sub: function(a, b) {
- return new int32x4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
- },
- /**
- * @param {int32x4} a An instance of int32x4.
- * @param {int32x4} b An instance of int32x4.
- * @return {int32x4} New instance of int32x4 with values of a * b.
- */
- mul: function(a, b) {
- return new int32x4(Math.imul(a.x, b.x), Math.imul(a.y, b.y),
- Math.imul(a.z, b.z), Math.imul(a.w, b.w));
- },
- /**
- * @param {int32x4} t An instance of float32x4 to be shuffled.
- * @param {integer} mask One of the 256 shuffle masks, for example, SIMD.XXXX.
- * @return {int32x4} New instance of float32x4 with lanes shuffled.
- */
- shuffle: function(t, mask) {
- var _x = (mask) & 0x3;
- var _y = (mask >> 2) & 0x3;
- var _z = (mask >> 4) & 0x3;
- var _w = (mask >> 6) & 0x3;
- return new int32x4(t.storage_[_x], t.storage_[_y], t.storage_[_z],
- t.storage_[_w]);
- },
- /**
- * @param {int32x4} t1 An instance of float32x4 to be shuffled. XY lanes in result
- * @param {int32x4} t2 An instance of float32x4 to be shuffled. ZW lanes in result
- * @param {integer} mask One of the 256 shuffle masks, for example, SIMD.XXXX.
- * @return {int32x4} New instance of float32x4 with lanes shuffled.
- */
- shuffleMix: function(t1, t2, mask) {
- var _x = (mask) & 0x3;
- var _y = (mask >> 2) & 0x3;
- var _z = (mask >> 4) & 0x3;
- var _w = (mask >> 6) & 0x3;
- return new int32x4(t1.storage_[_x], t1.storage_[_y], t2.storage_[_z],
- t2.storage_[_w]);
- },
- /**
- * @param {float32x4}
- */
- select: function(t, trueValue, falseValue) {
- var tv = SIMD.float32x4.bitsToInt32x4(trueValue);
- var fv = SIMD.float32x4.bitsToInt32x4(falseValue);
- var tr = SIMD.int32x4.and(t, tv);
- var fr = SIMD.int32x4.and(SIMD.int32x4.not(t), fv);
- return SIMD.int32x4.bitsToFloat32x4(SIMD.int32x4.or(tr, fr));
- },
- /**
- * @param {int32x4} t An instance of int32x4.
- * @param {integer} 32-bit value used for x lane.
- * @return {int32x4} New instance of int32x4 with the values in t and
- * x lane replaced with {x}.
- */
- withX: function(t, x) {
- return new int32x4(x, t.y, t.z, t.w);
- },
- /**
- * param {int32x4} t An instance of int32x4.
- * @param {integer} 32-bit value used for y lane.
- * @return {int32x4} New instance of int32x4 with the values in t and
- * y lane replaced with {y}.
- */
- withY: function(t, y) {
- return new int32x4(t.x, y, t.z, t.w);
- },
- /**
- * @param {int32x4} t An instance of int32x4.
- * @param {integer} 32-bit value used for z lane.
- * @return {int32x4} New instance of int32x4 with the values in t and
- * z lane replaced with {z}.
- */
- withZ: function(t, z) {
- return new int32x4(t.x, t.y, z, t.w);
- },
- /**
- * @param {integer} 32-bit value used for w lane.
- * @return {int32x4} New instance of int32x4 with the values in t and
- * w lane replaced with {w}.
- */
- withW: function(t, w) {
- return new int32x4(t.x, t.y, t.z, w);
- },
- /**
- * @param {int32x4} t An instance of int32x4.
- * @param {boolean} x flag used for x lane.
- * @return {int32x4} New instance of int32x4 with the values in t and
- * x lane replaced with {x}.
- */
- withFlagX: function(t, flagX) {
- var x = flagX ? 0xFFFFFFFF : 0x0;
- return new int32x4(x, t.y, t.z, t.w);
- },
- /**
- * @param {int32x4} t An instance of int32x4.
- * @param {boolean} y flag used for y lane.
- * @return {int32x4} New instance of int32x4 with the values in t and
- * y lane replaced with {y}.
- */
- withFlagY: function(t, flagY) {
- var y = flagY ? 0xFFFFFFFF : 0x0;
- return new int32x4(t.x, y, t.z, t.w);
- },
- /**
- * @param {int32x4} t An instance of int32x4.
- * @param {boolean} z flag used for z lane.
- * @return {int32x4} New instance of int32x4 with the values in t and
- * z lane replaced with {z}.
- */
- withFlagZ: function(t, flagZ) {
- var z = flagZ ? 0xFFFFFFFF : 0x0;
- return new int32x4(t.x, t.y, z, t.w);
- },
- /**
- * @param {int32x4} t An instance of int32x4.
- * @param {boolean} w flag used for w lane.
- * @return {int32x4} New instance of int32x4 with the values in t and
- * w lane replaced with {w}.
- */
- withFlagW: function(t, flagW) {
- var w = flagW ? 0xFFFFFFFF : 0x0;
- return new int32x4(t.x, t.y, t.z, w);
- },
- /**
- * @param {int32x4} t An instance of int32x4.
- * @return {float32x4} a bit-wise copy of t as a float32x4.
- */
- bitsToFloat32x4: function(t) {
- var temp_storage = new Int32Array([t.storage_[0], t.storage_[1], t.storage_[2], t.storage_[3]]);
- var alias = new Float32Array(temp_storage.buffer);
- var fx4 = float32x4.zero();
- fx4.storage_ = alias;
- return fx4;
- },
- /**
- * @param {int32x4} t An instance of int32x4.
- * @return {float32x4} with a float to integer conversion copy of t.
- */
- toFloat32x4: function(t) {
- var a = float32x4.zero();
- a.storage_[0] = t.storage_[0];
- a.storage_[1] = t.storage_[1];
- a.storage_[2] = t.storage_[2];
- a.storage_[3] = t.storage_[3];
- return a;
- }
- }
- }
-})();
+/**
+ * @param {int32x4} a An instance of int32x4.
+ * @param {int32x4} b An instance of int32x4.
+ * @return {int32x4} New instance of int32x4 with values of a + b.
+ */
+SIMD.int32x4.add = function(a, b) {
+ return SIMD.int32x4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
+}
+
+/**
+ * @param {int32x4} a An instance of int32x4.
+ * @param {int32x4} b An instance of int32x4.
+ * @return {int32x4} New instance of int32x4 with values of a - b.
+ */
+SIMD.int32x4.sub = function(a, b) {
+ return SIMD.int32x4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
+}
+
+/**
+ * @param {int32x4} a An instance of int32x4.
+ * @param {int32x4} b An instance of int32x4.
+ * @return {int32x4} New instance of int32x4 with values of a * b.
+ */
+SIMD.int32x4.mul = function(a, b) {
+ return SIMD.int32x4(Math.imul(a.x, b.x), Math.imul(a.y, b.y),
+ Math.imul(a.z, b.z), Math.imul(a.w, b.w));
+}
+
+/**
+ * @param {int32x4} t An instance of float32x4 to be shuffled.
+ * @param {integer} mask One of the 256 shuffle masks, for example, SIMD.XXXX.
+ * @return {int32x4} New instance of float32x4 with lanes shuffled.
+ */
+SIMD.int32x4.shuffle = function(t, mask) {
+ var _x = (mask) & 0x3;
+ var _y = (mask >> 2) & 0x3;
+ var _z = (mask >> 4) & 0x3;
+ var _w = (mask >> 6) & 0x3;
+ return SIMD.int32x4(t.storage_[_x], t.storage_[_y], t.storage_[_z],
+ t.storage_[_w]);
+}
+
+/**
+ * @param {int32x4} t1 An instance of float32x4 to be shuffled. XY lanes in result
+ * @param {int32x4} t2 An instance of float32x4 to be shuffled. ZW lanes in result
+ * @param {integer} mask One of the 256 shuffle masks, for example, SIMD.XXXX.
+ * @return {int32x4} New instance of float32x4 with lanes shuffled.
+ */
+SIMD.int32x4.shuffleMix = function(t1, t2, mask) {
+ var _x = (mask) & 0x3;
+ var _y = (mask >> 2) & 0x3;
+ var _z = (mask >> 4) & 0x3;
+ var _w = (mask >> 6) & 0x3;
+ return SIMD.int32x4(t1.storage_[_x], t1.storage_[_y], t2.storage_[_z],
+ t2.storage_[_w]);
+}
+
+/**
+ * @param {float32x4}
+ */
+SIMD.int32x4.select = function(t, trueValue, falseValue) {
+ var tv = SIMD.float32x4.bitsToInt32x4(trueValue);
+ var fv = SIMD.float32x4.bitsToInt32x4(falseValue);
+ var tr = SIMD.int32x4.and(t, tv);
+ var fr = SIMD.int32x4.and(SIMD.int32x4.not(t), fv);
+ return SIMD.int32x4.bitsToFloat32x4(SIMD.int32x4.or(tr, fr));
+}
+
+/**
+ * @param {int32x4} t An instance of int32x4.
+ * @param {integer} 32-bit value used for x lane.
+ * @return {int32x4} New instance of int32x4 with the values in t and
+ * x lane replaced with {x}.
+ */
+SIMD.int32x4.withX = function(t, x) {
+ return SIMD.int32x4(x, t.y, t.z, t.w);
+}
+
+/**
+ * param {int32x4} t An instance of int32x4.
+ * @param {integer} 32-bit value used for y lane.
+ * @return {int32x4} New instance of int32x4 with the values in t and
+ * y lane replaced with {y}.
+ */
+SIMD.int32x4.withY = function(t, y) {
+ return SIMD.int32x4(t.x, y, t.z, t.w);
+}
+
+/**
+ * @param {int32x4} t An instance of int32x4.
+ * @param {integer} 32-bit value used for z lane.
+ * @return {int32x4} New instance of int32x4 with the values in t and
+ * z lane replaced with {z}.
+ */
+SIMD.int32x4.withZ = function(t, z) {
+ return SIMD.int32x4(t.x, t.y, z, t.w);
+}
+
+/**
+ * @param {integer} 32-bit value used for w lane.
+ * @return {int32x4} New instance of int32x4 with the values in t and
+ * w lane replaced with {w}.
+ */
+SIMD.int32x4.withW = function(t, w) {
+ return SIMD.int32x4(t.x, t.y, t.z, w);
+}
+
+/**
+ * @param {int32x4} t An instance of int32x4.
+ * @param {boolean} x flag used for x lane.
+ * @return {int32x4} New instance of int32x4 with the values in t and
+ * x lane replaced with {x}.
+ */
+SIMD.int32x4.withFlagX = function(t, flagX) {
+ var x = flagX ? 0xFFFFFFFF : 0x0;
+ return SIMD.int32x4(x, t.y, t.z, t.w);
+}
+
+/**
+ * @param {int32x4} t An instance of int32x4.
+ * @param {boolean} y flag used for y lane.
+ * @return {int32x4} New instance of int32x4 with the values in t and
+ * y lane replaced with {y}.
+ */
+SIMD.int32x4.withFlagY = function(t, flagY) {
+ var y = flagY ? 0xFFFFFFFF : 0x0;
+ return SIMD.int32x4(t.x, y, t.z, t.w);
+}
+
+/**
+ * @param {int32x4} t An instance of int32x4.
+ * @param {boolean} z flag used for z lane.
+ * @return {int32x4} New instance of int32x4 with the values in t and
+ * z lane replaced with {z}.
+ */
+SIMD.int32x4.withFlagZ = function(t, flagZ) {
+ var z = flagZ ? 0xFFFFFFFF : 0x0;
+ return SIMD.int32x4(t.x, t.y, z, t.w);
+}
+
+/**
+ * @param {int32x4} t An instance of int32x4.
+ * @param {boolean} w flag used for w lane.
+ * @return {int32x4} New instance of int32x4 with the values in t and
+ * w lane replaced with {w}.
+ */
+SIMD.int32x4.withFlagW = function(t, flagW) {
+ var w = flagW ? 0xFFFFFFFF : 0x0;
+ return SIMD.int32x4(t.x, t.y, t.z, w);
+}
+
+/**
+ * @param {int32x4} t An instance of int32x4.
+ * @param {int32x4} other An instance of int32x4.
+ * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on
+ * the result of t == other.
+ */
+SIMD.int32x4.equal = function(t, other) {
+ var cx = t.x == other.x;
+ var cy = t.y == other.y;
+ var cz = t.z == other.z;
+ var cw = t.w == other.w;
+ return SIMD.int32x4.bool(cx, cy, cz, cw);
+}
+
+/**
+ * @param {int32x4} t An instance of int32x4.
+ * @param {int32x4} other An instance of int32x4.
+ * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on
+ * the result of t > other.
+ */
+SIMD.int32x4.greaterThan = function(t, other) {
+ var cx = t.x > other.x;
+ var cy = t.y > other.y;
+ var cz = t.z > other.z;
+ var cw = t.w > other.w;
+ return SIMD.int32x4.bool(cx, cy, cz, cw);
+}
+
+/**
+ * @param {int32x4} t An instance of int32x4.
+ * @param {int32x4} other An instance of int32x4.
+ * @return {int32x4} 0xFFFFFFFF or 0x0 in each lane depending on
+ * the result of t < other.
+ */
+SIMD.int32x4.lessThan = function(t, other) {
+ var cx = t.x < other.x;
+ var cy = t.y < other.y;
+ var cz = t.z < other.z;
+ var cw = t.w < other.w;
+ return SIMD.int32x4.bool(cx, cy, cz, cw);
+}
+
+/**
+ * @param {int32x4} a An instance of int32x4.
+ * @param {int} bits Bit count to shift by.
+ * @return {int32x4} lanes in a shifted by bits.
+ */
+SIMD.int32x4.shiftLeft = function(a, bits) {
+ var x = a.x << bits;
+ var y = a.y << bits;
+ var z = a.z << bits;
+ var w = a.w << bits;
+ return SIMD.int32x4(x, y, z, w);
+}
+
+/**
+ * @param {int32x4} a An instance of int32x4.
+ * @param {int} bits Bit count to shift by.
+ * @return {int32x4} lanes in a shifted by bits.
+ */
+SIMD.int32x4.shiftRightLogical = function(a, bits) {
+ var x = a.x >>> bits;
+ var y = a.y >>> bits;
+ var z = a.z >>> bits;
+ var w = a.w >>> bits;
+ return SIMD.int32x4(x, y, z, w);
+}
+
+/**
+ * @param {int32x4} a An instance of int32x4.
+ * @param {int} bits Bit count to shift by.
+ * @return {int32x4} lanes in a shifted by bits.
+ */
+SIMD.int32x4.shiftRightArithmetic = function(a, bits) {
+ var x = a.x >> bits;
+ var y = a.y >> bits;
+ var z = a.z >> bits;
+ var w = a.w >> bits;
+ return SIMD.int32x4(x, y, z, w);
+}
+
+/**
+ * @param {int32x4} t An instance of int32x4.
+ * @return {float32x4} a bit-wise copy of t as a float32x4.
+ */
+SIMD.int32x4.bitsToFloat32x4 = function(t) {
+ var temp_storage = new Int32Array([t.storage_[0], t.storage_[1], t.storage_[2], t.storage_[3]]);
+ var alias = new Float32Array(temp_storage.buffer);
+ var fx4 = SIMD.float32x4.zero();
+ fx4.storage_ = alias;
+ return fx4;
+}
+
+/**
+ * @param {int32x4} t An instance of int32x4.
+ * @return {float32x4} with a float to integer conversion copy of t.
+ */
+SIMD.int32x4.toFloat32x4 = function(t) {
+ var a = float32x4.zero();
+ a.storage_[0] = t.storage_[0];
+ a.storage_[1] = t.storage_[1];
+ a.storage_[2] = t.storage_[2];
+ a.storage_[3] = t.storage_[3];
+ return a;
+}
Object.defineProperty(SIMD, 'XXXX', { get: function() { return 0x0; } });
Object.defineProperty(SIMD, 'XXXY', { get: function() { return 0x40; } });
@@ -1126,3 +1000,302 @@ Object.defineProperty(SIMD, 'WWWX', { get: function() { return 0x3F; } });
Object.defineProperty(SIMD, 'WWWY', { get: function() { return 0x7F; } });
Object.defineProperty(SIMD, 'WWWZ', { get: function() { return 0xBF; } });
Object.defineProperty(SIMD, 'WWWW', { get: function() { return 0xFF; } });
+
+Object.defineProperty(SIMD.float32x4.prototype, 'x', {
+ get: function() { return this.storage_[0]; }
+});
+
+Object.defineProperty(SIMD.float32x4.prototype, 'y', {
+ get: function() { return this.storage_[1]; }
+});
+
+Object.defineProperty(SIMD.float32x4.prototype, 'z', {
+ get: function() { return this.storage_[2]; }
+});
+
+Object.defineProperty(SIMD.float32x4.prototype, 'w',
+ { get: function() { return this.storage_[3]; }
+});
+
+/**
+ * Extract the sign bit from each lane return them in the first 4 bits.
+ */
+Object.defineProperty(SIMD.float32x4.prototype, 'signMask', {
+ get: function() {
+ var mx = this.x < 0.0 ? 1 : 0;
+ var my = this.y < 0.0 ? 1 : 0;
+ var mz = this.z < 0.0 ? 1 : 0;
+ var mw = this.w < 0.0 ? 1 : 0;
+ return mx | my << 1 | mz << 2 | mw << 3;
+ }
+});
+
+Object.defineProperty(SIMD.int32x4.prototype, 'x', {
+ get: function() { return this.storage_[0]; }
+});
+
+Object.defineProperty(SIMD.int32x4.prototype, 'y', {
+ get: function() { return this.storage_[1]; }
+});
+
+Object.defineProperty(SIMD.int32x4.prototype, 'z', {
+ get: function() { return this.storage_[2]; }
+});
+
+Object.defineProperty(SIMD.int32x4.prototype, 'w',
+ { get: function() { return this.storage_[3]; }
+});
+
+Object.defineProperty(SIMD.int32x4.prototype, 'flagX', {
+ get: function() { return this.storage_[0] != 0x0; }
+});
+
+Object.defineProperty(SIMD.int32x4.prototype, 'flagY', {
+ get: function() { return this.storage_[1] != 0x0; }
+});
+
+Object.defineProperty(SIMD.int32x4.prototype, 'flagZ', {
+ get: function() { return this.storage_[2] != 0x0; }
+});
+
+Object.defineProperty(SIMD.int32x4.prototype, 'flagW',
+ { get: function() { return this.storage_[3] != 0x0; }
+});
+
+/**
+ * Extract the sign bit from each lane return them in the first 4 bits.
+ */
+Object.defineProperty(SIMD.int32x4.prototype, 'signMask', {
+ get: function() {
+ var mx = (this.storage_[0] & 0x80000000) >>> 31;
+ var my = (this.storage_[1] & 0x80000000) >>> 31;
+ var mz = (this.storage_[2] & 0x80000000) >>> 31;
+ var mw = (this.storage_[3] & 0x80000000) >>> 31;
+ return mx | my << 1 | mz << 2 | mw << 3;
+ }
+});
+
+function isNumber(o) {
+ return typeof o == "number" || (typeof o == "object" && o.constructor === Number);
+}
+
+function isTypedArray(o) {
+ return (o instanceof Int8Array) ||
+ (o instanceof Uint8Array) ||
+ (o instanceof Uint8ClampedArray) ||
+ (o instanceof Int16Array) ||
+ (o instanceof Uint16Array) ||
+ (o instanceof Int32Array) ||
+ (o instanceof Uint32Array) ||
+ (o instanceof Float32Array) ||
+ (o instanceof Float64Array) ||
+ (o instanceof Float32x4Array);
+}
+
+function isArrayBuffer(o) {
+ return (o instanceof ArrayBuffer);
+}
+
+function Float32x4Array(a, b, c) {
+ if (isNumber(a)) {
+ this.storage_ = new Float32Array(a*4);
+ this.length_ = a;
+ this.byteOffset_ = 0;
+ return;
+ } else if (isTypedArray(a)) {
+ if (!(a instanceof Float32x4Array)) {
+ throw "Copying typed array of non-Float32x4Array is unimplemented.";
+ }
+ this.storage_ = new Float32Array(a.length * 4);
+ this.length_ = a.length;
+ this.byteOffset_ = 0;
+ // Copy floats.
+ for (var i = 0; i < a.length*4; i++) {
+ this.storage_[i] = a.storage_[i];
+ }
+ } else if (isArrayBuffer(a)) {
+ if ((b != undefined) && (b % Float32x4Array.BYTES_PER_ELEMENT) != 0) {
+ throw "byteOffset must be a multiple of 16.";
+ }
+ if (c != undefined) {
+ c *= 4;
+ this.storage_ = new Float32Array(a, b, c);
+ }
+ else {
+ // Note = new Float32Array(a, b) is NOT equivalent to new Float32Array(a, b, undefined)
+ this.storage_ = new Float32Array(a, b);
+ }
+ this.length_ = this.storage_.length / 4;
+ this.byteOffset_ = b != undefined ? b : 0;
+ } else {
+ throw "Unknown type of first argument.";
+ }
+}
+
+Object.defineProperty(Float32x4Array.prototype, 'length',
+ { get: function() { return this.length_; }
+});
+
+Object.defineProperty(Float32x4Array.prototype, 'byteLength',
+ { get: function() { return this.length_ * Float32x4Array.BYTES_PER_ELEMENT; }
+});
+
+Object.defineProperty(Float32x4Array, 'BYTES_PER_ELEMENT',
+ { get: function() { return 16; }
+});
+
+Object.defineProperty(Float32x4Array.prototype, 'BYTES_PER_ELEMENT',
+ { get: function() { return 16; }
+});
+
+Object.defineProperty(Float32x4Array.prototype, 'byteOffset',
+ { get: function() { return this.byteOffset_; }
+});
+
+Object.defineProperty(Float32x4Array.prototype, 'buffer',
+ { get: function() { return this.storage_.buffer; }
+});
+
+Float32x4Array.prototype.getAt = function(i) {
+ if (i < 0) {
+ throw "Index must be >= 0.";
+ }
+ if (i >= this.length) {
+ throw "Index out of bounds.";
+ }
+ var x = this.storage_[i*4+0];
+ var y = this.storage_[i*4+1];
+ var z = this.storage_[i*4+2];
+ var w = this.storage_[i*4+3];
+ return SIMD.float32x4(x, y, z, w);
+}
+
+Float32x4Array.prototype.setAt = function(i, v) {
+ if (i < 0) {
+ throw "Index must be >= 0.";
+ }
+ if (i >= this.length) {
+ throw "Index out of bounds.";
+ }
+ if (!(v instanceof SIMD.float32x4)) {
+ throw "Value is not a float32x4.";
+ }
+ this.storage_[i*4+0] = v.x;
+ this.storage_[i*4+1] = v.y;
+ this.storage_[i*4+2] = v.z;
+ this.storage_[i*4+3] = v.w;
+}
+
+
+function Int32x4Array(a, b, c) {
+
+ function isNumber(o) {
+ return typeof o == "number" || (typeof o == "object" && o.constructor === Number);
+ }
+
+ function isTypedArray(o) {
+ return (o instanceof Int8Array) ||
+ (o instanceof Uint8Array) ||
+ (o instanceof Uint8ClampedArray) ||
+ (o instanceof Int16Array) ||
+ (o instanceof Uint16Array) ||
+ (o instanceof Int32Array) ||
+ (o instanceof Uint32Array) ||
+ (o instanceof Float32Array) ||
+ (o instanceof Float64Array) ||
+ (o instanceof Int32x4Array) ||
+ (o instanceof Float32x4Array);
+ }
+
+ function isArrayBuffer(o) {
+ return (o instanceof ArrayBuffer);
+ }
+
+ if (isNumber(a)) {
+ this.storage_ = new Int32Array(a*4);
+ this.length_ = a;
+ this.byteOffset_ = 0;
+ return;
+ } else if (isTypedArray(a)) {
+ if (!(a instanceof Int32x4Array)) {
+ throw "Copying typed array of non-Int32x4Array is unimplemented.";
+ }
+ this.storage_ = new Int32Array(a.length * 4);
+ this.length_ = a.length;
+ this.byteOffset_ = 0;
+ // Copy ints.
+ for (var i = 0; i < a.length*4; i++) {
+ this.storage_[i] = a.storage_[i];
+ }
+ } else if (isArrayBuffer(a)) {
+ if ((b != undefined) && (b % Int32x4Array.BYTES_PER_ELEMENT) != 0) {
+ throw "byteOffset must be a multiple of 16.";
+ }
+ if (c != undefined) {
+ c *= 4;
+ this.storage_ = new Int32Array(a, b, c);
+ }
+ else {
+ // Note = new Int32Array(a, b) is NOT equivalent to new Float32Array(a, b, undefined)
+ this.storage_ = new Int32Array(a, b);
+ }
+ this.length_ = this.storage_.length / 4;
+ this.byteOffset_ = b != undefined ? b : 0;
+ } else {
+ throw "Unknown type of first argument.";
+ }
+}
+
+Object.defineProperty(Int32x4Array.prototype, 'length',
+ { get: function() { return this.length_; }
+});
+
+Object.defineProperty(Int32x4Array.prototype, 'byteLength',
+ { get: function() { return this.length_ * Int32x4Array.BYTES_PER_ELEMENT; }
+});
+
+Object.defineProperty(Int32x4Array, 'BYTES_PER_ELEMENT',
+ { get: function() { return 16; }
+});
+
+Object.defineProperty(Int32x4Array.prototype, 'BYTES_PER_ELEMENT',
+ { get: function() { return 16; }
+});
+
+Object.defineProperty(Int32x4Array.prototype, 'byteOffset',
+ { get: function() { return this.byteOffset_; }
+});
+
+Object.defineProperty(Int32x4Array.prototype, 'buffer',
+ { get: function() { return this.storage_.buffer; }
+});
+
+Int32x4Array.prototype.getAt = function(i) {
+ if (i < 0) {
+ throw "Index must be >= 0.";
+ }
+ if (i >= this.length) {
+ throw "Index out of bounds.";
+ }
+ var x = this.storage_[i*4+0];
+ var y = this.storage_[i*4+1];
+ var z = this.storage_[i*4+2];
+ var w = this.storage_[i*4+3];
+ return SIMD.int32x4(x, y, z, w);
+}
+
+Int32x4Array.prototype.setAt = function(i, v) {
+ if (i < 0) {
+ throw "Index must be >= 0.";
+ }
+ if (i >= this.length) {
+ throw "Index out of bounds.";
+ }
+ if (!(v instanceof SIMD.int32x4)) {
+ throw "Value is not a int32x4.";
+ }
+ this.storage_[i*4+0] = v.x;
+ this.storage_[i*4+1] = v.y;
+ this.storage_[i*4+2] = v.z;
+ this.storage_[i*4+3] = v.w;
+} \ No newline at end of file
diff --git a/src/struct_info.json b/src/struct_info.json
index f762bf2b..54c89fd7 100644
--- a/src/struct_info.json
+++ b/src/struct_info.json
@@ -932,6 +932,16 @@
"file": "SDL/SDL_events.h",
"defines": [],
"structs": {
+ "SDL_WindowEvent": [
+ "type",
+ "windowID",
+ "event",
+ "padding1",
+ "padding2",
+ "padding3",
+ "data1",
+ "data2"
+ ],
"SDL_KeyboardEvent": [
"type",
"windowID",
@@ -969,6 +979,14 @@
"x",
"y"
],
+ "SDL_MouseWheelEvent": [
+ "type",
+ "timestamp",
+ "windowID",
+ "which",
+ "x",
+ "y"
+ ],
"SDL_JoyAxisEvent": [
"type",
"which",
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h
index 0699715c..7bc28ff6 100644
--- a/system/include/emscripten/bind.h
+++ b/system/include/emscripten/bind.h
@@ -20,6 +20,8 @@ namespace emscripten {
namespace internal {
typedef long GenericEnumValue;
+ typedef void (*GenericFunction)();
+
// Implemented in JavaScript. Don't call these directly.
extern "C" {
void _embind_fatal_error(
@@ -70,21 +72,26 @@ namespace emscripten {
const char* name,
unsigned argCount,
TYPEID argTypes[],
+ const char* signature,
GenericFunction invoker,
GenericFunction function);
void _embind_register_value_array(
TYPEID tupleType,
const char* name,
+ const char* constructorSignature,
GenericFunction constructor,
+ const char* destructorSignature,
GenericFunction destructor);
void _embind_register_value_array_element(
TYPEID tupleType,
TYPEID getterReturnType,
+ const char* getterSignature,
GenericFunction getter,
void* getterContext,
TYPEID setterArgumentType,
+ const char* setterSignature,
GenericFunction setter,
void* setterContext);
@@ -93,46 +100,45 @@ namespace emscripten {
void _embind_register_value_object(
TYPEID structType,
const char* fieldName,
+ const char* constructorSignature,
GenericFunction constructor,
+ const char* destructorSignature,
GenericFunction destructor);
void _embind_register_value_object_field(
TYPEID structType,
const char* fieldName,
TYPEID getterReturnType,
+ const char* getterSignature,
GenericFunction getter,
void* getterContext,
TYPEID setterArgumentType,
+ const char* setterSignature,
GenericFunction setter,
void* setterContext);
void _embind_finalize_value_object(TYPEID structType);
- void _embind_register_smart_ptr(
- TYPEID pointerType,
- TYPEID pointeeType,
- const char* pointerName,
- sharing_policy sharingPolicy,
- GenericFunction getPointee,
- GenericFunction constructor,
- GenericFunction share,
- GenericFunction destructor);
-
void _embind_register_class(
TYPEID classType,
TYPEID pointerType,
TYPEID constPointerType,
TYPEID baseClassType,
+ const char* getActualTypeSignature,
GenericFunction getActualType,
+ const char* upcastSignature,
GenericFunction upcast,
+ const char* downcastSignature,
GenericFunction downcast,
const char* className,
+ const char* destructorSignature,
GenericFunction destructor);
void _embind_register_class_constructor(
TYPEID classType,
unsigned argCount,
TYPEID argTypes[],
+ const char* invokerSignature,
GenericFunction invoker,
GenericFunction constructor);
@@ -141,16 +147,20 @@ namespace emscripten {
const char* methodName,
unsigned argCount,
TYPEID argTypes[],
+ const char* invokerSignature,
GenericFunction invoker,
- void* context);
+ void* context,
+ unsigned isPureVirtual);
void _embind_register_class_property(
TYPEID classType,
const char* fieldName,
TYPEID getterReturnType,
+ const char* getterSignature,
GenericFunction getter,
void* getterContext,
TYPEID setterArgumentType,
+ const char* setterSignature,
GenericFunction setter,
void* setterContext);
@@ -159,26 +169,40 @@ namespace emscripten {
const char* methodName,
unsigned argCount,
TYPEID argTypes[],
+ const char* invokerSignature,
GenericFunction invoker,
GenericFunction method);
+ EM_VAL _embind_create_inheriting_constructor(
+ const char* constructorName,
+ TYPEID wrapperType,
+ EM_VAL properties);
+
void _embind_register_enum(
TYPEID enumType,
const char* name,
size_t size,
bool isSigned);
+ void _embind_register_smart_ptr(
+ TYPEID pointerType,
+ TYPEID pointeeType,
+ const char* pointerName,
+ sharing_policy sharingPolicy,
+ const char* getPointeeSignature,
+ GenericFunction getPointee,
+ const char* constructorSignature,
+ GenericFunction constructor,
+ const char* shareSignature,
+ GenericFunction share,
+ const char* destructorSignature,
+ GenericFunction destructor);
+
void _embind_register_enum_value(
TYPEID enumType,
const char* valueName,
GenericEnumValue value);
- void _embind_register_interface(
- TYPEID interfaceType,
- const char* name,
- GenericFunction constructor,
- GenericFunction destructor);
-
void _embind_register_constant(
const char* name,
TYPEID constantType,
@@ -258,6 +282,33 @@ namespace emscripten {
return method;
}
+ namespace internal {
+ // this should be in <type_traits>, but alas, it's not
+ template<typename T> struct remove_class;
+ template<typename C, typename R, typename... A>
+ struct remove_class<R(C::*)(A...)> { using type = R(A...); };
+ template<typename C, typename R, typename... A>
+ struct remove_class<R(C::*)(A...) const> { using type = R(A...); };
+ template<typename C, typename R, typename... A>
+ struct remove_class<R(C::*)(A...) volatile> { using type = R(A...); };
+ template<typename C, typename R, typename... A>
+ struct remove_class<R(C::*)(A...) const volatile> { using type = R(A...); };
+
+ template<typename LambdaType>
+ struct CalculateLambdaSignature {
+ using type = typename std::add_pointer<
+ typename remove_class<
+ decltype(&LambdaType::operator())
+ >::type
+ >::type;
+ };
+ }
+
+ template<typename LambdaType>
+ typename internal::CalculateLambdaSignature<LambdaType>::type optional_override(const LambdaType& fp) {
+ return fp;
+ }
+
////////////////////////////////////////////////////////////////////////////////
// Invoker
////////////////////////////////////////////////////////////////////////////////
@@ -291,6 +342,63 @@ namespace emscripten {
}
////////////////////////////////////////////////////////////////////////////////
+ // SignatureCode, SignatureString
+ ////////////////////////////////////////////////////////////////////////////////
+
+ namespace internal {
+ template<typename T>
+ struct SignatureCode {
+ static constexpr char get() {
+ return 'i';
+ }
+ };
+
+ template<>
+ struct SignatureCode<void> {
+ static constexpr char get() {
+ return 'v';
+ }
+ };
+
+ template<>
+ struct SignatureCode<float> {
+ static constexpr char get() {
+ return 'f';
+ }
+ };
+
+ template<>
+ struct SignatureCode<double> {
+ static constexpr char get() {
+ return 'd';
+ }
+ };
+
+ template<typename... T>
+ struct SignatureString;
+
+ template<>
+ struct SignatureString<> {
+ char c = 0;
+ };
+
+ template<typename First, typename... Rest>
+ struct SignatureString<First, Rest...> {
+ constexpr SignatureString()
+ : c(SignatureCode<First>::get())
+ {}
+ char c;
+ SignatureString<Rest...> rest;
+ };
+
+ template<typename Return, typename... Args>
+ const char* getSignature(Return (*)(Args...)) {
+ static constexpr SignatureString<Return, Args...> sig;
+ return &sig.c;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
@@ -302,11 +410,13 @@ namespace emscripten {
void function(const char* name, ReturnType (*fn)(Args...), Policies...) {
using namespace internal;
typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, Args...> args;
+ auto invoker = &Invoker<ReturnType, Args...>::invoke;
_embind_register_function(
name,
args.count,
args.types,
- reinterpret_cast<GenericFunction>(&Invoker<ReturnType, Args...>::invoke),
+ getSignature(invoker),
+ reinterpret_cast<GenericFunction>(invoker),
reinterpret_cast<GenericFunction>(fn));
}
@@ -542,11 +652,16 @@ namespace emscripten {
value_array(const char* name) {
using namespace internal;
+
+ auto constructor = &raw_constructor<ClassType>;
+ auto destructor = &raw_destructor<ClassType>;
_embind_register_value_array(
TypeID<ClassType>::get(),
name,
- reinterpret_cast<GenericFunction>(&raw_constructor<ClassType>),
- reinterpret_cast<GenericFunction>(&raw_destructor<ClassType>));
+ getSignature(constructor),
+ reinterpret_cast<GenericFunction>(constructor),
+ getSignature(destructor),
+ reinterpret_cast<GenericFunction>(destructor));
}
~value_array() {
@@ -557,17 +672,21 @@ namespace emscripten {
template<typename InstanceType, typename ElementType>
value_array& element(ElementType InstanceType::*field) {
using namespace internal;
+
+ auto getter = &MemberAccess<InstanceType, ElementType>
+ ::template getWire<ClassType>;
+ auto setter = &MemberAccess<InstanceType, ElementType>
+ ::template setWire<ClassType>;
+
_embind_register_value_array_element(
TypeID<ClassType>::get(),
TypeID<ElementType>::get(),
- reinterpret_cast<GenericFunction>(
- &MemberAccess<InstanceType, ElementType>
- ::template getWire<ClassType>),
+ getSignature(getter),
+ reinterpret_cast<GenericFunction>(getter),
getContext(field),
TypeID<ElementType>::get(),
- reinterpret_cast<GenericFunction>(
- &MemberAccess<InstanceType, ElementType>
- ::template setWire<ClassType>),
+ getSignature(setter),
+ reinterpret_cast<GenericFunction>(setter),
getContext(field));
return *this;
}
@@ -577,13 +696,19 @@ namespace emscripten {
using namespace internal;
typedef GetterPolicy<Getter> GP;
typedef SetterPolicy<Setter> SP;
+
+ auto g = &GP::template get<ClassType>;
+ auto s = &SP::template set<ClassType>;
+
_embind_register_value_array_element(
TypeID<ClassType>::get(),
TypeID<typename GP::ReturnType>::get(),
- reinterpret_cast<GenericFunction>(&GP::template get<ClassType>),
+ getSignature(g),
+ reinterpret_cast<GenericFunction>(g),
GP::getContext(getter),
TypeID<typename SP::ArgumentType>::get(),
- reinterpret_cast<GenericFunction>(&SP::template set<ClassType>),
+ getSignature(s),
+ reinterpret_cast<GenericFunction>(s),
SP::getContext(setter));
return *this;
}
@@ -593,13 +718,18 @@ namespace emscripten {
using namespace internal;
ClassType* null = 0;
typedef typename std::remove_reference<decltype((*null)[Index])>::type ElementType;
+ auto getter = &internal::get_by_index<ClassType, ElementType>;
+ auto setter = &internal::set_by_index<ClassType, ElementType>;
+
_embind_register_value_array_element(
TypeID<ClassType>::get(),
TypeID<ElementType>::get(),
- reinterpret_cast<GenericFunction>(&internal::get_by_index<ClassType, ElementType>),
+ getSignature(getter),
+ reinterpret_cast<GenericFunction>(getter),
reinterpret_cast<void*>(Index),
TypeID<ElementType>::get(),
- reinterpret_cast<GenericFunction>(&internal::set_by_index<ClassType, ElementType>),
+ getSignature(setter),
+ reinterpret_cast<GenericFunction>(setter),
reinterpret_cast<void*>(Index));
return *this;
}
@@ -616,11 +746,17 @@ namespace emscripten {
value_object(const char* name) {
using namespace internal;
+
+ auto ctor = &raw_constructor<ClassType>;
+ auto dtor = &raw_destructor<ClassType>;
+
_embind_register_value_object(
TypeID<ClassType>::get(),
name,
- reinterpret_cast<GenericFunction>(&raw_constructor<ClassType>),
- reinterpret_cast<GenericFunction>(&raw_destructor<ClassType>));
+ getSignature(ctor),
+ reinterpret_cast<GenericFunction>(ctor),
+ getSignature(dtor),
+ reinterpret_cast<GenericFunction>(dtor));
}
~value_object() {
@@ -630,18 +766,22 @@ namespace emscripten {
template<typename InstanceType, typename FieldType>
value_object& field(const char* fieldName, FieldType InstanceType::*field) {
using namespace internal;
+
+ auto getter = &MemberAccess<InstanceType, FieldType>
+ ::template getWire<ClassType>;
+ auto setter = &MemberAccess<InstanceType, FieldType>
+ ::template setWire<ClassType>;
+
_embind_register_value_object_field(
TypeID<ClassType>::get(),
fieldName,
TypeID<FieldType>::get(),
- reinterpret_cast<GenericFunction>(
- &MemberAccess<InstanceType, FieldType>
- ::template getWire<ClassType>),
+ getSignature(getter),
+ reinterpret_cast<GenericFunction>(getter),
getContext(field),
TypeID<FieldType>::get(),
- reinterpret_cast<GenericFunction>(
- &MemberAccess<InstanceType, FieldType>
- ::template setWire<ClassType>),
+ getSignature(setter),
+ reinterpret_cast<GenericFunction>(setter),
getContext(field));
return *this;
}
@@ -655,14 +795,20 @@ namespace emscripten {
using namespace internal;
typedef GetterPolicy<Getter> GP;
typedef SetterPolicy<Setter> SP;
+
+ auto g = &GP::template get<ClassType>;
+ auto s = &SP::template set<ClassType>;
+
_embind_register_value_object_field(
TypeID<ClassType>::get(),
fieldName,
TypeID<typename GP::ReturnType>::get(),
- reinterpret_cast<GenericFunction>(&GP::template get<ClassType>),
+ getSignature(g),
+ reinterpret_cast<GenericFunction>(g),
GP::getContext(getter),
TypeID<typename SP::ArgumentType>::get(),
- reinterpret_cast<GenericFunction>(&SP::template set<ClassType>),
+ getSignature(s),
+ reinterpret_cast<GenericFunction>(s),
SP::getContext(setter));
return *this;
}
@@ -672,14 +818,20 @@ namespace emscripten {
using namespace internal;
ClassType* null = 0;
typedef typename std::remove_reference<decltype((*null)[Index])>::type ElementType;
+
+ auto getter = &internal::get_by_index<ClassType, ElementType>;
+ auto setter = &internal::set_by_index<ClassType, ElementType>;
+
_embind_register_value_object_field(
TypeID<ClassType>::get(),
fieldName,
TypeID<ElementType>::get(),
- reinterpret_cast<GenericFunction>(&internal::get_by_index<ClassType, ElementType>),
+ getSignature(getter),
+ reinterpret_cast<GenericFunction>(getter),
reinterpret_cast<void*>(Index),
TypeID<ElementType>::get(),
- reinterpret_cast<GenericFunction>(&internal::set_by_index<ClassType, ElementType>),
+ getSignature(setter),
+ reinterpret_cast<GenericFunction>(setter),
reinterpret_cast<void*>(Index));
return *this;
}
@@ -754,40 +906,55 @@ namespace emscripten {
};
};
+
////////////////////////////////////////////////////////////////////////////////
// CLASSES
////////////////////////////////////////////////////////////////////////////////
+ namespace internal {
+ class WrapperBase {
+ public:
+ void setNotifyJSOnDestruction(bool notify) {
+ notifyJSOnDestruction = notify;
+ }
+
+ protected:
+ bool notifyJSOnDestruction = false;
+ };
+ }
+
// abstract classes
template<typename T>
- class wrapper : public T {
+ class wrapper : public T, public internal::WrapperBase {
public:
typedef T class_type;
- explicit wrapper(val&& wrapped)
- : wrapped(std::forward<val>(wrapped))
+ template<typename... Args>
+ explicit wrapper(val&& wrapped, Args&&... args)
+ : T(std::forward<Args>(args)...)
+ , wrapped(std::forward<val>(wrapped))
{}
+ ~wrapper() {
+ if (notifyJSOnDestruction) {
+ call<void>("__destruct");
+ }
+ }
+
template<typename ReturnType, typename... Args>
ReturnType call(const char* name, Args&&... args) const {
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 (wrapped.has_function(name)) {
- return call<ReturnType>(name, std::forward<Args>(args)...);
- } else {
- return def();
- }
- }
-
private:
val wrapped;
};
-#define EMSCRIPTEN_WRAPPER(T) \
- T(::emscripten::val&& v): wrapper(std::forward<::emscripten::val>(v)) {}
+#define EMSCRIPTEN_WRAPPER(T) \
+ template<typename... Args> \
+ T(::emscripten::val&& v, Args&&... args) \
+ : wrapper(std::forward<::emscripten::val>(v), std::forward<Args>(args)...) \
+ {}
namespace internal {
struct NoBaseClass {
@@ -832,13 +999,19 @@ namespace emscripten {
}
template<typename ClassType>
- static internal::GenericFunction getUpcaster() {
- return reinterpret_cast<internal::GenericFunction>(&convertPointer<ClassType, BaseClass>);
+ using Upcaster = BaseClass* (*)(ClassType*);
+
+ template<typename ClassType>
+ using Downcaster = ClassType* (*)(BaseClass*);
+
+ template<typename ClassType>
+ static Upcaster<ClassType> getUpcaster() {
+ return &convertPointer<ClassType, BaseClass>;
}
template<typename ClassType>
- static internal::GenericFunction getDowncaster() {
- return reinterpret_cast<internal::GenericFunction>(&convertPointer<BaseClass, ClassType>);
+ static Downcaster<ClassType> getDowncaster() {
+ return &convertPointer<BaseClass, ClassType>;
}
template<typename From, typename To>
@@ -862,6 +1035,45 @@ namespace emscripten {
SmartPtrIfNeeded(U&, const char*) {
}
};
+
+ template<typename WrapperType>
+ val wrapped_extend(const std::string& name, const val& properties) {
+ return val::take_ownership(_embind_create_inheriting_constructor(
+ name.c_str(),
+ TypeID<WrapperType>::get(),
+ properties.__get_handle()));
+ }
+ };
+
+ struct pure_virtual {
+ template<typename InputType, int Index>
+ struct Transform {
+ typedef InputType type;
+ };
+ };
+
+ namespace internal {
+ template<typename... Policies>
+ struct isPureVirtual;
+
+ template<typename... Rest>
+ struct isPureVirtual<pure_virtual, Rest...> {
+ static constexpr bool value = true;
+ };
+
+ template<typename T, typename... Rest>
+ struct isPureVirtual<T, Rest...> {
+ static constexpr bool value = isPureVirtual<Rest...>::value;
+ };
+
+ template<>
+ struct isPureVirtual<> {
+ static constexpr bool value = false;
+ };
+ }
+
+ template<typename... ConstructorArgs>
+ struct constructor {
};
template<typename ClassType, typename BaseSpecifier = internal::NoBaseClass>
@@ -877,16 +1089,25 @@ namespace emscripten {
BaseSpecifier::template verify<ClassType>();
+ auto _getActualType = &getActualType<ClassType>;
+ auto upcast = BaseSpecifier::template getUpcaster<ClassType>();
+ auto downcast = BaseSpecifier::template getDowncaster<ClassType>();
+ auto destructor = &raw_destructor<ClassType>;
+
_embind_register_class(
TypeID<ClassType>::get(),
TypeID<AllowedRawPointer<ClassType>>::get(),
TypeID<AllowedRawPointer<const ClassType>>::get(),
BaseSpecifier::get(),
- reinterpret_cast<GenericFunction>(&getActualType<ClassType>),
- BaseSpecifier::template getUpcaster<ClassType>(),
- BaseSpecifier::template getDowncaster<ClassType>(),
+ getSignature(_getActualType),
+ reinterpret_cast<GenericFunction>(_getActualType),
+ getSignature(upcast),
+ reinterpret_cast<GenericFunction>(upcast),
+ getSignature(downcast),
+ reinterpret_cast<GenericFunction>(downcast),
name,
- reinterpret_cast<GenericFunction>(&raw_destructor<ClassType>));
+ getSignature(destructor),
+ reinterpret_cast<GenericFunction>(destructor));
}
template<typename PointerType>
@@ -898,15 +1119,24 @@ namespace emscripten {
static_assert(std::is_same<ClassType, typename std::remove_cv<PointeeType>::type>::value, "smart pointer must point to this class");
+ auto get = &PointerTrait::get;
+ auto construct_null = &PointerTrait::construct_null;
+ auto share = &PointerTrait::share;
+ auto destructor = &raw_destructor<PointerType>;
+
_embind_register_smart_ptr(
TypeID<PointerType>::get(),
TypeID<PointeeType>::get(),
name,
PointerTrait::get_sharing_policy(),
- reinterpret_cast<GenericFunction>(&PointerTrait::get),
- reinterpret_cast<GenericFunction>(&PointerTrait::construct_null),
- reinterpret_cast<GenericFunction>(&PointerTrait::share),
- reinterpret_cast<GenericFunction>(&raw_destructor<PointerType>));
+ getSignature(get),
+ reinterpret_cast<GenericFunction>(get),
+ getSignature(construct_null),
+ reinterpret_cast<GenericFunction>(construct_null),
+ getSignature(share),
+ reinterpret_cast<GenericFunction>(share),
+ getSignature(destructor),
+ reinterpret_cast<GenericFunction>(destructor));
return *this;
};
@@ -923,11 +1153,13 @@ namespace emscripten {
// TODO: allows all raw pointers... policies need a rethink
typename WithPolicies<allow_raw_pointers, Policies...>::template ArgTypeList<ReturnType, Args...> args;
+ auto invoke = &Invoker<ReturnType, Args...>::invoke;
_embind_register_class_constructor(
TypeID<ClassType>::get(),
args.count,
args.types,
- reinterpret_cast<GenericFunction>(&Invoker<ReturnType, Args...>::invoke),
+ getSignature(invoke),
+ reinterpret_cast<GenericFunction>(invoke),
reinterpret_cast<GenericFunction>(factory));
return *this;
}
@@ -939,41 +1171,67 @@ namespace emscripten {
smart_ptr<SmartPtr>(smartPtrName);
typename WithPolicies<Policies...>::template ArgTypeList<SmartPtr, Args...> args;
+ auto invoke = &Invoker<SmartPtr, Args...>::invoke;
_embind_register_class_constructor(
TypeID<ClassType>::get(),
args.count,
args.types,
- reinterpret_cast<GenericFunction>(&Invoker<SmartPtr, Args...>::invoke),
+ getSignature(invoke),
+ reinterpret_cast<GenericFunction>(invoke),
reinterpret_cast<GenericFunction>(factory));
return *this;
}
- template<typename WrapperType, typename PointerType = WrapperType*>
- const class_& allow_subclass(const char* wrapperClassName, const char* pointerName = "<UnknownPointerName>") const {
+ template<typename WrapperType, typename PointerType = WrapperType*, typename... ConstructorArgs>
+ const class_& allow_subclass(
+ const char* wrapperClassName,
+ const char* pointerName = "<UnknownPointerName>",
+ ::emscripten::constructor<ConstructorArgs...> = ::emscripten::constructor<ConstructorArgs...>()
+ ) const {
using namespace internal;
auto cls = class_<WrapperType, base<ClassType>>(wrapperClassName)
+ .function("notifyOnDestruction", select_overload<void(WrapperType&)>([](WrapperType& wrapper) {
+ wrapper.setNotifyJSOnDestruction(true);
+ }))
;
SmartPtrIfNeeded<PointerType> _(cls, pointerName);
- return class_function(
- "implement",
- &wrapped_new<PointerType, WrapperType, val>,
- allow_raw_pointer<ret_val>());
+ return
+ class_function(
+ "implement",
+ &wrapped_new<PointerType, WrapperType, val, ConstructorArgs...>,
+ allow_raw_pointer<ret_val>())
+ .class_function(
+ "extend",
+ &wrapped_extend<WrapperType>)
+ ;
+ }
+
+ template<typename WrapperType, typename... ConstructorArgs>
+ const class_& allow_subclass(
+ const char* wrapperClassName,
+ ::emscripten::constructor<ConstructorArgs...> constructor
+ ) const {
+ return allow_subclass<WrapperType, WrapperType*>(wrapperClassName, "<UnknownPointerName>", constructor);
}
template<typename ReturnType, typename... Args, typename... Policies>
EMSCRIPTEN_ALWAYS_INLINE const class_& function(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...), Policies...) const {
using namespace internal;
+ auto invoker = &MethodInvoker<decltype(memberFunction), ReturnType, ClassType*, Args...>::invoke;
+
typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, AllowedRawPointer<ClassType>, Args...> args;
_embind_register_class_function(
TypeID<ClassType>::get(),
methodName,
args.count,
args.types,
- reinterpret_cast<GenericFunction>(&MethodInvoker<decltype(memberFunction), ReturnType, ClassType*, Args...>::invoke),
- getContext(memberFunction));
+ getSignature(invoker),
+ reinterpret_cast<GenericFunction>(invoker),
+ getContext(memberFunction),
+ isPureVirtual<Policies...>::value);
return *this;
}
@@ -981,14 +1239,18 @@ namespace emscripten {
EMSCRIPTEN_ALWAYS_INLINE const class_& function(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...) const, Policies...) const {
using namespace internal;
+ auto invoker = &MethodInvoker<decltype(memberFunction), ReturnType, const ClassType*, Args...>::invoke;
+
typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, AllowedRawPointer<const ClassType>, Args...> args;
_embind_register_class_function(
TypeID<ClassType>::get(),
methodName,
args.count,
args.types,
- reinterpret_cast<GenericFunction>(&MethodInvoker<decltype(memberFunction), ReturnType, const ClassType*, Args...>::invoke),
- getContext(memberFunction));
+ getSignature(invoker),
+ reinterpret_cast<GenericFunction>(invoker),
+ getContext(memberFunction),
+ isPureVirtual<Policies...>::value);
return *this;
}
@@ -997,28 +1259,34 @@ namespace emscripten {
using namespace internal;
typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, ThisType, Args...> args;
+ auto invoke = &FunctionInvoker<decltype(function), ReturnType, ThisType, Args...>::invoke;
_embind_register_class_function(
TypeID<ClassType>::get(),
methodName,
args.count,
args.types,
- reinterpret_cast<GenericFunction>(&FunctionInvoker<decltype(function), ReturnType, ThisType, Args...>::invoke),
- getContext(function));
+ getSignature(invoke),
+ reinterpret_cast<GenericFunction>(invoke),
+ getContext(function),
+ false);
return *this;
}
template<typename FieldType, typename = typename std::enable_if<!std::is_function<FieldType>::value>::type>
EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, const FieldType ClassType::*field) const {
using namespace internal;
-
+
+ auto getter = &MemberAccess<ClassType, FieldType>::template getWire<ClassType>;
_embind_register_class_property(
TypeID<ClassType>::get(),
fieldName,
TypeID<FieldType>::get(),
- reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::template getWire<ClassType>),
+ getSignature(getter),
+ reinterpret_cast<GenericFunction>(getter),
getContext(field),
0,
0,
+ 0,
0);
return *this;
}
@@ -1027,14 +1295,18 @@ namespace emscripten {
EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, FieldType ClassType::*field) const {
using namespace internal;
+ auto getter = &MemberAccess<ClassType, FieldType>::template getWire<ClassType>;
+ auto setter = &MemberAccess<ClassType, FieldType>::template setWire<ClassType>;
_embind_register_class_property(
TypeID<ClassType>::get(),
fieldName,
TypeID<FieldType>::get(),
- reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::template getWire<ClassType>),
+ getSignature(getter),
+ reinterpret_cast<GenericFunction>(getter),
getContext(field),
TypeID<FieldType>::get(),
- reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::template setWire<ClassType>),
+ getSignature(setter),
+ reinterpret_cast<GenericFunction>(setter),
getContext(field));
return *this;
}
@@ -1043,14 +1315,17 @@ namespace emscripten {
EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, Getter getter) const {
using namespace internal;
typedef GetterPolicy<Getter> GP;
+ auto gter = &GP::template get<ClassType>;
_embind_register_class_property(
TypeID<ClassType>::get(),
fieldName,
TypeID<typename GP::ReturnType>::get(),
- reinterpret_cast<GenericFunction>(&GP::template get<ClassType>),
+ getSignature(gter),
+ reinterpret_cast<GenericFunction>(gter),
GP::getContext(getter),
0,
0,
+ 0,
0);
return *this;
}
@@ -1060,14 +1335,20 @@ namespace emscripten {
using namespace internal;
typedef GetterPolicy<Getter> GP;
typedef SetterPolicy<Setter> SP;
+
+ auto gter = &GP::template get<ClassType>;
+ auto ster = &SP::template set<ClassType>;
+
_embind_register_class_property(
TypeID<ClassType>::get(),
fieldName,
TypeID<typename GP::ReturnType>::get(),
- reinterpret_cast<GenericFunction>(&GP::template get<ClassType>),
+ getSignature(gter),
+ reinterpret_cast<GenericFunction>(gter),
GP::getContext(getter),
TypeID<typename SP::ArgumentType>::get(),
- reinterpret_cast<GenericFunction>(&SP::template set<ClassType>),
+ getSignature(ster),
+ reinterpret_cast<GenericFunction>(ster),
SP::getContext(setter));
return *this;
}
@@ -1077,12 +1358,14 @@ namespace emscripten {
using namespace internal;
typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, Args...> args;
+ auto invoke = &internal::Invoker<ReturnType, Args...>::invoke;
_embind_register_class_class_function(
TypeID<ClassType>::get(),
methodName,
args.count,
args.types,
- reinterpret_cast<internal::GenericFunction>(&internal::Invoker<ReturnType, Args...>::invoke),
+ getSignature(invoke),
+ reinterpret_cast<internal::GenericFunction>(invoke),
reinterpret_cast<GenericFunction>(classMethod));
return *this;
}
diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h
index 73836018..b495c0f5 100644
--- a/system/include/emscripten/emscripten.h
+++ b/system/include/emscripten/emscripten.h
@@ -14,10 +14,38 @@
extern "C" {
#endif
+#include <stdio.h>
+
#if !__EMSCRIPTEN__
#include <SDL/SDL.h> /* for SDL_Delay in async_call */
#endif
+
+/* Typedefs */
+
+/*
+ * Unaligned types, helpful to force LLVM to emit unaligned
+ * loads/stores in places in your code where SAFE_HEAP found
+ * an unaligned operation. (It's better to avoid unaligned
+ * operations, but if you are reading from a packed stream of
+ * bytes or such, these types may be useful.)
+ */
+
+typedef short __attribute__((aligned(1))) emscripten_align1_short;
+
+typedef int __attribute__((aligned(2))) emscripten_align2_int;
+typedef int __attribute__((aligned(1))) emscripten_align1_int;
+
+typedef float __attribute__((aligned(2))) emscripten_align2_float;
+typedef float __attribute__((aligned(1))) emscripten_align1_float;
+
+typedef double __attribute__((aligned(4))) emscripten_align4_double;
+typedef double __attribute__((aligned(2))) emscripten_align2_double;
+typedef double __attribute__((aligned(1))) emscripten_align1_double;
+
+
+/* Functions */
+
/*
* Convenient syntax for inline assembly/js. Allows stuff like
*
@@ -27,8 +55,8 @@ extern "C" {
* does a function call to reach it). It supports newlines,
*
* EM_ASM(
- * window.alert('hai'));
- * window.alert('bai'));
+ * window.alert('hai');
+ * window.alert('bai');
* )
*
* Notes: Double-quotes (") are not supported, but you can use
@@ -121,7 +149,11 @@ extern void emscripten_async_load_script(const char *script, void (*onload)(void
*
* If you want your main loop function to receive a void*
* argument, use emscripten_set_main_loop_arg.
-
+ *
+ * There can be only *one* main loop function at a time. You
+ * can cancel the current one and set another, if you want to
+ * change it.
+ *
* @simulate_infinite_loop If true, this function will throw an
* exception in order to stop execution of the caller. This
* will lead to the main loop being entered instead of code
@@ -248,7 +280,7 @@ void emscripten_get_canvas_size(int *width, int *height, int *isFullscreen);
double emscripten_get_now(void);
#else
#include <time.h>
-double emscripten_get_now(void) {
+static inline double emscripten_get_now(void) {
return (1000*clock())/(double)CLOCKS_PER_SEC;
}
#endif
@@ -485,6 +517,24 @@ int emscripten_get_compiler_setting(const char *name);
*/
void emscripten_debugger();
+/*
+ * Get preloaded image data and the size of the image.
+ *
+ * Returns pointer to loaded image or NULL.
+ * width/height of image are written to w/h if data is valid.
+ * Pointer should be free()'d
+ */
+char *emscripten_get_preloaded_image_data(const char *path, int *w, int *h);
+
+/*
+ * Get preloaded image data from a c FILE *.
+ *
+ * Returns pointer to loaded image or NULL.
+ * width/height of image are written to w/h if data is valid.
+ * Pointer should be free()'d
+ */
+char *emscripten_get_preloaded_image_data_from_FILE(FILE *file, int *w, int *h);
+
/* ===================================== */
/* Internal APIs. Be careful with these. */
diff --git a/system/include/emscripten/html5.h b/system/include/emscripten/html5.h
index db81725a..74c32a99 100644
--- a/system/include/emscripten/html5.h
+++ b/system/include/emscripten/html5.h
@@ -636,6 +636,12 @@ extern EMSCRIPTEN_RESULT emscripten_set_beforeunload_callback(void *userData, co
extern EMSCRIPTEN_RESULT emscripten_set_webglcontextlost_callback(const char *target, void *userData, int useCapture, EM_BOOL (*func)(int eventType, const void *reserved, void *userData));
extern EMSCRIPTEN_RESULT emscripten_set_webglcontextrestored_callback(const char *target, void *userData, int useCapture, EM_BOOL (*func)(int eventType, const void *reserved, void *userData));
+/*
+ * Queries the given canvas element for whether its WebGL context is in a lost state.
+ * target: Reserved for future use, pass in 0.
+ */
+extern EM_BOOL emscripten_is_webgl_context_lost(const char *target);
+
#ifdef __cplusplus
} // ~extern "C"
#endif
diff --git a/system/include/emscripten/val.h b/system/include/emscripten/val.h
index e217c959..31f5923e 100644
--- a/system/include/emscripten/val.h
+++ b/system/include/emscripten/val.h
@@ -61,7 +61,9 @@ namespace emscripten {
EM_VAR_ARGS argv);
bool _emval_has_function(
EM_VAL value,
- const char* methodName);
+ const char* methodName,
+ internal::TYPEID filter);
+ EM_VAL _emval_typeof(EM_VAL value);
}
template<const char* address>
@@ -254,7 +256,6 @@ namespace emscripten {
// * delete
// * in
// * instanceof
- // * typeof
// * ! ~ - + ++ --
// * * / %
// * + -
@@ -392,8 +393,10 @@ namespace emscripten {
return MethodCaller<ReturnValue, Args...>::call(handle, name, std::forward<Args>(args)...);
}
- bool has_function(const char* name) const {
- return _emval_has_function(handle, name);
+ template<typename ClassType>
+ bool has_implementation_defined_function(const char* name) const {
+ using namespace internal;
+ return _emval_has_function(handle, name, TypeID<ClassType>::get());
}
template<typename T>
@@ -411,6 +414,15 @@ namespace emscripten {
return fromGenericWireType<T>(result);
}
+ // private: TODO: use a friend?
+ internal::EM_VAL __get_handle() const {
+ return handle;
+ }
+
+ val typeof() const {
+ return val(_emval_typeof(handle));
+ }
+
private:
// takes ownership, assumes handle already incref'd
explicit val(internal::EM_VAL handle)
diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp
index 37918050..16c24a91 100644
--- a/system/lib/embind/bind.cpp
+++ b/system/lib/embind/bind.cpp
@@ -78,6 +78,7 @@ EMSCRIPTEN_BINDINGS(native_and_builtin_types) {
register_float<double>("double");
_embind_register_std_string(TypeID<std::string>::get(), "std::string");
+ _embind_register_std_string(TypeID<std::basic_string<unsigned char> >::get(), "std::basic_string<unsigned char>");
_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/libc.symbols b/system/lib/libc.symbols
index eb2053ce..28e959d9 100644
--- a/system/lib/libc.symbols
+++ b/system/lib/libc.symbols
@@ -40,6 +40,7 @@
W _Znwj
W _ZnwjRKSt9nothrow_t
T __floatscan
+ T __intscan
T __overflow
T __shgetc
T __shlim
@@ -55,8 +56,14 @@
W bulk_free
W calloc
W free
+ T frexp
+ T frexpf
+ T frexpl
W independent_calloc
W independent_comalloc
+ T isdigit
+ T isspace
+ T isupper
W mallinfo
W malloc
W malloc_footprint
@@ -68,15 +75,25 @@
W malloc_usable_size
W mallopt
W memalign
+ T MUSL_vfprintf
W posix_memalign
W pvalloc
W realloc
W realloc_in_place
T scalbn
T scalbnl
+ T memchr
T memcmp
T memcpy
+ T snprintf
+ T sprintf
T strtod
+ T strtoull
+ T strtoll
+ T strtoul
+ T strtol
+ T strtoimax
+ T strtoumax
T strcoll
T __strcoll_l
W strcoll_l
@@ -89,4 +106,9 @@
T strtof_l
T strtold
T strtold_l
+ T tolower
W valloc
+ T vsnprintf
+ T vsprintf
+ T wcrtomb
+ T wctomb
diff --git a/system/lib/libc/musl/src/compat/readme.txt b/system/lib/libc/musl/src/compat/readme.txt
new file mode 100644
index 00000000..c96c6136
--- /dev/null
+++ b/system/lib/libc/musl/src/compat/readme.txt
@@ -0,0 +1,2 @@
+Files in this directory are not strictly standard musl libc, but implemented here for compatibility for Emscripten purposes.
+
diff --git a/system/lib/libc/musl/src/compat/strlwr.c b/system/lib/libc/musl/src/compat/strlwr.c
new file mode 100644
index 00000000..7c70a948
--- /dev/null
+++ b/system/lib/libc/musl/src/compat/strlwr.c
@@ -0,0 +1,12 @@
+#include <ctype.h>
+
+char *strlwr(char *str)
+{
+ char *ret = str;
+ while(*str)
+ {
+ *str = tolower(*str);
+ ++str;
+ }
+ return ret;
+}
diff --git a/system/lib/libc/musl/src/compat/strtol_l.c b/system/lib/libc/musl/src/compat/strtol_l.c
new file mode 100644
index 00000000..58b46186
--- /dev/null
+++ b/system/lib/libc/musl/src/compat/strtol_l.c
@@ -0,0 +1,22 @@
+#include <stdlib.h>
+#include <ctype.h>
+
+unsigned long long strtoull_l(const char *restrict s, char **restrict p, int base, locale_t loc)
+{
+ return strtoull(s, p, base);
+}
+
+long long strtoll_l(const char *restrict s, char **restrict p, int base, locale_t loc)
+{
+ return strtoll(s, p, base);
+}
+
+unsigned long strtoul_l(const char *restrict s, char **restrict p, int base, locale_t loc)
+{
+ return strtoul(s, p, base);
+}
+
+long strtol_l(const char *restrict s, char **restrict p, int base, locale_t loc)
+{
+ return strtol(s, p, base);
+}
diff --git a/system/lib/libc/musl/src/compat/strupr.c b/system/lib/libc/musl/src/compat/strupr.c
new file mode 100644
index 00000000..469ad8b1
--- /dev/null
+++ b/system/lib/libc/musl/src/compat/strupr.c
@@ -0,0 +1,12 @@
+#include <ctype.h>
+
+char *strupr(char *str)
+{
+ char *ret = str;
+ while(*str)
+ {
+ *str = toupper(*str);
+ ++str;
+ }
+ return ret;
+}
diff --git a/system/lib/libc/musl/src/ctype/isalnum.c b/system/lib/libc/musl/src/ctype/isalnum.c
new file mode 100644
index 00000000..e3d2cf0b
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/isalnum.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isalnum(int c)
+{
+ return isalpha(c) || isdigit(c);
+}
diff --git a/system/lib/libc/musl/src/ctype/isalpha.c b/system/lib/libc/musl/src/ctype/isalpha.c
new file mode 100644
index 00000000..53e115c2
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/isalpha.c
@@ -0,0 +1,7 @@
+#include <ctype.h>
+#undef isalpha
+
+int isalpha(int c)
+{
+ return ((unsigned)c|32)-'a' < 26;
+}
diff --git a/system/lib/libc/musl/src/ctype/isascii.c b/system/lib/libc/musl/src/ctype/isascii.c
new file mode 100644
index 00000000..3af0a10d
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/isascii.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isascii(int c)
+{
+ return !(c&~0x7f);
+}
diff --git a/system/lib/libc/musl/src/ctype/isblank.c b/system/lib/libc/musl/src/ctype/isblank.c
new file mode 100644
index 00000000..957400b2
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/isblank.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isblank(int c)
+{
+ return (c == ' ' || c == '\t');
+}
diff --git a/system/lib/libc/musl/src/ctype/iscntrl.c b/system/lib/libc/musl/src/ctype/iscntrl.c
new file mode 100644
index 00000000..92ed7f0e
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/iscntrl.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int iscntrl(int c)
+{
+ return (unsigned)c < 0x20 || c == 0x7f;
+}
diff --git a/system/lib/libc/musl/src/ctype/isdigit.c b/system/lib/libc/musl/src/ctype/isdigit.c
new file mode 100644
index 00000000..0bc82a6d
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/isdigit.c
@@ -0,0 +1,7 @@
+#include <ctype.h>
+#undef isdigit
+
+int isdigit(int c)
+{
+ return (unsigned)c-'0' < 10;
+}
diff --git a/system/lib/libc/musl/src/ctype/isgraph.c b/system/lib/libc/musl/src/ctype/isgraph.c
new file mode 100644
index 00000000..98979d1e
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/isgraph.c
@@ -0,0 +1,4 @@
+int isgraph(int c)
+{
+ return (unsigned)c-0x21 < 0x5e;
+}
diff --git a/system/lib/libc/musl/src/ctype/islower.c b/system/lib/libc/musl/src/ctype/islower.c
new file mode 100644
index 00000000..d72fb212
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/islower.c
@@ -0,0 +1,7 @@
+#include <ctype.h>
+#undef islower
+
+int islower(int c)
+{
+ return (unsigned)c-'a' < 26;
+}
diff --git a/system/lib/libc/musl/src/ctype/isprint.c b/system/lib/libc/musl/src/ctype/isprint.c
new file mode 100644
index 00000000..504e66ed
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/isprint.c
@@ -0,0 +1,4 @@
+int isprint(int c)
+{
+ return (unsigned)c-0x20 < 0x5f;
+}
diff --git a/system/lib/libc/musl/src/ctype/ispunct.c b/system/lib/libc/musl/src/ctype/ispunct.c
new file mode 100644
index 00000000..fc455352
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/ispunct.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int ispunct(int c)
+{
+ return isgraph(c) && !isalnum(c);
+}
diff --git a/system/lib/libc/musl/src/ctype/isspace.c b/system/lib/libc/musl/src/ctype/isspace.c
new file mode 100644
index 00000000..8e535aa1
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/isspace.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isspace(int c)
+{
+ return c == ' ' || (unsigned)c-'\t' < 5;
+}
diff --git a/system/lib/libc/musl/src/ctype/isupper.c b/system/lib/libc/musl/src/ctype/isupper.c
new file mode 100644
index 00000000..f09d88c5
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/isupper.c
@@ -0,0 +1,7 @@
+#include <ctype.h>
+#undef isupper
+
+int isupper(int c)
+{
+ return (unsigned)c-'A' < 26;
+}
diff --git a/system/lib/libc/musl/src/ctype/isxdigit.c b/system/lib/libc/musl/src/ctype/isxdigit.c
new file mode 100644
index 00000000..ae68a3dc
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/isxdigit.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isxdigit(int c)
+{
+ return isdigit(c) || ((unsigned)c|32)-'a' < 6;
+}
diff --git a/system/lib/libc/musl/src/ctype/toascii.c b/system/lib/libc/musl/src/ctype/toascii.c
new file mode 100644
index 00000000..f0e48e8e
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/toascii.c
@@ -0,0 +1,7 @@
+#include <ctype.h>
+
+/* nonsense function that should NEVER be used! */
+int toascii(int c)
+{
+ return c & 0x7f;
+}
diff --git a/system/lib/libc/musl/src/ctype/tolower.c b/system/lib/libc/musl/src/ctype/tolower.c
new file mode 100644
index 00000000..b56f3c50
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/tolower.c
@@ -0,0 +1,7 @@
+#include <ctype.h>
+
+int tolower(int c)
+{
+ if (isupper(c)) return c | 32;
+ return c;
+}
diff --git a/system/lib/libc/musl/src/ctype/toupper.c b/system/lib/libc/musl/src/ctype/toupper.c
new file mode 100644
index 00000000..1799f030
--- /dev/null
+++ b/system/lib/libc/musl/src/ctype/toupper.c
@@ -0,0 +1,7 @@
+#include <ctype.h>
+
+int toupper(int c)
+{
+ if (islower(c)) return c & 0x5f;
+ return c;
+}
diff --git a/system/lib/libc/musl/src/internal/stdio_impl.h b/system/lib/libc/musl/src/internal/stdio_impl.h
index 6bcd44dc..0e10e30d 100644
--- a/system/lib/libc/musl/src/internal/stdio_impl.h
+++ b/system/lib/libc/musl/src/internal/stdio_impl.h
@@ -95,4 +95,8 @@ int __fmodeflags(const char *);
FILE *__fopen_rb_ca(const char *, FILE *, unsigned char *, size_t);
int __fclose_ca(FILE *);
+// XXX Emscripten: musl-specific vfscanf and vfprintf live parallel to JS handwritten vfscanf and vfprintf, so musl ones are prefixed.
+int MUSL_vfscanf(FILE *restrict f, const char *restrict fmt, va_list ap);
+int MUSL_vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap);
+
#endif
diff --git a/system/lib/libc/musl/src/locale/isalnum_l.c b/system/lib/libc/musl/src/locale/isalnum_l.c
new file mode 100644
index 00000000..b8a6eef3
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/isalnum_l.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isalnum_l(int c, locale_t l)
+{
+ return isalnum(c);
+}
diff --git a/system/lib/libc/musl/src/locale/isalpha_l.c b/system/lib/libc/musl/src/locale/isalpha_l.c
new file mode 100644
index 00000000..2e1205c6
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/isalpha_l.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isalpha_l(int c, locale_t l)
+{
+ return isalpha(c);
+}
diff --git a/system/lib/libc/musl/src/locale/isblank_l.c b/system/lib/libc/musl/src/locale/isblank_l.c
new file mode 100644
index 00000000..27479aa1
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/isblank_l.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isblank_l(int c, locale_t l)
+{
+ return isblank(c);
+}
diff --git a/system/lib/libc/musl/src/locale/iscntrl_l.c b/system/lib/libc/musl/src/locale/iscntrl_l.c
new file mode 100644
index 00000000..ca596fa9
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/iscntrl_l.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int iscntrl_l(int c, locale_t l)
+{
+ return iscntrl(c);
+}
diff --git a/system/lib/libc/musl/src/locale/isdigit_l.c b/system/lib/libc/musl/src/locale/isdigit_l.c
new file mode 100644
index 00000000..c8ae7bd3
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/isdigit_l.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isdigit_l(int c, locale_t l)
+{
+ return isdigit(c);
+}
diff --git a/system/lib/libc/musl/src/locale/isgraph_l.c b/system/lib/libc/musl/src/locale/isgraph_l.c
new file mode 100644
index 00000000..713a86e6
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/isgraph_l.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isgraph_l(int c, locale_t l)
+{
+ return isgraph(c);
+}
diff --git a/system/lib/libc/musl/src/locale/islower_l.c b/system/lib/libc/musl/src/locale/islower_l.c
new file mode 100644
index 00000000..25ec97a1
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/islower_l.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int islower_l(int c, locale_t l)
+{
+ return islower(c);
+}
diff --git a/system/lib/libc/musl/src/locale/isprint_l.c b/system/lib/libc/musl/src/locale/isprint_l.c
new file mode 100644
index 00000000..79ef3514
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/isprint_l.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isprint_l(int c, locale_t l)
+{
+ return isprint(c);
+}
diff --git a/system/lib/libc/musl/src/locale/ispunct_l.c b/system/lib/libc/musl/src/locale/ispunct_l.c
new file mode 100644
index 00000000..1c0bd046
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/ispunct_l.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int ispunct_l(int c, locale_t l)
+{
+ return ispunct(c);
+}
diff --git a/system/lib/libc/musl/src/locale/isspace_l.c b/system/lib/libc/musl/src/locale/isspace_l.c
new file mode 100644
index 00000000..e1a0efed
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/isspace_l.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isspace_l(int c, locale_t l)
+{
+ return isspace(c);
+}
diff --git a/system/lib/libc/musl/src/locale/isupper_l.c b/system/lib/libc/musl/src/locale/isupper_l.c
new file mode 100644
index 00000000..11ba7036
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/isupper_l.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isupper_l(int c, locale_t l)
+{
+ return isupper(c);
+}
diff --git a/system/lib/libc/musl/src/locale/isxdigit_l.c b/system/lib/libc/musl/src/locale/isxdigit_l.c
new file mode 100644
index 00000000..68649d09
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/isxdigit_l.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int isxdigit_l(int c, locale_t l)
+{
+ return isxdigit(c);
+}
diff --git a/system/lib/libc/musl/src/locale/tolower_l.c b/system/lib/libc/musl/src/locale/tolower_l.c
new file mode 100644
index 00000000..ba277919
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/tolower_l.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int tolower_l(int c, locale_t l)
+{
+ return tolower(c);
+}
diff --git a/system/lib/libc/musl/src/locale/toupper_l.c b/system/lib/libc/musl/src/locale/toupper_l.c
new file mode 100644
index 00000000..73f2f39b
--- /dev/null
+++ b/system/lib/libc/musl/src/locale/toupper_l.c
@@ -0,0 +1,6 @@
+#include <ctype.h>
+
+int toupper_l(int c, locale_t l)
+{
+ return toupper(c);
+}
diff --git a/system/lib/libc/musl/src/math/frexp.c b/system/lib/libc/musl/src/math/frexp.c
new file mode 100644
index 00000000..27b6266e
--- /dev/null
+++ b/system/lib/libc/musl/src/math/frexp.c
@@ -0,0 +1,23 @@
+#include <math.h>
+#include <stdint.h>
+
+double frexp(double x, int *e)
+{
+ union { double d; uint64_t i; } y = { x };
+ int ee = y.i>>52 & 0x7ff;
+
+ if (!ee) {
+ if (x) {
+ x = frexp(x*0x1p64, e);
+ *e -= 64;
+ } else *e = 0;
+ return x;
+ } else if (ee == 0x7ff) {
+ return x;
+ }
+
+ *e = ee - 0x3fe;
+ y.i &= 0x800fffffffffffffull;
+ y.i |= 0x3fe0000000000000ull;
+ return y.d;
+}
diff --git a/system/lib/libc/musl/src/math/frexpf.c b/system/lib/libc/musl/src/math/frexpf.c
new file mode 100644
index 00000000..07870975
--- /dev/null
+++ b/system/lib/libc/musl/src/math/frexpf.c
@@ -0,0 +1,23 @@
+#include <math.h>
+#include <stdint.h>
+
+float frexpf(float x, int *e)
+{
+ union { float f; uint32_t i; } y = { x };
+ int ee = y.i>>23 & 0xff;
+
+ if (!ee) {
+ if (x) {
+ x = frexpf(x*0x1p64, e);
+ *e -= 64;
+ } else *e = 0;
+ return x;
+ } else if (ee == 0xff) {
+ return x;
+ }
+
+ *e = ee - 0x7e;
+ y.i &= 0x807ffffful;
+ y.i |= 0x3f000000ul;
+ return y.f;
+}
diff --git a/system/lib/libc/musl/src/math/frexpl.c b/system/lib/libc/musl/src/math/frexpl.c
new file mode 100644
index 00000000..f9d90a6d
--- /dev/null
+++ b/system/lib/libc/musl/src/math/frexpl.c
@@ -0,0 +1,37 @@
+#include <math.h>
+#include <stdint.h>
+#include <float.h>
+
+#if LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384
+
+/* This version is for 80-bit little endian long double */
+
+long double frexpl(long double x, int *e)
+{
+ union { long double ld; uint16_t hw[5]; } y = { x };
+ int ee = y.hw[4]&0x7fff;
+
+ if (!ee) {
+ if (x) {
+ x = frexpl(x*0x1p64, e);
+ *e -= 64;
+ } else *e = 0;
+ return x;
+ } else if (ee == 0x7fff) {
+ return x;
+ }
+
+ *e = ee - 0x3ffe;
+ y.hw[4] &= 0x8000;
+ y.hw[4] |= 0x3ffe;
+ return y.ld;
+}
+
+#else
+
+long double frexpl(long double x, int *e)
+{
+ return frexp(x, e);
+}
+
+#endif
diff --git a/system/lib/libc/musl/src/stdio/__string_read.c b/system/lib/libc/musl/src/stdio/__string_read.c
new file mode 100644
index 00000000..7b50a7e1
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/__string_read.c
@@ -0,0 +1,16 @@
+#include "stdio_impl.h"
+#include <string.h>
+
+size_t __string_read(FILE *f, unsigned char *buf, size_t len)
+{
+ char *src = f->cookie;
+ size_t k = len+256;
+ char *end = memchr(src, 0, k);
+ if (end) k = end-src;
+ if (k < len) len = k;
+ memcpy(buf, src, len);
+ f->rpos = (void *)(src+len);
+ f->rend = (void *)(src+k);
+ f->cookie = src+k;
+ return len;
+}
diff --git a/system/lib/libc/musl/src/stdio/asprintf.c b/system/lib/libc/musl/src/stdio/asprintf.c
new file mode 100644
index 00000000..4ec83534
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/asprintf.c
@@ -0,0 +1,13 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdarg.h>
+
+int asprintf(char **s, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+ va_start(ap, fmt);
+ ret = vasprintf(s, fmt, ap);
+ va_end(ap);
+ return ret;
+}
diff --git a/system/lib/libc/musl/src/stdio/fwrite.c b/system/lib/libc/musl/src/stdio/fwrite.c
new file mode 100644
index 00000000..bf68b794
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/fwrite.c
@@ -0,0 +1,41 @@
+#include "stdio_impl.h"
+#include <string.h>
+
+size_t __fwritex(const unsigned char *restrict s, size_t l, FILE *restrict f)
+{
+ size_t i=0;
+
+ if (!f->wend && __towrite(f)) return 0;
+
+ if (l > f->wend - f->wpos) return f->write(f, s, l);
+
+ if (f->lbf >= 0) {
+ /* Match /^(.*\n|)/ */
+ for (i=l; i && s[i-1] != '\n'; i--);
+ if (i) {
+ if (f->write(f, s, i) < i)
+ return i;
+ s += i;
+ l -= i;
+ }
+ }
+
+ memcpy(f->wpos, s, l);
+ f->wpos += l;
+ return l+i;
+}
+
+// XXX Emscripten: Not used, since we are not currently using musl file IO.
+#if 0
+size_t fwrite(const void *restrict src, size_t size, size_t nmemb, FILE *restrict f)
+{
+ size_t k, l = size*nmemb;
+ if (!l) return l;
+ FLOCK(f);
+ k = __fwritex(src, l, f);
+ FUNLOCK(f);
+ return k==l ? nmemb : k/size;
+}
+#endif
+
+weak_alias(fwrite, fwrite_unlocked);
diff --git a/system/lib/libc/musl/src/stdio/snprintf.c b/system/lib/libc/musl/src/stdio/snprintf.c
new file mode 100644
index 00000000..771503b2
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/snprintf.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+int snprintf(char *restrict s, size_t n, const char *restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+ va_start(ap, fmt);
+ ret = vsnprintf(s, n, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
diff --git a/system/lib/libc/musl/src/stdio/sprintf.c b/system/lib/libc/musl/src/stdio/sprintf.c
new file mode 100644
index 00000000..9dff524c
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/sprintf.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+int sprintf(char *restrict s, const char *restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+ va_start(ap, fmt);
+ ret = vsprintf(s, fmt, ap);
+ va_end(ap);
+ return ret;
+}
diff --git a/system/lib/libc/musl/src/stdio/sscanf.c b/system/lib/libc/musl/src/stdio/sscanf.c
new file mode 100644
index 00000000..8a2302ff
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/sscanf.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include "libc.h"
+
+int sscanf(const char *restrict s, const char *restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+ va_start(ap, fmt);
+ ret = vsscanf(s, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+weak_alias(sscanf,__isoc99_sscanf);
diff --git a/system/lib/libc/musl/src/stdio/vasprintf.c b/system/lib/libc/musl/src/stdio/vasprintf.c
new file mode 100644
index 00000000..68b7246b
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/vasprintf.c
@@ -0,0 +1,28 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#define GUESS 240U
+
+int vasprintf(char **s, const char *fmt, va_list ap)
+{
+ va_list ap2;
+ char *a;
+ int l=GUESS;
+
+ if (!(a=malloc(GUESS))) return -1;
+
+ va_copy(ap2, ap);
+ l=vsnprintf(a, GUESS, fmt, ap2);
+ va_end(ap2);
+
+ if (l<GUESS) {
+ char *b = realloc(a, l+1U);
+ *s = b ? b : a;
+ return l;
+ }
+ free(a);
+ if (l<0 || !(*s=malloc(l+1U))) return -1;
+ return vsnprintf(*s, l+1U, fmt, ap);
+}
diff --git a/system/lib/libc/musl/src/stdio/vfprintf.c b/system/lib/libc/musl/src/stdio/vfprintf.c
new file mode 100644
index 00000000..750ad1e3
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/vfprintf.c
@@ -0,0 +1,685 @@
+#include "stdio_impl.h"
+#include <errno.h>
+#include <ctype.h>
+#include <limits.h>
+#include <string.h>
+#include <stdarg.h>
+#include <wchar.h>
+#include <inttypes.h>
+#include <math.h>
+#include <float.h>
+
+/* Some useful macros */
+
+#define MAX(a,b) ((a)>(b) ? (a) : (b))
+#define MIN(a,b) ((a)<(b) ? (a) : (b))
+#define CONCAT2(x,y) x ## y
+#define CONCAT(x,y) CONCAT2(x,y)
+
+/* Convenient bit representation for modifier flags, which all fall
+ * within 31 codepoints of the space character. */
+
+#define ALT_FORM (1U<<'#'-' ')
+#define ZERO_PAD (1U<<'0'-' ')
+#define LEFT_ADJ (1U<<'-'-' ')
+#define PAD_POS (1U<<' '-' ')
+#define MARK_POS (1U<<'+'-' ')
+#define GROUPED (1U<<'\''-' ')
+
+#define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS|GROUPED)
+
+#if UINT_MAX == ULONG_MAX
+#define LONG_IS_INT
+#endif
+
+#if SIZE_MAX != ULONG_MAX || UINTMAX_MAX != ULLONG_MAX
+#define ODD_TYPES
+#endif
+
+/* State machine to accept length modifiers + conversion specifiers.
+ * Result is 0 on failure, or an argument type to pop on success. */
+
+enum {
+ BARE, LPRE, LLPRE, HPRE, HHPRE, BIGLPRE,
+ ZTPRE, JPRE,
+ STOP,
+ PTR, INT, UINT, ULLONG,
+#ifndef LONG_IS_INT
+ LONG, ULONG,
+#else
+#define LONG INT
+#define ULONG UINT
+#endif
+ SHORT, USHORT, CHAR, UCHAR,
+#ifdef ODD_TYPES
+ LLONG, SIZET, IMAX, UMAX, PDIFF, UIPTR,
+#else
+#define LLONG ULLONG
+#define SIZET ULONG
+#define IMAX LLONG
+#define UMAX ULLONG
+#define PDIFF LONG
+#define UIPTR ULONG
+#endif
+ DBL, LDBL,
+ NOARG,
+ MAXSTATE
+};
+
+#define S(x) [(x)-'A']
+
+static const unsigned char states[]['z'-'A'+1] = {
+ { /* 0: bare types */
+ S('d') = INT, S('i') = INT,
+ S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT,
+ S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
+ S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
+ S('c') = CHAR, S('C') = INT,
+ S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR,
+ S('m') = NOARG,
+ S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
+ S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE,
+ }, { /* 1: l-prefixed */
+ S('d') = LONG, S('i') = LONG,
+ S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
+ S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
+ S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
+ S('c') = INT, S('s') = PTR, S('n') = PTR,
+ S('l') = LLPRE,
+ }, { /* 2: ll-prefixed */
+ S('d') = LLONG, S('i') = LLONG,
+ S('o') = ULLONG, S('u') = ULLONG,
+ S('x') = ULLONG, S('X') = ULLONG,
+ S('n') = PTR,
+ }, { /* 3: h-prefixed */
+ S('d') = SHORT, S('i') = SHORT,
+ S('o') = USHORT, S('u') = USHORT,
+ S('x') = USHORT, S('X') = USHORT,
+ S('n') = PTR,
+ S('h') = HHPRE,
+ }, { /* 4: hh-prefixed */
+ S('d') = CHAR, S('i') = CHAR,
+ S('o') = UCHAR, S('u') = UCHAR,
+ S('x') = UCHAR, S('X') = UCHAR,
+ S('n') = PTR,
+ }, { /* 5: L-prefixed */
+ S('e') = LDBL, S('f') = LDBL, S('g') = LDBL, S('a') = LDBL,
+ S('E') = LDBL, S('F') = LDBL, S('G') = LDBL, S('A') = LDBL,
+ S('n') = PTR,
+ }, { /* 6: z- or t-prefixed (assumed to be same size) */
+ S('d') = PDIFF, S('i') = PDIFF,
+ S('o') = SIZET, S('u') = SIZET,
+ S('x') = SIZET, S('X') = SIZET,
+ S('n') = PTR,
+ }, { /* 7: j-prefixed */
+ S('d') = IMAX, S('i') = IMAX,
+ S('o') = UMAX, S('u') = UMAX,
+ S('x') = UMAX, S('X') = UMAX,
+ S('n') = PTR,
+ }
+};
+
+#define OOB(x) ((unsigned)(x)-'A' > 'z'-'A')
+
+union arg
+{
+ uintmax_t i;
+ long double f;
+ void *p;
+};
+
+static void pop_arg(union arg *arg, int type, va_list *ap)
+{
+ /* Give the compiler a hint for optimizing the switch. */
+ if ((unsigned)type > MAXSTATE) return;
+ switch (type) {
+ case PTR: arg->p = va_arg(*ap, void *);
+ break; case INT: arg->i = va_arg(*ap, int);
+ break; case UINT: arg->i = va_arg(*ap, unsigned int);
+#ifndef LONG_IS_INT
+ break; case LONG: arg->i = va_arg(*ap, long);
+ break; case ULONG: arg->i = va_arg(*ap, unsigned long);
+#endif
+ break; case ULLONG: arg->i = va_arg(*ap, unsigned long long);
+ break; case SHORT: arg->i = (short)va_arg(*ap, int);
+ break; case USHORT: arg->i = (unsigned short)va_arg(*ap, int);
+ break; case CHAR: arg->i = (signed char)va_arg(*ap, int);
+ break; case UCHAR: arg->i = (unsigned char)va_arg(*ap, int);
+#ifdef ODD_TYPES
+ break; case LLONG: arg->i = va_arg(*ap, long long);
+ break; case SIZET: arg->i = va_arg(*ap, size_t);
+ break; case IMAX: arg->i = va_arg(*ap, intmax_t);
+ break; case UMAX: arg->i = va_arg(*ap, uintmax_t);
+ break; case PDIFF: arg->i = va_arg(*ap, ptrdiff_t);
+ break; case UIPTR: arg->i = (uintptr_t)va_arg(*ap, void *);
+#endif
+ break; case DBL: arg->f = va_arg(*ap, double);
+ break; case LDBL: arg->f = va_arg(*ap, long double);
+ }
+}
+
+static void out(FILE *f, const char *s, size_t l)
+{
+ __fwritex((void *)s, l, f);
+}
+
+static void pad(FILE *f, char c, int w, int l, int fl)
+{
+ char pad[256];
+ if (fl & (LEFT_ADJ | ZERO_PAD) || l >= w) return;
+ l = w - l;
+ memset(pad, c, l>sizeof pad ? sizeof pad : l);
+ for (; l >= sizeof pad; l -= sizeof pad)
+ out(f, pad, sizeof pad);
+ out(f, pad, l);
+}
+
+static const char xdigits[16] = {
+ "0123456789ABCDEF"
+};
+
+static char *fmt_x(uintmax_t x, char *s, int lower)
+{
+ for (; x; x>>=4) *--s = xdigits[(x&15)]|lower;
+ return s;
+}
+
+static char *fmt_o(uintmax_t x, char *s)
+{
+ for (; x; x>>=3) *--s = '0' + (x&7);
+ return s;
+}
+
+static char *fmt_u(uintmax_t x, char *s)
+{
+ unsigned long y;
+ for ( ; x>ULONG_MAX; x/=10) *--s = '0' + x%10;
+ for (y=x; y; y/=10) *--s = '0' + y%10;
+ return s;
+}
+
+/* Do not override this check. The floating point printing code below
+ * depends on the float.h constants being right. If they are wrong, it
+ * may overflow the stack. */
+#if LDBL_MANT_DIG == 53
+typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)];
+#endif
+
+static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
+{
+ uint32_t big[(LDBL_MAX_EXP+LDBL_MANT_DIG)/9+1];
+ uint32_t *a, *d, *r, *z;
+ int e2=0, e, i, j, l;
+ char buf[9+LDBL_MANT_DIG/4], *s;
+ const char *prefix="-0X+0X 0X-0x+0x 0x";
+ int pl;
+ char ebuf0[3*sizeof(int)], *ebuf=&ebuf0[3*sizeof(int)], *estr;
+
+ pl=1;
+ if (signbit(y)) {
+ y=-y;
+ } else if (fl & MARK_POS) {
+ prefix+=3;
+ } else if (fl & PAD_POS) {
+ prefix+=6;
+ } else prefix++, pl=0;
+
+ if (!isfinite(y)) {
+ char *s = (t&32)?"inf":"INF";
+ if (y!=y) s=(t&32)?"nan":"NAN", pl=0;
+ pad(f, ' ', w, 3+pl, fl&~ZERO_PAD);
+ out(f, prefix, pl);
+ out(f, s, 3);
+ pad(f, ' ', w, 3+pl, fl^LEFT_ADJ);
+ return MAX(w, 3+pl);
+ }
+
+ y = frexpl(y, &e2) * 2;
+ if (y) e2--;
+
+ if ((t|32)=='a') {
+ long double round = 8.0;
+ int re;
+
+ if (t&32) prefix += 9;
+ pl += 2;
+
+ if (p<0 || p>=LDBL_MANT_DIG/4-1) re=0;
+ else re=LDBL_MANT_DIG/4-1-p;
+
+ if (re) {
+ while (re--) round*=16;
+ if (*prefix=='-') {
+ y=-y;
+ y-=round;
+ y+=round;
+ y=-y;
+ } else {
+ y+=round;
+ y-=round;
+ }
+ }
+
+ estr=fmt_u(e2<0 ? -e2 : e2, ebuf);
+ if (estr==ebuf) *--estr='0';
+ *--estr = (e2<0 ? '-' : '+');
+ *--estr = t+('p'-'a');
+
+ s=buf;
+ do {
+ int x=y;
+ *s++=xdigits[x]|(t&32);
+ y=16*(y-x);
+ if (s-buf==1 && (y||p>0||(fl&ALT_FORM))) *s++='.';
+ } while (y);
+
+ if (p && s-buf-2 < p)
+ l = (p+2) + (ebuf-estr);
+ else
+ l = (s-buf) + (ebuf-estr);
+
+ pad(f, ' ', w, pl+l, fl);
+ out(f, prefix, pl);
+ pad(f, '0', w, pl+l, fl^ZERO_PAD);
+ out(f, buf, s-buf);
+ pad(f, '0', l-(ebuf-estr)-(s-buf), 0, 0);
+ out(f, estr, ebuf-estr);
+ pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
+ return MAX(w, pl+l);
+ }
+ if (p<0) p=6;
+
+ if (y) y *= 0x1p28, e2-=28;
+
+ if (e2<0) a=r=z=big;
+ else a=r=z=big+sizeof(big)/sizeof(*big) - LDBL_MANT_DIG - 1;
+
+ do {
+ *z = y;
+ y = 1000000000*(y-*z++);
+ } while (y);
+
+ while (e2>0) {
+ uint32_t carry=0;
+ int sh=MIN(29,e2);
+ for (d=z-1; d>=a; d--) {
+ uint64_t x = ((uint64_t)*d<<sh)+carry;
+ *d = x % 1000000000;
+ carry = x / 1000000000;
+ }
+ if (!z[-1] && z>a) z--;
+ if (carry) *--a = carry;
+ e2-=sh;
+ }
+ while (e2<0) {
+ uint32_t carry=0, *b;
+ int sh=MIN(9,-e2);
+ for (d=a; d<z; d++) {
+ uint32_t rm = *d & (1<<sh)-1;
+ *d = (*d>>sh) + carry;
+ carry = (1000000000>>sh) * rm;
+ }
+ if (!*a) a++;
+ if (carry) *z++ = carry;
+ /* Avoid (slow!) computation past requested precision */
+ b = (t|32)=='f' ? r : a;
+ if (z-b > 2+p/9) z = b+2+p/9;
+ e2+=sh;
+ }
+
+ if (a<z) for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
+ else e=0;
+
+ /* Perform rounding: j is precision after the radix (possibly neg) */
+ j = p - ((t|32)!='f')*e - ((t|32)=='g' && p);
+ if (j < 9*(z-r-1)) {
+ uint32_t x;
+ /* We avoid C's broken division of negative numbers */
+ d = r + 1 + ((j+9*LDBL_MAX_EXP)/9 - LDBL_MAX_EXP);
+ j += 9*LDBL_MAX_EXP;
+ j %= 9;
+ for (i=10, j++; j<9; i*=10, j++);
+ x = *d % i;
+ /* Are there any significant digits past j? */
+ if (x || d+1!=z) {
+ long double round = CONCAT(0x1p,LDBL_MANT_DIG);
+ long double small;
+ if (*d/i & 1) round += 2;
+ if (x<i/2) small=0x0.8p0;
+ else if (x==i/2 && d+1==z) small=0x1.0p0;
+ else small=0x1.8p0;
+ if (pl && *prefix=='-') round*=-1, small*=-1;
+ *d -= x;
+ /* Decide whether to round by probing round+small */
+ if (round+small != round) {
+ *d = *d + i;
+ while (*d > 999999999) {
+ *d--=0;
+ (*d)++;
+ }
+ if (d<a) a=d;
+ for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
+ }
+ }
+ if (z>d+1) z=d+1;
+ for (; !z[-1] && z>a; z--);
+ }
+
+ if ((t|32)=='g') {
+ if (!p) p++;
+ if (p>e && e>=-4) {
+ t--;
+ p-=e+1;
+ } else {
+ t-=2;
+ p--;
+ }
+ if (!(fl&ALT_FORM)) {
+ /* Count trailing zeros in last place */
+ if (z>a && z[-1]) for (i=10, j=0; z[-1]%i==0; i*=10, j++);
+ else j=9;
+ if ((t|32)=='f')
+ p = MIN(p,MAX(0,9*(z-r-1)-j));
+ else
+ p = MIN(p,MAX(0,9*(z-r-1)+e-j));
+ }
+ }
+ l = 1 + p + (p || (fl&ALT_FORM));
+ if ((t|32)=='f') {
+ if (e>0) l+=e;
+ } else {
+ estr=fmt_u(e<0 ? -e : e, ebuf);
+ while(ebuf-estr<2) *--estr='0';
+ *--estr = (e<0 ? '-' : '+');
+ *--estr = t;
+ l += ebuf-estr;
+ }
+
+ pad(f, ' ', w, pl+l, fl);
+ out(f, prefix, pl);
+ pad(f, '0', w, pl+l, fl^ZERO_PAD);
+
+ if ((t|32)=='f') {
+ if (a>r) a=r;
+ for (d=a; d<=r; d++) {
+ char *s = fmt_u(*d, buf+9);
+ if (d!=a) while (s>buf) *--s='0';
+ else if (s==buf+9) *--s='0';
+ out(f, s, buf+9-s);
+ }
+ if (p || (fl&ALT_FORM)) out(f, ".", 1);
+ for (; d<z && p>0; d++, p-=9) {
+ char *s = fmt_u(*d, buf+9);
+ while (s>buf) *--s='0';
+ out(f, s, MIN(9,p));
+ }
+ pad(f, '0', p+9, 9, 0);
+ } else {
+ if (z<=a) z=a+1;
+ for (d=a; d<z && p>=0; d++) {
+ char *s = fmt_u(*d, buf+9);
+ if (s==buf+9) *--s='0';
+ if (d!=a) while (s>buf) *--s='0';
+ else {
+ out(f, s++, 1);
+ if (p>0||(fl&ALT_FORM)) out(f, ".", 1);
+ }
+ out(f, s, MIN(buf+9-s, p));
+ p -= buf+9-s;
+ }
+ pad(f, '0', p+18, 18, 0);
+ out(f, estr, ebuf-estr);
+ }
+
+ pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
+
+ return MAX(w, pl+l);
+}
+
+static int getint(char **s) {
+ int i;
+ for (i=0; isdigit(**s); (*s)++)
+ i = 10*i + (**s-'0');
+ return i;
+}
+
+static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, int *nl_type)
+{
+ char *a, *z, *s=(char *)fmt;
+ unsigned l10n=0, fl;
+ int w, p;
+ union arg arg;
+ int argpos;
+ unsigned st, ps;
+ int cnt=0, l=0;
+ int i;
+ char buf[sizeof(uintmax_t)*3+3+LDBL_MANT_DIG/4];
+ const char *prefix;
+ int t, pl;
+ wchar_t wc[2], *ws;
+ char mb[4];
+
+ for (;;) {
+ /* Update output count, end loop when fmt is exhausted */
+ if (cnt >= 0) {
+ if (l > INT_MAX - cnt) {
+ errno = EOVERFLOW;
+ cnt = -1;
+ } else cnt += l;
+ }
+ if (!*s) break;
+
+ /* Handle literal text and %% format specifiers */
+ for (a=s; *s && *s!='%'; s++);
+ for (z=s; s[0]=='%' && s[1]=='%'; z++, s+=2);
+ l = z-a;
+ if (f) out(f, a, l);
+ if (l) continue;
+
+ if (isdigit(s[1]) && s[2]=='$') {
+ l10n=1;
+ argpos = s[1]-'0';
+ s+=3;
+ } else {
+ argpos = -1;
+ s++;
+ }
+
+ /* Read modifier flags */
+ for (fl=0; (unsigned)*s-' '<32 && (FLAGMASK&(1U<<*s-' ')); s++)
+ fl |= 1U<<*s-' ';
+
+ /* Read field width */
+ if (*s=='*') {
+ if (isdigit(s[1]) && s[2]=='$') {
+ l10n=1;
+ nl_type[s[1]-'0'] = INT;
+ w = nl_arg[s[1]-'0'].i;
+ s+=3;
+ } else if (!l10n) {
+ w = f ? va_arg(*ap, int) : 0;
+ s++;
+ } else return -1;
+ if (w<0) fl|=LEFT_ADJ, w=-w;
+ } else if ((w=getint(&s))<0) return -1;
+
+ /* Read precision */
+ if (*s=='.' && s[1]=='*') {
+ if (isdigit(s[2]) && s[3]=='$') {
+ nl_type[s[2]-'0'] = INT;
+ p = nl_arg[s[2]-'0'].i;
+ s+=4;
+ } else if (!l10n) {
+ p = f ? va_arg(*ap, int) : 0;
+ s+=2;
+ } else return -1;
+ } else if (*s=='.') {
+ s++;
+ p = getint(&s);
+ } else p = -1;
+
+ /* Format specifier state machine */
+ st=0;
+ do {
+ if (OOB(*s)) return -1;
+ ps=st;
+ st=states[st]S(*s++);
+ } while (st-1<STOP);
+ if (!st) return -1;
+
+ /* Check validity of argument type (nl/normal) */
+ if (st==NOARG) {
+ if (argpos>=0) return -1;
+ else if (!f) continue;
+ } else {
+ if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos];
+ else if (f) pop_arg(&arg, st, ap);
+ else return 0;
+ }
+
+ if (!f) continue;
+
+ z = buf + sizeof(buf);
+ prefix = "-+ 0X0x";
+ pl = 0;
+ t = s[-1];
+
+ /* Transform ls,lc -> S,C */
+ if (ps && (t&15)==3) t&=~32;
+
+ /* - and 0 flags are mutually exclusive */
+ if (fl & LEFT_ADJ) fl &= ~ZERO_PAD;
+
+ switch(t) {
+ case 'n':
+ switch(ps) {
+ case BARE: *(int *)arg.p = cnt; break;
+ case LPRE: *(long *)arg.p = cnt; break;
+ case LLPRE: *(long long *)arg.p = cnt; break;
+ case HPRE: *(unsigned short *)arg.p = cnt; break;
+ case HHPRE: *(unsigned char *)arg.p = cnt; break;
+ case ZTPRE: *(size_t *)arg.p = cnt; break;
+ case JPRE: *(uintmax_t *)arg.p = cnt; break;
+ }
+ continue;
+ case 'p':
+ p = MAX(p, 2*sizeof(void*));
+ t = 'x';
+ fl |= ALT_FORM;
+ case 'x': case 'X':
+ a = fmt_x(arg.i, z, t&32);
+ if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2;
+ if (0) {
+ case 'o':
+ a = fmt_o(arg.i, z);
+ if ((fl&ALT_FORM) && arg.i) prefix+=5, pl=1;
+ } if (0) {
+ case 'd': case 'i':
+ pl=1;
+ if (arg.i>INTMAX_MAX) {
+ arg.i=-arg.i;
+ } else if (fl & MARK_POS) {
+ prefix++;
+ } else if (fl & PAD_POS) {
+ prefix+=2;
+ } else pl=0;
+ case 'u':
+ a = fmt_u(arg.i, z);
+ }
+ if (p>=0) fl &= ~ZERO_PAD;
+ if (!arg.i && !p) {
+ a=z;
+ break;
+ }
+ p = MAX(p, z-a + !arg.i);
+ break;
+ case 'c':
+ *(a=z-(p=1))=arg.i;
+ fl &= ~ZERO_PAD;
+ break;
+ case 'm':
+ if (1) a = strerror(errno); else
+ case 's':
+ a = arg.p ? arg.p : "(null)";
+ z = memchr(a, 0, p);
+ if (!z) z=a+p;
+ else p=z-a;
+ fl &= ~ZERO_PAD;
+ break;
+ case 'C':
+ wc[0] = arg.i;
+ wc[1] = 0;
+ arg.p = wc;
+ p = -1;
+ case 'S':
+ ws = arg.p;
+ for (i=l=0; i<0U+p && *ws && (l=wctomb(mb, *ws++))>=0 && l<=0U+p-i; i+=l);
+ if (l<0) return -1;
+ p = i;
+ pad(f, ' ', w, p, fl);
+ ws = arg.p;
+ for (i=0; i<0U+p && *ws && i+(l=wctomb(mb, *ws++))<=p; i+=l)
+ out(f, mb, l);
+ pad(f, ' ', w, p, fl^LEFT_ADJ);
+ l = w>p ? w : p;
+ continue;
+ case 'e': case 'f': case 'g': case 'a':
+ case 'E': case 'F': case 'G': case 'A':
+ l = fmt_fp(f, arg.f, w, p, fl, t);
+ continue;
+ }
+
+ if (p < z-a) p = z-a;
+ if (w < pl+p) w = pl+p;
+
+ pad(f, ' ', w, pl+p, fl);
+ out(f, prefix, pl);
+ pad(f, '0', w, pl+p, fl^ZERO_PAD);
+ pad(f, '0', p, z-a, 0);
+ out(f, a, z-a);
+ pad(f, ' ', w, pl+p, fl^LEFT_ADJ);
+
+ l = w;
+ }
+
+ if (f) return cnt;
+ if (!l10n) return 0;
+
+ for (i=1; i<=NL_ARGMAX && nl_type[i]; i++)
+ pop_arg(nl_arg+i, nl_type[i], ap);
+ for (; i<=NL_ARGMAX && !nl_type[i]; i++);
+ if (i<=NL_ARGMAX) return -1;
+ return 1;
+}
+
+//int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap)
+int MUSL_vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) /// XXX Emscripten: Only use musl-specific vfprintf when called from within sprintf.
+{
+ va_list ap2;
+ int nl_type[NL_ARGMAX+1] = {0};
+ union arg nl_arg[NL_ARGMAX+1];
+ unsigned char internal_buf[80], *saved_buf = 0;
+ int ret;
+
+ va_copy(ap2, ap);
+ if (printf_core(0, fmt, &ap2, nl_arg, nl_type) < 0) return -1;
+
+ FLOCK(f);
+ if (!f->buf_size) {
+ saved_buf = f->buf;
+ f->wpos = f->wbase = f->buf = internal_buf;
+ f->buf_size = sizeof internal_buf;
+ f->wend = internal_buf + sizeof internal_buf;
+ }
+ ret = printf_core(f, fmt, &ap2, nl_arg, nl_type);
+ if (saved_buf) {
+ f->write(f, 0, 0);
+ if (!f->wpos) ret = -1;
+ f->buf = saved_buf;
+ f->buf_size = 0;
+ f->wpos = f->wbase = f->wend = 0;
+ }
+ FUNLOCK(f);
+ va_end(ap2);
+ return ret;
+}
diff --git a/system/lib/libc/musl/src/stdio/vfscanf.c b/system/lib/libc/musl/src/stdio/vfscanf.c
new file mode 100644
index 00000000..5373eea6
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/vfscanf.c
@@ -0,0 +1,332 @@
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <wchar.h>
+#include <wctype.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+#include <float.h>
+#include <inttypes.h>
+
+#include "stdio_impl.h"
+#include "shgetc.h"
+#include "intscan.h"
+#include "floatscan.h"
+
+#define SIZE_hh -2
+#define SIZE_h -1
+#define SIZE_def 0
+#define SIZE_l 1
+#define SIZE_L 2
+#define SIZE_ll 3
+
+static void store_int(void *dest, int size, unsigned long long i)
+{
+ if (!dest) return;
+ switch (size) {
+ case SIZE_hh:
+ *(char *)dest = i;
+ break;
+ case SIZE_h:
+ *(short *)dest = i;
+ break;
+ case SIZE_def:
+ *(int *)dest = i;
+ break;
+ case SIZE_l:
+ *(long *)dest = i;
+ break;
+ case SIZE_ll:
+ *(long long *)dest = i;
+ break;
+ }
+}
+
+static void *arg_n(va_list ap, unsigned int n)
+{
+ void *p;
+ unsigned int i;
+ va_list ap2;
+ va_copy(ap2, ap);
+ for (i=n; i>1; i--) va_arg(ap2, void *);
+ p = va_arg(ap2, void *);
+ va_end(ap2);
+ return p;
+}
+
+//int vfscanf(FILE *restrict f, const char *restrict fmt, va_list ap)
+int MUSL_vfscanf(FILE *restrict f, const char *restrict fmt, va_list ap) // XXX Emscripten: Only use musl-specific vfscanf when called from within sscanf.
+{
+ int width;
+ int size;
+ int alloc;
+ int base;
+ const unsigned char *p;
+ int c, t;
+ char *s;
+ wchar_t *wcs;
+ mbstate_t st;
+ void *dest=NULL;
+ int invert;
+ int matches=0;
+ unsigned long long x;
+ long double y;
+ off_t pos = 0;
+ unsigned char scanset[257];
+ size_t i, k;
+ wchar_t wc;
+
+ FLOCK(f);
+
+ for (p=(const unsigned char *)fmt; *p; p++) {
+
+ alloc = 0;
+
+ if (isspace(*p)) {
+ while (isspace(p[1])) p++;
+ shlim(f, 0);
+ while (isspace(shgetc(f)));
+ shunget(f);
+ pos += shcnt(f);
+ continue;
+ }
+ if (*p != '%' || p[1] == '%') {
+ p += *p=='%';
+ shlim(f, 0);
+ c = shgetc(f);
+ if (c!=*p) {
+ shunget(f);
+ if (c<0) goto input_fail;
+ goto match_fail;
+ }
+ pos++;
+ continue;
+ }
+
+ p++;
+ if (*p=='*') {
+ dest = 0; p++;
+ } else if (isdigit(*p) && p[1]=='$') {
+ dest = arg_n(ap, *p-'0'); p+=2;
+ } else {
+ dest = va_arg(ap, void *);
+ }
+
+ for (width=0; isdigit(*p); p++) {
+ width = 10*width + *p - '0';
+ }
+
+ if (*p=='m') {
+ alloc = !!dest;
+ p++;
+ } else {
+ alloc = 0;
+ }
+
+ size = SIZE_def;
+ switch (*p++) {
+ case 'h':
+ if (*p == 'h') p++, size = SIZE_hh;
+ else size = SIZE_h;
+ break;
+ case 'l':
+ if (*p == 'l') p++, size = SIZE_ll;
+ else size = SIZE_l;
+ break;
+ case 'j':
+ size = SIZE_ll;
+ break;
+ case 'z':
+ case 't':
+ size = SIZE_l;
+ break;
+ case 'L':
+ size = SIZE_L;
+ break;
+ case 'd': case 'i': case 'o': case 'u': case 'x':
+ case 'a': case 'e': case 'f': case 'g':
+ case 'A': case 'E': case 'F': case 'G': case 'X':
+ case 's': case 'c': case '[':
+ case 'S': case 'C':
+ case 'p': case 'n':
+ p--;
+ break;
+ default:
+ goto fmt_fail;
+ }
+
+ t = *p;
+
+ /* C or S */
+ if ((t&0x2f) == 3) {
+ t |= 32;
+ size = SIZE_l;
+ }
+
+ switch (t) {
+ case 'c':
+ if (width < 1) width = 1;
+ case '[':
+ break;
+ case 'n':
+ store_int(dest, size, pos);
+ /* do not increment match count, etc! */
+ continue;
+ default:
+ shlim(f, 0);
+ while (isspace(shgetc(f)));
+ shunget(f);
+ pos += shcnt(f);
+ }
+
+ shlim(f, width);
+ if (shgetc(f) < 0) goto input_fail;
+ shunget(f);
+
+ switch (t) {
+ case 's':
+ case 'c':
+ case '[':
+ if (t == 'c' || t == 's') {
+ memset(scanset, -1, sizeof scanset);
+ scanset[0] = 0;
+ if (t == 's') {
+ scanset[1+'\t'] = 0;
+ scanset[1+'\n'] = 0;
+ scanset[1+'\v'] = 0;
+ scanset[1+'\f'] = 0;
+ scanset[1+'\r'] = 0;
+ scanset[1+' '] = 0;
+ }
+ } else {
+ if (*++p == '^') p++, invert = 1;
+ else invert = 0;
+ memset(scanset, invert, sizeof scanset);
+ scanset[0] = 0;
+ if (*p == '-') p++, scanset[1+'-'] = 1-invert;
+ else if (*p == ']') p++, scanset[1+']'] = 1-invert;
+ for (; *p != ']'; p++) {
+ if (!*p) goto fmt_fail;
+ if (*p=='-' && p[1] && p[1] != ']')
+ for (c=p++[-1]; c<*p; c++)
+ scanset[1+c] = 1-invert;
+ scanset[1+*p] = 1-invert;
+ }
+ }
+ wcs = 0;
+ s = 0;
+ i = 0;
+ k = t=='c' ? width+1U : 31;
+ if (size == SIZE_l) {
+ if (alloc) {
+ wcs = malloc(k*sizeof(wchar_t));
+ if (!wcs) goto alloc_fail;
+ } else {
+ wcs = dest;
+ }
+ st = (mbstate_t){0};
+ while (scanset[(c=shgetc(f))+1]) {
+ switch (mbrtowc(&wc, &(char){c}, 1, &st)) {
+ case -1:
+ goto input_fail;
+ case -2:
+ continue;
+ }
+ if (wcs) wcs[i++] = wc;
+ if (alloc && i==k) {
+ k+=k+1;
+ wchar_t *tmp = realloc(wcs, k*sizeof(wchar_t));
+ if (!tmp) goto alloc_fail;
+ wcs = tmp;
+ }
+ }
+ if (!mbsinit(&st)) goto input_fail;
+ } else if (alloc) {
+ s = malloc(k);
+ if (!s) goto alloc_fail;
+ while (scanset[(c=shgetc(f))+1]) {
+ s[i++] = c;
+ if (i==k) {
+ k+=k+1;
+ char *tmp = realloc(s, k);
+ if (!tmp) goto alloc_fail;
+ s = tmp;
+ }
+ }
+ } else if ((s = dest)) {
+ while (scanset[(c=shgetc(f))+1])
+ s[i++] = c;
+ } else {
+ while (scanset[(c=shgetc(f))+1]);
+ }
+ shunget(f);
+ if (!shcnt(f)) goto match_fail;
+ if (t == 'c' && shcnt(f) != width) goto match_fail;
+ if (alloc) {
+ if (size == SIZE_l) *(wchar_t **)dest = wcs;
+ else *(char **)dest = s;
+ }
+ if (t != 'c') {
+ if (wcs) wcs[i] = 0;
+ if (s) s[i] = 0;
+ }
+ break;
+ case 'p':
+ case 'X':
+ case 'x':
+ base = 16;
+ goto int_common;
+ case 'o':
+ base = 8;
+ goto int_common;
+ case 'd':
+ case 'u':
+ base = 10;
+ goto int_common;
+ case 'i':
+ base = 0;
+ int_common:
+ x = __intscan(f, base, 0, ULLONG_MAX);
+ if (!shcnt(f)) goto match_fail;
+ if (t=='p' && dest) *(void **)dest = (void *)(uintptr_t)x;
+ else store_int(dest, size, x);
+ break;
+ case 'a': case 'A':
+ case 'e': case 'E':
+ case 'f': case 'F':
+ case 'g': case 'G':
+ y = __floatscan(f, size, 0);
+ if (!shcnt(f)) goto match_fail;
+ if (dest) switch (size) {
+ case SIZE_def:
+ *(float *)dest = y;
+ break;
+ case SIZE_l:
+ *(double *)dest = y;
+ break;
+ case SIZE_L:
+ *(long double *)dest = y;
+ break;
+ }
+ break;
+ }
+
+ pos += shcnt(f);
+ if (dest) matches++;
+ }
+ if (0) {
+fmt_fail:
+alloc_fail:
+input_fail:
+ if (!matches) matches--;
+match_fail:
+ if (alloc) {
+ free(s);
+ free(wcs);
+ }
+ }
+ FUNLOCK(f);
+ return matches;
+}
diff --git a/system/lib/libc/musl/src/stdio/vsnprintf.c b/system/lib/libc/musl/src/stdio/vsnprintf.c
new file mode 100644
index 00000000..9dcc84af
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/vsnprintf.c
@@ -0,0 +1,45 @@
+#include "stdio_impl.h"
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+
+static size_t sn_write(FILE *f, const unsigned char *s, size_t l)
+{
+ size_t k = f->wend - f->wpos;
+ if (k > l) k = l;
+ memcpy(f->wpos, s, k);
+ f->wpos += k;
+ /* pretend to succeed, but discard extra data */
+ return l;
+}
+
+// XXX Emscripten Call to musl-specific vfprintf for better asm.js performance, instead of the handwritten js function.
+#define vfprintf MUSL_vfprintf
+
+int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap)
+{
+ int r;
+ char b;
+ FILE f = { .lbf = EOF, .write = sn_write, .lock = -1 };
+
+ if (n-1 > INT_MAX-1) {
+ if (n) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ s = &b;
+ n = 1;
+ }
+
+ /* Ensure pointers don't wrap if "infinite" n is passed in */
+ if (n > (char *)0+SIZE_MAX-s-1) n = (char *)0+SIZE_MAX-s-1;
+ f.buf_size = n;
+ f.buf = f.wpos = (void *)s;
+ f.wbase = f.wend = (void *)(s+n);
+ r = vfprintf(&f, fmt, ap);
+
+ /* Null-terminate, overwriting last char if dest buffer is full */
+ if (n) f.wpos[-(f.wpos == f.wend)] = 0;
+ return r;
+}
diff --git a/system/lib/libc/musl/src/stdio/vsprintf.c b/system/lib/libc/musl/src/stdio/vsprintf.c
new file mode 100644
index 00000000..c57349d4
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/vsprintf.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <limits.h>
+
+int vsprintf(char *restrict s, const char *restrict fmt, va_list ap)
+{
+ return vsnprintf(s, INT_MAX, fmt, ap);
+}
diff --git a/system/lib/libc/musl/src/stdio/vsscanf.c b/system/lib/libc/musl/src/stdio/vsscanf.c
new file mode 100644
index 00000000..6492f78b
--- /dev/null
+++ b/system/lib/libc/musl/src/stdio/vsscanf.c
@@ -0,0 +1,20 @@
+#include "stdio_impl.h"
+#include "libc.h"
+
+static size_t do_read(FILE *f, unsigned char *buf, size_t len)
+{
+ return __string_read(f, buf, len);
+}
+
+#define vfscanf MUSL_vfscanf // XXX Emscripten: Call into musl version of vfscanf for asm.js performance, not the handwritten js version.
+
+int vsscanf(const char *restrict s, const char *restrict fmt, va_list ap)
+{
+ FILE f = {
+ .buf = (void *)s, .cookie = (void *)s,
+ .read = do_read, .lock = -1
+ };
+ return vfscanf(&f, fmt, ap);
+}
+
+weak_alias(vsscanf,__isoc99_vsscanf);
diff --git a/system/lib/libc/musl/src/stdlib/strtol.c b/system/lib/libc/musl/src/stdlib/strtol.c
new file mode 100644
index 00000000..730bf2d7
--- /dev/null
+++ b/system/lib/libc/musl/src/stdlib/strtol.c
@@ -0,0 +1,64 @@
+#include "stdio_impl.h"
+#include "intscan.h"
+#include "shgetc.h"
+#include <inttypes.h>
+#include <limits.h>
+#include <ctype.h>
+#include "libc.h"
+
+static unsigned long long strtox(const char *s, char **p, int base, unsigned long long lim)
+{
+ /* FIXME: use a helper function or macro to setup the FILE */
+ FILE f;
+ f.flags = 0;
+ f.buf = f.rpos = (void *)s;
+ if ((size_t)s > (size_t)-1/2)
+ f.rend = (void *)-1;
+ else
+ f.rend = (unsigned char *)s+(size_t)-1/2;
+ f.lock = -1;
+ shlim(&f, 0);
+ unsigned long long y = __intscan(&f, base, 1, lim);
+ if (p) {
+ size_t cnt = shcnt(&f);
+ *p = (char *)s + cnt;
+ }
+ return y;
+}
+
+unsigned long long strtoull(const char *restrict s, char **restrict p, int base)
+{
+ return strtox(s, p, base, ULLONG_MAX);
+}
+
+long long strtoll(const char *restrict s, char **restrict p, int base)
+{
+ return strtox(s, p, base, LLONG_MIN);
+}
+
+unsigned long strtoul(const char *restrict s, char **restrict p, int base)
+{
+ return strtox(s, p, base, ULONG_MAX);
+}
+
+long strtol(const char *restrict s, char **restrict p, int base)
+{
+ return strtox(s, p, base, 0UL+LONG_MIN);
+}
+
+intmax_t strtoimax(const char *restrict s, char **restrict p, int base)
+{
+ return strtoll(s, p, base);
+}
+
+uintmax_t strtoumax(const char *restrict s, char **restrict p, int base)
+{
+ return strtoull(s, p, base);
+}
+
+weak_alias(strtol, __strtol_internal);
+weak_alias(strtoul, __strtoul_internal);
+weak_alias(strtoll, __strtoll_internal);
+weak_alias(strtoull, __strtoull_internal);
+weak_alias(strtoimax, __strtoimax_internal);
+weak_alias(strtoumax, __strtoumax_internal);
diff --git a/system/lib/libcextra.symbols b/system/lib/libcextra.symbols
index 64ba670a..1ab849bd 100644
--- a/system/lib/libcextra.symbols
+++ b/system/lib/libcextra.symbols
@@ -1,7 +1,6 @@
T __cos
T __cosdf
T __fputwc_unlocked
- T __intscan
W __iswctype_l
T __lgamma_r
T __lgammaf_r
@@ -22,6 +21,7 @@
T __wcscoll_l
T __wcsxfrm_l
W __wctype_l
+ T asprintf
T atoll
T bcmp
T bcopy
@@ -46,6 +46,27 @@
T ilogbf
T ilogbl
T index
+ T isascii
+ T islower
+ T islower_l
+ T isupper_l
+ T isalpha
+ T isalpha_l
+ T isblank_l
+ T isdigit_l
+ T isxdigit
+ T isxdigit_l
+ T isalnum
+ T isalnum_l
+ T ispunct
+ T ispunct_l
+ T isspace_l
+ T iscntrl
+ T iscntrl_l
+ T isprint
+ T isprint_l
+ T isgraph
+ T isgraph_l
T iswalnum
T iswalnum_l
T iswalpha
@@ -93,7 +114,6 @@
T mbstowcs
T mbtowc
T memccpy
- T memchr
T memmem
T mempcpy
W memrchr
@@ -111,6 +131,7 @@
T rindex
T scalbnf
D signgam
+ T sscanf
T stpcpy
T strcasecmp_l
T strcasestr
@@ -122,6 +143,7 @@
T strfmon_l
T strlcat
T strlcpy
+ T strlwr
T strncasecmp_l
T strncat
T strndup
@@ -133,6 +155,11 @@
T strstr
T strtok
T strtok_r
+ T strtoull_l
+ T strtoll_l
+ T strtoul_l
+ T strtol_l
+ T strupr
T strverscmp
T strxfrm
W strxfrm_l
@@ -140,14 +167,21 @@
T tgamma
T tgammaf
T tgammal
+ T toascii
+ T toupper
+ T toupper_l
+ T tolower_l
T towctrans
T towctrans_l
T towlower
T towlower_l
T towupper
T towupper_l
+ T vasprintf
T verr
T verrx
+ T MUSL_vfscanf
+ T vsscanf
T vfwprintf
T vswprintf
T vwarn
@@ -157,7 +191,6 @@
T warnx
T wcpcpy
T wcpncpy
- T wcrtomb
T wcscasecmp
T wcscasecmp_l
T wcscat
@@ -197,7 +230,6 @@
T wcsxfrm
T wcsxfrm_l
T wctob
- T wctomb
T wctrans
T wctrans_l
T wctype
diff --git a/tests/cases/floatundefinvoke_fastcomp.ll b/tests/cases/floatundefinvoke_fastcomp.ll
new file mode 100644
index 00000000..215506ef
--- /dev/null
+++ b/tests/cases/floatundefinvoke_fastcomp.ll
@@ -0,0 +1,30 @@
+; ModuleID = 'a.o'
+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:128-n32-S128"
+target triple = "asmjs-unknown-emscripten"
+
+@.str = private unnamed_addr constant [11 x i8] c"float: %f\0A\00", align 1
+
+define void @_Z10printFloatf(float %f) #0 {
+entry:
+ %conv = fpext float %f to double
+ %call = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @.str, i32 0, i32 0), double %conv)
+ ret void
+}
+
+define i32 @main() #1 {
+entry:
+ tail call void @_Z10printFloatf(float 1.000000e+00)
+ call void @emscripten_preinvoke()
+ call void @_Z10printFloatf(float undef)
+ %last = call i32 @emscripten_postinvoke()
+ %lastf = sitofp i32 %last to float
+ tail call void @_Z10printFloatf(float %lastf)
+ ret i32 1
+}
+
+declare void @emscripten_preinvoke()
+declare i32 @emscripten_postinvoke()
+declare i32 @printf(i8* nocapture, ...) #1
+
+attributes #0 = { noinline nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
diff --git a/tests/cases/floatundefinvoke_fastcomp.txt b/tests/cases/floatundefinvoke_fastcomp.txt
new file mode 100644
index 00000000..5e19391e
--- /dev/null
+++ b/tests/cases/floatundefinvoke_fastcomp.txt
@@ -0,0 +1,3 @@
+float: 1.000000
+float: 0.000000
+float: 0.000000
diff --git a/tests/cases/i1tof_ta2.ll b/tests/cases/i1tof_ta2.ll
new file mode 100644
index 00000000..12940907
--- /dev/null
+++ b/tests/cases/i1tof_ta2.ll
@@ -0,0 +1,71 @@
+; ModuleID = 'bad/emcc-0-basebc.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:128-n32-S128"
+target triple = "asmjs-unknown-emscripten"
+
+@.str = private unnamed_addr constant [7 x i8] c"%0.1f\0A\00", align 1
+@.str2 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
+
+; Function Attrs: noinline
+define float @_Z2v1v() #0 {
+entry:
+ %call = tail call double @emscripten_get_now()
+ %cmp = fcmp oge double %call, 0.000000e+00
+ %cond = select i1 %cmp, float 0x3FECCCCCC0000000, float 0.000000e+00
+ ret float %cond
+}
+
+define double @emscripten_get_now() #0 {
+ ret double 1.0
+}
+
+; Function Attrs: noinline
+define float @_Z2v2v() #0 {
+entry:
+ %call = tail call double @emscripten_get_now()
+ %cmp = fcmp oge double %call, 0.000000e+00
+ %cond = select i1 %cmp, float 0x3FD99999A0000000, float 0.000000e+00
+ ret float %cond
+}
+
+; Function Attrs: noinline
+define float @_Z2v3v() #0 {
+entry:
+ %call = tail call double @emscripten_get_now()
+ %cmp = fcmp oge double %call, 0.000000e+00
+ %cond = select i1 %cmp, float 0x3FB99999A0000000, float 0.000000e+00
+ ret float %cond
+}
+
+define i32 @main() #1 {
+entry:
+ %call = tail call float @_Z2v1v()
+ %call1 = tail call float @_Z2v2v()
+ %call2 = tail call float @_Z2v3v()
+ %sub = fsub float %call1, %call
+ %cmp.i = fcmp ogt float %sub, 0.000000e+00
+ br i1 %cmp.i, label %_ZL5signff.exit, label %cond.false.i
+
+cond.false.i: ; preds = %entry
+ %cmp1.i = fcmp olt float %sub, 0.000000e+00
+ %phitmp = sitofp i1 %cmp1.i to float
+ %phitmpd = fpext float %phitmp to double
+ %call1115a = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([7 x i8]* @.str, i32 0, i32 0), double %phitmpd)
+ %phitmpi = sext i1 %cmp1.i to i32
+ %call1115b = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str2, i32 0, i32 0), i32 %phitmpi)
+ br label %_ZL5signff.exit
+
+_ZL5signff.exit: ; preds = %cond.false.i, %entry
+ %cond2.i = phi float [ %phitmp, %cond.false.i ], [ 1.000000e+00, %entry ]
+ %mul = fmul float %call2, %cond2.i
+ %add = fadd float %call, %mul
+ %conv4 = fpext float %add to double
+ %call5 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([7 x i8]* @.str, i32 0, i32 0), double %conv4)
+ ret i32 0
+}
+
+; Function Attrs: nounwind
+declare i32 @printf(i8* nocapture, ...) #2
+
+attributes #0 = { noinline "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
diff --git a/tests/cases/i1tof_ta2.txt b/tests/cases/i1tof_ta2.txt
new file mode 100644
index 00000000..5d3943cd
--- /dev/null
+++ b/tests/cases/i1tof_ta2.txt
@@ -0,0 +1,3 @@
+-1.0
+-1
+0.8
diff --git a/tests/cases/redundantswitch_fastcomp.ll b/tests/cases/redundantswitch_fastcomp.ll
new file mode 100644
index 00000000..5b797ac8
--- /dev/null
+++ b/tests/cases/redundantswitch_fastcomp.ll
@@ -0,0 +1,28 @@
+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:128-n32-S128"
+target triple = "asmjs-unknown-emscripten"
+
+@.str = private constant [18 x i8] c"hello, world: %d\0A\00", align 1
+
+declare i32 @printf(i8*, ...)
+
+define linkonce_odr i32 @main() align 2 {
+entry:
+ %temp32 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([18 x i8]* @.str, i32 0, i32 0), i32 5)
+ switch i32 %temp32, label %mid1 [
+ i32 1000, label %mid1
+ i32 1001, label %mid2
+ i32 2000, label %finish
+ ]
+
+mid1:
+ br label %finish
+
+mid2:
+ br label %finish
+
+finish: ; preds = %555
+ %last = phi i32 [0, %entry], [1, %mid1], [2, %mid2]
+ %a333c = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([18 x i8]* @.str, i32 0, i32 0), i32 %last)
+ ret i32 0
+}
+
diff --git a/tests/cases/redundantswitch_fastcomp.txt b/tests/cases/redundantswitch_fastcomp.txt
new file mode 100644
index 00000000..72084b0c
--- /dev/null
+++ b/tests/cases/redundantswitch_fastcomp.txt
@@ -0,0 +1,2 @@
+hello, world: 5
+hello, world: 1
diff --git a/tests/cmake/target_library/CMakeLists.txt b/tests/cmake/target_library/CMakeLists.txt
new file mode 100644
index 00000000..c7023192
--- /dev/null
+++ b/tests/cmake/target_library/CMakeLists.txt
@@ -0,0 +1,43 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(test_cmake)
+
+option(BUILD_SHARED_LIBS "Build with shared libraries." OFF)
+
+if (CMAKE_BUILD_TYPE STREQUAL Debug)
+ SET(linkFlags "-g4")
+else() # Either MinSizeRel, RelWithDebInfo or Release, all which run with optimizations enabled.
+ SET(linkFlags "-O2")
+endif()
+
+set(MAX_SRC_FILE_INDEX 30)
+SET(TEST_SRC_FILE_BASE_NAME "this_is_a_test_src_file_with_a_quite_lengthy_name_to_simulate_very_long_command_line_length_problems_on_windows_")
+
+
+foreach(i RANGE ${MAX_SRC_FILE_INDEX})
+ set (TEST_FUNCTION_NAME "FooBar_${i}")
+ configure_file("srcfile.cmake" "${TEST_SRC_FILE_BASE_NAME}${i}.c")
+ configure_file("srcfile.cmake" "${TEST_SRC_FILE_BASE_NAME}${i}.cpp")
+ list(APPEND TEST_SOURCES "${TEST_SRC_FILE_BASE_NAME}${i}.c" "${TEST_SRC_FILE_BASE_NAME}${i}.cpp")
+endforeach()
+
+add_library(test_cmake ${TEST_SOURCES})
+
+if (WIN32)
+ message(FATAL_ERROR "WIN32 should not be defined when cross-compiling!")
+endif()
+
+if (APPLE)
+ message(FATAL_ERROR "APPLE should not be defined when cross-compiling!")
+endif()
+
+if (NOT EMSCRIPTEN)
+ message(FATAL_ERROR "EMSCRIPTEN should be defined when cross-compiling!")
+endif()
+
+if (NOT CMAKE_C_SIZEOF_DATA_PTR)
+ message(FATAL_ERROR "CMAKE_C_SIZEOF_DATA_PTR was not defined!")
+endif()
+
+# GOTCHA: If your project has custom link flags, these must be set *before* calling any of the em_link_xxx functions!
+set_target_properties(test_cmake PROPERTIES LINK_FLAGS "${linkFlags}")
diff --git a/tests/cmake/target_library/srcfile.cmake b/tests/cmake/target_library/srcfile.cmake
new file mode 100644
index 00000000..10e9e6f8
--- /dev/null
+++ b/tests/cmake/target_library/srcfile.cmake
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void @TEST_FUNCTION_NAME@()
+{
+ printf("@TEST_FUNCTION_NAME@");
+}
diff --git a/tests/core/test_double_varargs.c b/tests/core/test_double_varargs.c
new file mode 100644
index 00000000..d3eb3eed
--- /dev/null
+++ b/tests/core/test_double_varargs.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+double func_int_double_1(int unused1, ...)
+{
+ int i;
+ double d;
+ va_list vl;
+ va_start(vl, unused1);
+ i = va_arg(vl, int);
+ d = va_arg(vl, double);
+ va_end(vl);
+ return i+d;
+}
+
+double func_int_double_2(int unused1, int unused2, ...)
+{
+ int i;
+ double d;
+ va_list vl;
+ va_start(vl, unused2);
+ i = va_arg(vl, int);
+ d = va_arg(vl, double);
+ va_end(vl);
+ return i+d;
+}
+
+int main() {
+ double ret = func_int_double_1(0, 5, 10.0);
+ printf("%f\n", ret); // Expects to print 15
+ ret = func_int_double_2(0, 0, 5, 10.0);
+ printf("%f\n", ret); // Expects to print 15
+}
+
diff --git a/tests/core/test_double_varargs.out b/tests/core/test_double_varargs.out
new file mode 100644
index 00000000..c907dece
--- /dev/null
+++ b/tests/core/test_double_varargs.out
@@ -0,0 +1,2 @@
+15.000000
+15.000000
diff --git a/tests/core/test_exceptions_white_list_empty.out b/tests/core/test_exceptions_white_list_empty.out
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tests/core/test_exceptions_white_list_empty.out
diff --git a/tests/core/test_floatvars.in b/tests/core/test_floatvars.in
index b6c94c82..d59b6028 100644
--- a/tests/core/test_floatvars.in
+++ b/tests/core/test_floatvars.in
@@ -15,13 +15,8 @@ int main(int argc, char **argv) {
printf("small: %.10f\n", argc * 0.000001);
- /*
- // Rounding behavior
- float fs[6] = { -2.75, -2.50, -2.25, 2.25, 2.50, 2.75 };
- double ds[6] = { -2.75, -2.50, -2.25, 2.25, 2.50, 2.75 };
- for (int i = 0; i < 6; i++)
- printf("*int(%.2f)=%d,%d*\n", fs[i], int(fs[i]), int(ds[i]));
- */
+ double d = 1.12345678901234567890123e21;
+ printf("double: %f\n", d);
return 0;
}
diff --git a/tests/core/test_floatvars.out b/tests/core/test_floatvars.out
index 57635092..128c04ae 100644
--- a/tests/core/test_floatvars.out
+++ b/tests/core/test_floatvars.out
@@ -1,3 +1,4 @@
*1,10,10.5,1,1.2340,0.00*
0.50, 3.30, 3.30, 3.30
small: 0.0000010000
+double: 1.1234567890123457e+21
diff --git a/tests/core/test_polymorph.in b/tests/core/test_polymorph.in
index 1f24a1aa..af07dc05 100644
--- a/tests/core/test_polymorph.in
+++ b/tests/core/test_polymorph.in
@@ -16,6 +16,8 @@ struct Child : Parent {
struct Other {
int one() { return 11; }
int two() { return 22; }
+ virtual int three() { return 33; }
+ virtual int four() { return 44; }
};
int main() {
@@ -24,10 +26,16 @@ int main() {
printf("*%d,%d,%d,%d*\n", x->getit(), y->getit(), x->implme(), y->implme());
Other *o = new Other;
+
int (Other::*Ls)() = &Other::one;
printf("*%d*\n", (o->*(Ls))());
Ls = &Other::two;
printf("*%d*\n", (o->*(Ls))());
+ Ls = &Other::three;
+ printf("*%d*\n", (o->*(Ls))());
+ Ls = &Other::four;
+ printf("*%d*\n", (o->*(Ls))());
+
return 0;
}
diff --git a/tests/core/test_polymorph.out b/tests/core/test_polymorph.out
index 0d036bf0..5163ea8e 100644
--- a/tests/core/test_polymorph.out
+++ b/tests/core/test_polymorph.out
@@ -1,3 +1,5 @@
*11,74,32,1012*
*11*
-*22* \ No newline at end of file
+*22*
+*33*
+*44*
diff --git a/tests/core/test_set_align.c b/tests/core/test_set_align.c
new file mode 100644
index 00000000..26158ef4
--- /dev/null
+++ b/tests/core/test_set_align.c
@@ -0,0 +1,50 @@
+
+#include <stdio.h>
+#include <emscripten.h>
+
+volatile char data[16];
+
+__attribute__((noinline)) void *get_aligned(int align)
+{
+ char *ptr = (char*)(((int)(data + 7)) & ~7); // Make 8-byte aligned
+ ptr += align; // Now 'align' aligned
+ return (void*)ptr;
+}
+
+int main()
+{
+ emscripten_align4_double *d4 = (emscripten_align4_double*)get_aligned(4);
+ *d4 = 17.0;
+ printf("addr: %d, value: %f\n", ((int)d4) % 8, *d4);
+
+ emscripten_align2_double *d2 = (emscripten_align2_double*)get_aligned(2);
+ *d2 = 18.0;
+ printf("addr: %d, value: %f\n", ((int)d2) % 8, *d2);
+
+ emscripten_align1_double *d1 = (emscripten_align1_double*)get_aligned(1);
+ *d1 = 19.0;
+ printf("addr: %d, value: %f\n", ((int)d1) % 8, *d1);
+
+ emscripten_align2_float *f2 = (emscripten_align2_float*)get_aligned(2);
+ *f2 = 20.0;
+ printf("addr: %d, value: %f\n", ((int)f2) % 4, *f2);
+
+ emscripten_align1_float *f1 = (emscripten_align1_float*)get_aligned(1);
+ *f1 = 21.0;
+ printf("addr: %d, value: %f\n", ((int)f1) % 4, *f1);
+
+ emscripten_align2_int *i2 = (emscripten_align2_int*)get_aligned(2);
+ *i2 = 22;
+ printf("addr: %d, value: %d\n", ((int)i2) % 4, *i2);
+
+ emscripten_align1_int *i1 = (emscripten_align1_int*)get_aligned(1);
+ *i1 = 23;
+ printf("addr: %d, value: %d\n", ((int)i1) % 4, *i1);
+
+ emscripten_align1_short *s1 = (emscripten_align1_short*)get_aligned(1);
+ *s1 = 24;
+ printf("addr: %d, value: %d\n", ((int)s1) % 4, (int)*s1);
+
+ return 0;
+}
+
diff --git a/tests/core/test_set_align.out b/tests/core/test_set_align.out
new file mode 100644
index 00000000..55e377b0
--- /dev/null
+++ b/tests/core/test_set_align.out
@@ -0,0 +1,8 @@
+addr: 4, value: 17.000000
+addr: 2, value: 18.000000
+addr: 1, value: 19.000000
+addr: 2, value: 20.000000
+addr: 1, value: 21.000000
+addr: 2, value: 22
+addr: 1, value: 23
+addr: 1, value: 24
diff --git a/tests/core/test_simd4.in b/tests/core/test_simd4.in
new file mode 100644
index 00000000..b597d8a3
--- /dev/null
+++ b/tests/core/test_simd4.in
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <xmmintrin.h>
+
+static __inline__ __m128 __attribute__((__always_inline__))
+_mm_load_ps(const float *__p)
+{
+ return *(__m128*)__p;
+}
+
+float simdAverage(float *src, int len) {
+ __m128 sumx4 = _mm_setzero_ps();
+ for (int i = 0; i < len; i += 4) {
+ __m128 v = _mm_load_ps(src);
+ sumx4 = _mm_add_ps(sumx4, v);
+ src += 4;
+ }
+ float sumx4_mem[4];
+ float *sumx4_ptr = sumx4_mem;
+ _mm_store_ps(sumx4_ptr, sumx4);
+ return (sumx4_mem[0] + sumx4_mem[1] +
+ sumx4_mem[2] + sumx4_mem[3])/len;
+}
+
+void initArray(float *src, int len) {
+ for (int i = 0; i < len; ++i) {
+ src[i] = 0.1 * i;
+ }
+}
+
+int main() {
+ const int len = 100000;
+ float src[len];
+ float result = 0.0;
+
+ initArray(src, len);
+
+ result = simdAverage(src, len);
+ printf("averagex4 result: %.1f\n", result);
+} \ No newline at end of file
diff --git a/tests/core/test_simd4.out b/tests/core/test_simd4.out
new file mode 100644
index 00000000..99449772
--- /dev/null
+++ b/tests/core/test_simd4.out
@@ -0,0 +1 @@
+averagex4 result: 4999.9 \ No newline at end of file
diff --git a/tests/core/test_sscanf.in b/tests/core/test_sscanf.in
index 55a310c5..470aaf37 100644
--- a/tests/core/test_sscanf.in
+++ b/tests/core/test_sscanf.in
@@ -66,7 +66,8 @@ int main() {
char buf1[100], buf2[100], buf3[100], buf4[100];
memset(buf4, 0, 100);
- int numItems = sscanf("level=4:ref=3", "%255[^:=]=%255[^:]:%255[^=]=%255c",
+
+ int numItems = sscanf("level=4:ref=3", "%255[^:=]=%255[^:]:%255[^=]=%c",
buf1, buf2, buf3, buf4);
printf("%d, %s, %s, %s, %s\n", numItems, buf1, buf2, buf3, buf4);
diff --git a/tests/core/test_sscanf_hex.in b/tests/core/test_sscanf_hex.in
index d8175e82..a05eb890 100644
--- a/tests/core/test_sscanf_hex.in
+++ b/tests/core/test_sscanf_hex.in
@@ -1,7 +1,27 @@
-#include "stdio.h"
+#include <stdio.h>
+#include <string>
+#include <cstdlib>
-int main() {
+int main()
+{
unsigned int a, b;
sscanf("0x12AB 12AB", "%x %x", &a, &b);
printf("%d %d\n", a, b);
+
+ std::string hexstr("0102037F00FF");
+ const char * cstr = hexstr.c_str();
+ int len = hexstr.length() / 2;
+ char * tmp_data = new char[len];
+ for(int i = 0; i < len; i++)
+ {
+ sscanf(cstr, "%2hhx", &tmp_data[i]);
+ cstr += 2 * sizeof(char);
+ }
+
+ for (int j = 0; j < len; j++)
+ printf("%i, ", tmp_data[j]);
+ printf("\n");
+ delete[] tmp_data;
}
+
+
diff --git a/tests/core/test_sscanf_hex.out b/tests/core/test_sscanf_hex.out
index ac855044..6e7f66aa 100644
--- a/tests/core/test_sscanf_hex.out
+++ b/tests/core/test_sscanf_hex.out
@@ -1 +1,2 @@
-4779 4779 \ No newline at end of file
+4779 4779
+1, 2, 3, 127, 0, -1,
diff --git a/tests/core/test_strptime_tm.in b/tests/core/test_strptime_tm.in
index 93cdb1d5..2cccfa55 100644
--- a/tests/core/test_strptime_tm.in
+++ b/tests/core/test_strptime_tm.in
@@ -2,6 +2,15 @@
#include <stdio.h>
#include <string.h>
+void ReadMonth(const char *month)
+{
+ tm value = {0};
+ if(strptime(month, "%b", &value))
+ {
+ printf("%s: %d\n", month, value.tm_mon);
+ }
+}
+
int main() {
struct tm tm;
char *ptr = strptime("17410105012000", "%H%M%S%d%m%Y", &tm);
@@ -24,4 +33,26 @@ int main() {
: "ERR")))))),
tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900, tm.tm_hour, tm.tm_min,
tm.tm_sec);
+
+ printf("\n");
+
+ ReadMonth("jan");
+ ReadMonth("january");
+ ReadMonth("feb");
+ ReadMonth("february");
+ ReadMonth("march");
+ ReadMonth("mar");
+ ReadMonth("april");
+ ReadMonth("may");
+ ReadMonth("may");
+ ReadMonth("june");
+ ReadMonth("jul");
+ ReadMonth("august");
+ ReadMonth("september");
+ ReadMonth("oct");
+ ReadMonth("nov");
+ ReadMonth("november");
+ ReadMonth("december");
+
+ return 0;
}
diff --git a/tests/core/test_strptime_tm.out b/tests/core/test_strptime_tm.out
index 32c321f7..c241cbdd 100644
--- a/tests/core/test_strptime_tm.out
+++ b/tests/core/test_strptime_tm.out
@@ -1 +1,18 @@
-OK: Wed, 1/5/2000 17:41:1 \ No newline at end of file
+OK: Wed, 1/5/2000 17:41:1
+jan: 0
+january: 0
+feb: 1
+february: 1
+march: 2
+mar: 2
+april: 3
+may: 4
+may: 4
+june: 5
+jul: 6
+august: 7
+september: 8
+oct: 9
+nov: 10
+november: 10
+december: 11
diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js
index 6bba4de0..432202ff 100644
--- a/tests/embind/embind.test.js
+++ b/tests/embind/embind.test.js
@@ -442,6 +442,21 @@ module({
var e = cm.emval_test_take_and_return_std_string((new Int8Array([65, 66, 67, 68])).buffer);
assert.equal('ABCD', e);
});
+
+ test("can pass Uint8Array to std::basic_string<unsigned char>", function() {
+ var e = cm.emval_test_take_and_return_std_basic_string_unsigned_char(new Uint8Array([65, 66, 67, 68]));
+ assert.equal('ABCD', e);
+ });
+
+ test("can pass Int8Array to std::basic_string<unsigned char>", function() {
+ var e = cm.emval_test_take_and_return_std_basic_string_unsigned_char(new Int8Array([65, 66, 67, 68]));
+ assert.equal('ABCD', e);
+ });
+
+ test("can pass ArrayBuffer to std::basic_string<unsigned char>", function() {
+ var e = cm.emval_test_take_and_return_std_basic_string_unsigned_char((new Int8Array([65, 66, 67, 68])).buffer);
+ assert.equal('ABCD', e);
+ });
test("non-ascii wstrings", function() {
var expected = String.fromCharCode(10) +
@@ -1533,7 +1548,7 @@ module({
});
});
- BaseFixture.extend("abstract methods", function() {
+ BaseFixture.extend("implementing abstract methods with JS objects", function() {
test("can call abstract methods", function() {
var obj = cm.getAbstractClass();
assert.equal("from concrete", obj.abstractMethod());
@@ -1565,7 +1580,8 @@ module({
};
var impl = cm.AbstractClass.implement(new MyImplementation);
- assert.equal(expected, impl.optionalMethod(expected));
+ // TODO: remove .implement() as a public API. It interacts poorly with Class.extend.
+ //assert.equal(expected, impl.optionalMethod(expected));
assert.equal(expected, cm.callOptionalMethod(impl, expected));
impl.delete();
});
@@ -1573,7 +1589,8 @@ module({
test("if not implemented then optional method runs default", function() {
var impl = cm.AbstractClass.implement({});
assert.equal("optionalfoo", impl.optionalMethod("foo"));
- assert.equal("optionalfoo", cm.callOptionalMethod(impl, "foo"));
+ // TODO: remove .implement() as a public API. It interacts poorly with Class.extend.
+ //assert.equal("optionalfoo", cm.callOptionalMethod(impl, "foo"));
impl.delete();
});
@@ -1623,6 +1640,366 @@ module({
impl.delete();
});
+
+ test("returning a cached new shared pointer from interfaces implemented in JS code does not leak", function() {
+ var derived = cm.embind_test_return_smart_derived_ptr();
+ var impl = cm.AbstractClass.implement({
+ returnsSharedPtr: function() {
+ return derived;
+ }
+ });
+ cm.callReturnsSharedPtrMethod(impl);
+ impl.delete();
+ derived.delete();
+ // Let the memory leak test superfixture check that no leaks occurred.
+ });
+ });
+
+ BaseFixture.extend("constructor prototype class inheritance", function() {
+ var Empty = cm.AbstractClass.extend("Empty", {
+ abstractMethod: function() {
+ }
+ });
+
+ test("can extend, construct, and delete", function() {
+ var instance = new Empty;
+ instance.delete();
+ });
+
+ test("properties set in constructor are externally visible", function() {
+ var HasProperty = cm.AbstractClass.extend("HasProperty", {
+ __construct: function(x) {
+ this.__parent.__construct.call(this);
+ this.property = x;
+ },
+ abstractMethod: function() {
+ }
+ });
+ var instance = new HasProperty(10);
+ assert.equal(10, instance.property);
+ instance.delete();
+ });
+
+ test("pass derived object to c++", function() {
+ var Implementation = cm.AbstractClass.extend("Implementation", {
+ abstractMethod: function() {
+ return "abc";
+ },
+ });
+ var instance = new Implementation;
+ var result = cm.callAbstractMethod(instance);
+ instance.delete();
+ assert.equal("abc", result);
+ });
+
+ test("properties set in constructor are visible in overridden methods", function() {
+ var HasProperty = cm.AbstractClass.extend("HasProperty", {
+ __construct: function(x) {
+ this.__parent.__construct.call(this);
+ this.x = x;
+ },
+ abstractMethod: function() {
+ return this.x;
+ },
+ });
+ var instance = new HasProperty("xyz");
+ var result = cm.callAbstractMethod(instance);
+ instance.delete();
+ assert.equal("xyz", result);
+ });
+
+ test("interface methods are externally visible", function() {
+ var instance = new Empty;
+ var result = instance.concreteMethod();
+ instance.delete();
+ assert.equal("concrete", result);
+ });
+
+ test("optional methods are externally visible", function() {
+ var instance = new Empty;
+ var result = instance.optionalMethod("_123");
+ instance.delete();
+ assert.equal("optional_123", result);
+ });
+
+ test("optional methods: not defined", function() {
+ var instance = new Empty;
+ var result = cm.callOptionalMethod(instance, "_123");
+ instance.delete();
+ assert.equal("optional_123", result);
+ });
+
+ // Calling C++ implementations of optional functions can be
+ // made to work, but requires an interface change on the C++
+ // side, using a technique similar to the one described at
+ // https://wiki.python.org/moin/boost.python/OverridableVirtualFunctions
+ //
+ // The issue is that, in a standard binding, calling
+ // parent.prototype.optionalMethod invokes the wrapper
+ // function, which checks that the JS object implements
+ // 'optionalMethod', which it does. Thus, C++ calls back into
+ // JS, resulting in an infinite loop.
+ //
+ // The solution, for optional methods, is to bind a special
+ // concrete implementation that specifically calls the base
+ // class's implementation. See the binding of
+ // AbstractClass::optionalMethod in embind_test.cpp.
+
+ test("can call parent implementation from within derived implementation", function() {
+ var parent = cm.AbstractClass;
+ var ExtendsOptionalMethod = parent.extend("ExtendsOptionalMethod", {
+ abstractMethod: function() {
+ },
+ optionalMethod: function(s) {
+ return "optionaljs_" + parent.prototype.optionalMethod.call(this, s);
+ },
+ });
+ var instance = new ExtendsOptionalMethod;
+ var result = cm.callOptionalMethod(instance, "_123");
+ instance.delete();
+ assert.equal("optionaljs_optional_123", result);
+ });
+
+ // TODO: deriving from classes with constructors?
+
+ test("instanceof", function() {
+ var instance = new Empty;
+ assert.instanceof(instance, Empty);
+ assert.instanceof(instance, cm.AbstractClass);
+ instance.delete();
+ });
+
+ test("returning null shared pointer from interfaces implemented in JS code does not leak", function() {
+ var C = cm.AbstractClass.extend("C", {
+ abstractMethod: function() {
+ },
+ returnsSharedPtr: function() {
+ return null;
+ }
+ });
+ var impl = new C;
+ 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 C = cm.AbstractClass.extend("C", {
+ abstractMethod: function() {
+ },
+ returnsSharedPtr: function() {
+ return cm.embind_test_return_smart_derived_ptr().deleteLater();
+ }
+ });
+ var impl = new C;
+ cm.callReturnsSharedPtrMethod(impl);
+ impl.delete();
+ // Let the memory leak test superfixture check that no leaks occurred.
+ });
+
+ test("void methods work", function() {
+ var saved = {};
+ var C = cm.AbstractClass.extend("C", {
+ abstractMethod: function() {
+ },
+ differentArguments: function(i, d, f, q, s) {
+ saved.i = i;
+ saved.d = d;
+ saved.f = f;
+ saved.q = q;
+ saved.s = s;
+ }
+ });
+ var impl = new C;
+
+ cm.callDifferentArguments(impl, 1, 2, 3, 4, "foo");
+
+ assert.deepEqual(saved, {
+ i: 1,
+ d: 2,
+ f: 3,
+ q: 4,
+ s: "foo",
+ });
+
+ impl.delete();
+ });
+
+ test("returning a cached new shared pointer from interfaces implemented in JS code does not leak", function() {
+ var derived = cm.embind_test_return_smart_derived_ptr();
+ var C = cm.AbstractClass.extend("C", {
+ abstractMethod: function() {
+ },
+ returnsSharedPtr: function() {
+ return derived;
+ }
+ });
+ var impl = new C;
+ cm.callReturnsSharedPtrMethod(impl);
+ impl.delete();
+ derived.delete();
+ // Let the memory leak test superfixture check that no leaks occurred.
+ });
+
+ test("calling pure virtual function gives good error message", function() {
+ var C = cm.AbstractClass.extend("C", {});
+ var error = assert.throws(cm.PureVirtualError, function() {
+ new C;
+ });
+ assert.equal('Pure virtual function abstractMethod must be implemented in JavaScript', error.message);
+ });
+
+ test("can extend from C++ class with constructor arguments", function() {
+ var parent = cm.AbstractClassWithConstructor;
+ var C = parent.extend("C", {
+ __construct: function(x) {
+ this.__parent.__construct.call(this, x);
+ },
+ abstractMethod: function() {
+ return this.concreteMethod();
+ }
+ });
+
+ var impl = new C("hi");
+ var rv = cm.callAbstractMethod2(impl);
+ impl.delete();
+
+ assert.equal("hi", rv);
+ });
+
+ test("__destruct is called when object is destroyed", function() {
+ var parent = cm.HeldAbstractClass;
+ var calls = [];
+ var C = parent.extend("C", {
+ method: function() {
+ },
+ __destruct: function() {
+ calls.push("__destruct");
+ this.__parent.__destruct.call(this);
+ }
+ });
+ var impl = new C;
+ var copy = impl.clone();
+ impl.delete();
+ assert.deepEqual([], calls);
+ copy.delete();
+ assert.deepEqual(["__destruct"], calls);
+ });
+
+ test("if JavaScript implementation of interface is returned, don't wrap in new handle", function() {
+ var parent = cm.HeldAbstractClass;
+ var C = parent.extend("C", {
+ method: function() {
+ }
+ });
+ var impl = new C;
+ var rv = cm.passHeldAbstractClass(impl);
+ impl.delete();
+ assert.equal(impl, rv);
+ rv.delete();
+ });
+
+ test("can instantiate two wrappers with constructors", function() {
+ var parent = cm.HeldAbstractClass;
+ var C = parent.extend("C", {
+ __construct: function() {
+ this.__parent.__construct.call(this);
+ },
+ method: function() {
+ }
+ });
+ var a = new C;
+ var b = new C;
+ a.delete();
+ b.delete();
+ });
+
+ test("incorrectly calling parent is an error", function() {
+ var parent = cm.HeldAbstractClass;
+ var C = parent.extend("C", {
+ __construct: function() {
+ this.__parent.__construct();
+ },
+ method: function() {
+ }
+ });
+ assert.throws(cm.BindingError, function() {
+ new C;
+ });
+ });
+
+ test("deleteLater() works for JavaScript implementations", function() {
+ var parent = cm.HeldAbstractClass;
+ var C = parent.extend("C", {
+ method: function() {
+ }
+ });
+ var impl = new C;
+ var rv = cm.passHeldAbstractClass(impl);
+ impl.deleteLater();
+ rv.deleteLater();
+ cm.flushPendingDeletes();
+ });
+
+ test("deleteLater() combined with delete() works for JavaScript implementations", function() {
+ var parent = cm.HeldAbstractClass;
+ var C = parent.extend("C", {
+ method: function() {
+ }
+ });
+ var impl = new C;
+ var rv = cm.passHeldAbstractClass(impl);
+ impl.deleteLater();
+ rv.delete();
+ cm.flushPendingDeletes();
+ });
+
+ test("method arguments with pointer ownership semantics are cleaned up after call", function() {
+ var parent = cm.AbstractClass;
+ var C = parent.extend("C", {
+ abstractMethod: function() {
+ },
+ });
+ var impl = new C;
+ cm.passShared(impl);
+ impl.delete();
+ });
+
+ test("method arguments with pointer ownership semantics can be cloned", function() {
+ var parent = cm.AbstractClass;
+ var owned;
+ var C = parent.extend("C", {
+ abstractMethod: function() {
+ },
+ passShared: function(p) {
+ owned = p.clone();
+ }
+ });
+ var impl = new C;
+ cm.passShared(impl);
+ impl.delete();
+
+ assert.equal("Derived", owned.getClassName());
+ owned.delete();
+ });
+
+ test("emscripten::val method arguments don't leak", function() {
+ var parent = cm.AbstractClass;
+ var got;
+ var C = parent.extend("C", {
+ abstractMethod: function() {
+ },
+ passVal: function(g) {
+ got = g;
+ }
+ });
+ var impl = new C;
+ var v = {};
+ cm.passVal(impl, v);
+ impl.delete();
+
+ assert.equal(v, got);
+ });
});
BaseFixture.extend("registration order", function() {
@@ -1930,19 +2307,6 @@ module({
});
});
- test("returning a cached new shared pointer from interfaces implemented in JS code does not leak", function() {
- var derived = cm.embind_test_return_smart_derived_ptr();
- var impl = cm.AbstractClass.implement({
- returnsSharedPtr: function() {
- return derived;
- }
- });
- cm.callReturnsSharedPtrMethod(impl);
- impl.delete();
- derived.delete();
- // Let the memory leak test superfixture check that no leaks occurred.
- });
-
BaseFixture.extend("val::as", function() {
test("built-ins", function() {
assert.equal(true, cm.val_as_bool(true));
@@ -2015,6 +2379,50 @@ module({
assert.equal(65538, instance.c);
});
});
+
+ BaseFixture.extend("intrusive pointers", function() {
+ test("can pass intrusive pointers", function() {
+ var ic = new cm.IntrusiveClass;
+ var d = cm.passThroughIntrusiveClass(ic);
+ assert.true(ic.isAliasOf(d));
+ ic.delete();
+ d.delete();
+ });
+
+ test("can hold intrusive pointers", function() {
+ var ic = new cm.IntrusiveClass;
+ var holder = new cm.IntrusiveClassHolder;
+ holder.set(ic);
+ ic.delete();
+ var d = holder.get();
+ d.delete();
+ holder.delete();
+ });
+
+ test("can extend from intrusive pointer class and still preserve reference in JavaScript", function() {
+ var C = cm.IntrusiveClass.extend("C", {
+ });
+ var instance = new C;
+ var holder = new cm.IntrusiveClassHolder;
+ holder.set(instance);
+ instance.delete();
+
+ var back = holder.get();
+ assert.equal(back, instance);
+ holder.delete();
+ back.delete();
+ });
+ });
+
+ BaseFixture.extend("typeof", function() {
+ test("typeof", function() {
+ assert.equal("object", cm.getTypeOfVal(null));
+ assert.equal("object", cm.getTypeOfVal({}));
+ assert.equal("function", cm.getTypeOfVal(function(){}));
+ assert.equal("number", cm.getTypeOfVal(1));
+ assert.equal("string", cm.getTypeOfVal("hi"));
+ });
+ });
});
/* global run_all_tests */
diff --git a/tests/embind/embind_test.cpp b/tests/embind/embind_test.cpp
index 1b835751..30267994 100644
--- a/tests/embind/embind_test.cpp
+++ b/tests/embind/embind_test.cpp
@@ -109,6 +109,10 @@ std::string emval_test_take_and_return_std_string_const_ref(const std::string& s
return str;
}
+std::basic_string<unsigned char> emval_test_take_and_return_std_basic_string_unsigned_char(std::basic_string<unsigned char> str) {
+ return str;
+}
+
std::wstring take_and_return_std_wstring(std::wstring str) {
return str;
}
@@ -1086,6 +1090,16 @@ public:
virtual std::shared_ptr<Derived> returnsSharedPtr() = 0;
virtual void differentArguments(int i, double d, unsigned char f, double q, std::string) = 0;
+
+ std::string concreteMethod() const {
+ return "concrete";
+ }
+
+ virtual void passShared(const std::shared_ptr<Derived>&) {
+ }
+
+ virtual void passVal(const val& v) {
+ }
};
EMSCRIPTEN_SYMBOL(optionalMethod);
@@ -1099,9 +1113,10 @@ public:
}
std::string optionalMethod(std::string s) const {
- return optional_call<std::string>(optionalMethod_symbol, [&] {
- return AbstractClass::optionalMethod(s);
- }, s);
+ return call<std::string>("optionalMethod", s);
+ //return optional_call<std::string>(optionalMethod_symbol, [&] {
+ // return AbstractClass::optionalMethod(s);
+ //}, s);
}
std::shared_ptr<Derived> returnsSharedPtr() {
@@ -1111,6 +1126,14 @@ public:
void differentArguments(int i, double d, unsigned char f, double q, std::string s) {
return call<void>("differentArguments", i, d, f, q, s);
}
+
+ virtual void passShared(const std::shared_ptr<Derived>& p) override {
+ return call<void>("passShared", p);
+ }
+
+ virtual void passVal(const val& v) override {
+ return call<void>("passVal", v);
+ }
};
class ConcreteClass : public AbstractClass {
@@ -1118,7 +1141,6 @@ class ConcreteClass : public AbstractClass {
return "from concrete";
}
-
void differentArguments(int i, double d, unsigned char f, double q, std::string s) {
}
@@ -1148,12 +1170,74 @@ void callDifferentArguments(AbstractClass& ac, int i, double d, unsigned char f,
return ac.differentArguments(i, d, f, q, s);
}
+struct AbstractClassWithConstructor {
+ explicit AbstractClassWithConstructor(std::string s)
+ : s(s)
+ {}
+
+ virtual std::string abstractMethod() = 0;
+ std::string concreteMethod() {
+ return s;
+ }
+
+ std::string s;
+};
+
+struct AbstractClassWithConstructorWrapper : public wrapper<AbstractClassWithConstructor> {
+ EMSCRIPTEN_WRAPPER(AbstractClassWithConstructorWrapper);
+
+ virtual std::string abstractMethod() override {
+ return call<std::string>("abstractMethod");
+ }
+};
+
+std::string callAbstractMethod2(AbstractClassWithConstructor& ac) {
+ return ac.abstractMethod();
+}
+
+struct HeldAbstractClass : public PolyBase, public PolySecondBase {
+ virtual void method() = 0;
+};
+struct HeldAbstractClassWrapper : wrapper<HeldAbstractClass> {
+ EMSCRIPTEN_WRAPPER(HeldAbstractClassWrapper);
+
+ virtual void method() override {
+ return call<void>("method");
+ }
+};
+
+std::shared_ptr<PolySecondBase> passHeldAbstractClass(std::shared_ptr<HeldAbstractClass> p) {
+ return p;
+}
+
+void passShared(AbstractClass& ac) {
+ auto p = std::make_shared<Derived>();
+ ac.passShared(p);
+}
+
+void passVal(AbstractClass& ac, val v) {
+ return ac.passVal(v);
+}
+
EMSCRIPTEN_BINDINGS(interface_tests) {
class_<AbstractClass>("AbstractClass")
.smart_ptr<std::shared_ptr<AbstractClass>>("shared_ptr<AbstractClass>")
.allow_subclass<AbstractClassWrapper>("AbstractClassWrapper")
- .function("abstractMethod", &AbstractClass::abstractMethod)
- .function("optionalMethod", &AbstractClass::optionalMethod)
+ .function("abstractMethod", &AbstractClass::abstractMethod, pure_virtual())
+ // The select_overload is necessary because, otherwise, the C++ compiler
+ // cannot deduce the signature of the lambda function.
+ .function("optionalMethod", optional_override(
+ [](AbstractClass& this_, std::string s) {
+ return this_.AbstractClass::optionalMethod(s);
+ }
+ ))
+ .function("concreteMethod", &AbstractClass::concreteMethod)
+ .function("passShared", select_overload<void(AbstractClass&, const std::shared_ptr<Derived>&)>([](AbstractClass& self, const std::shared_ptr<Derived>& derived) {
+ self.AbstractClass::passShared(derived);
+ }))
+ .function("passVal", select_overload<void(AbstractClass&, const val&)>([](AbstractClass& self, const val& v) {
+ self.AbstractClass::passVal(v);
+ }))
;
function("getAbstractClass", &getAbstractClass);
@@ -1161,6 +1245,22 @@ EMSCRIPTEN_BINDINGS(interface_tests) {
function("callOptionalMethod", &callOptionalMethod);
function("callReturnsSharedPtrMethod", &callReturnsSharedPtrMethod);
function("callDifferentArguments", &callDifferentArguments);
+ function("passShared", &passShared);
+ function("passVal", &passVal);
+
+ class_<AbstractClassWithConstructor>("AbstractClassWithConstructor")
+ .allow_subclass<AbstractClassWithConstructorWrapper>("AbstractClassWithConstructorWrapper", constructor<std::string>())
+ .function("abstractMethod", &AbstractClassWithConstructor::abstractMethod, pure_virtual())
+ .function("concreteMethod", &AbstractClassWithConstructor::concreteMethod)
+ ;
+ function("callAbstractMethod2", &callAbstractMethod2);
+
+ class_<HeldAbstractClass, base<PolySecondBase>>("HeldAbstractClass")
+ .smart_ptr<std::shared_ptr<HeldAbstractClass>>("shared_ptr<HeldAbstractClass>")
+ .allow_subclass<HeldAbstractClassWrapper, std::shared_ptr<HeldAbstractClassWrapper>>("HeldAbstractClassWrapper")
+ .function("method", &HeldAbstractClass::method, pure_virtual())
+ ;
+ function("passHeldAbstractClass", &passHeldAbstractClass);
}
template<typename T, size_t sizeOfArray>
@@ -1446,6 +1546,7 @@ EMSCRIPTEN_BINDINGS(tests) {
//function("emval_test_take_and_return_const_char_star", &emval_test_take_and_return_const_char_star);
function("emval_test_take_and_return_std_string", &emval_test_take_and_return_std_string);
function("emval_test_take_and_return_std_string_const_ref", &emval_test_take_and_return_std_string_const_ref);
+ function("emval_test_take_and_return_std_basic_string_unsigned_char", &emval_test_take_and_return_std_basic_string_unsigned_char);
function("take_and_return_std_wstring", &take_and_return_std_wstring);
//function("emval_test_take_and_return_CustomStruct", &emval_test_take_and_return_CustomStruct);
@@ -2363,3 +2464,180 @@ EMSCRIPTEN_BINDINGS(val_new_) {
function("construct_with_memory_view", &construct_with_memory_view);
function("construct_with_ints_and_float", &construct_with_ints_and_float);
}
+
+template <typename T>
+class intrusive_ptr {
+public:
+ typedef T element_type;
+
+ intrusive_ptr(std::nullptr_t = nullptr)
+ : px(nullptr)
+ {}
+
+ template <typename U>
+ explicit intrusive_ptr(U* px)
+ : px(px)
+ {
+ addRef(px);
+ }
+
+ intrusive_ptr(const intrusive_ptr& that)
+ : px(that.px)
+ {
+ addRef(px);
+ }
+
+ template<typename U>
+ intrusive_ptr(const intrusive_ptr<U>& that)
+ : px(that.get())
+ {
+ addRef(px);
+ }
+
+ intrusive_ptr& operator=(const intrusive_ptr& that) {
+ reset(that.get());
+ return *this;
+ }
+
+ intrusive_ptr& operator=(intrusive_ptr&& that) {
+ release(px);
+ px = that.px;
+ that.px = 0;
+ return *this;
+ }
+
+ template<typename U>
+ intrusive_ptr& operator=(const intrusive_ptr<U>& that) {
+ reset(that.get());
+ return *this;
+ }
+
+ template<typename U>
+ intrusive_ptr& operator=(intrusive_ptr<U>&& that) {
+ release(px);
+ px = that.px;
+ that.px = 0;
+ return *this;
+ }
+
+ ~intrusive_ptr() {
+ release(px);
+ }
+
+ void reset(T* nx = nullptr) {
+ addRef(nx);
+ release(px);
+ px = nx;
+ }
+
+ T* get() const {
+ return px;
+ }
+
+ T& operator*() const {
+ return *px;
+ }
+
+ T* operator->() const {
+ return px;
+ }
+
+ explicit operator bool() const {
+ return px != nullptr;
+ }
+
+ void swap(intrusive_ptr& rhs) {
+ std::swap(px, rhs.px);
+ }
+
+private:
+ void addRef(T* px) {
+ if (px) {
+ ++px->referenceCount;
+ }
+ }
+
+ void release(T* px) {
+ if (--px->referenceCount == 0) {
+ delete px;
+ }
+ }
+
+ T* px;
+
+ template<typename U>
+ friend class intrusive_ptr;
+};
+
+namespace emscripten {
+ template<typename T>
+ struct smart_ptr_trait<intrusive_ptr<T>> {
+ typedef intrusive_ptr<T> pointer_type;
+ typedef T element_type;
+
+ static sharing_policy get_sharing_policy() {
+ return sharing_policy::INTRUSIVE;
+ }
+
+ static T* get(const intrusive_ptr<T>& p) {
+ return p.get();
+ }
+
+ static intrusive_ptr<T> share(const intrusive_ptr<T>& r, T* ptr) {
+ return intrusive_ptr<T>(ptr);
+ }
+
+ static pointer_type* construct_null() {
+ return new pointer_type;
+ }
+ };
+}
+
+template<typename T>
+intrusive_ptr<T> make_intrusive_ptr() {
+ return intrusive_ptr<T>(new T);
+}
+
+struct IntrusiveClass {
+ virtual ~IntrusiveClass() {}
+ long referenceCount = 0;
+};
+
+struct IntrusiveClassWrapper : public wrapper<IntrusiveClass> {
+ EMSCRIPTEN_WRAPPER(IntrusiveClassWrapper);
+};
+
+template<typename T>
+struct Holder {
+ void set(const T& v) {
+ value = v;
+ }
+ const T& get() const {
+ return value;
+ }
+ T value;
+};
+
+EMSCRIPTEN_BINDINGS(intrusive_pointers) {
+ class_<IntrusiveClass>("IntrusiveClass")
+ .smart_ptr_constructor("intrusive_ptr<IntrusiveClass>", &make_intrusive_ptr<IntrusiveClass>)
+ .allow_subclass<IntrusiveClassWrapper, intrusive_ptr<IntrusiveClassWrapper>>("IntrusiveClassWrapper")
+ ;
+
+ typedef Holder<intrusive_ptr<IntrusiveClass>> IntrusiveClassHolder;
+ class_<IntrusiveClassHolder>("IntrusiveClassHolder")
+ .constructor<>()
+ .function("set", &IntrusiveClassHolder::set)
+ .function("get", &IntrusiveClassHolder::get)
+ ;
+
+ function("passThroughIntrusiveClass", &passThrough<intrusive_ptr<IntrusiveClass>>);
+}
+
+std::string getTypeOfVal(const val& v) {
+ return v.typeof().as<std::string>();
+}
+
+EMSCRIPTEN_BINDINGS(typeof) {
+ function("getTypeOfVal", &getTypeOfVal);
+}
diff --git a/tests/embind/imvu_test_adapter.js b/tests/embind/imvu_test_adapter.js
index 421e86c8..93eeab37 100644
--- a/tests/embind/imvu_test_adapter.js
+++ b/tests/embind/imvu_test_adapter.js
@@ -586,12 +586,6 @@ function module(ignore, func) {
throw new AssertionError("Don't call setInterval in tests. Use fakes.");
};
- if (typeof process !== 'undefined') {
- process.nextTick = function() {
- throw new AssertionError("Don't call process.nextTick in tests. Use fakes.");
- };
- }
-
Math.random = function() {
throw new AssertionError("Don't call Math.random in tests. Use fakes.");
};
diff --git a/tests/emscripten_fs_api_browser.cpp b/tests/emscripten_fs_api_browser.cpp
index 0355287a..1410ba3c 100644
--- a/tests/emscripten_fs_api_browser.cpp
+++ b/tests/emscripten_fs_api_browser.cpp
@@ -107,11 +107,14 @@ int main() {
onLoaded,
onError);
+ char name[40];
+ strcpy(name, "/tmp/screen_shot.png"); // test for issue #2349, name being free'd
emscripten_async_wget(
"http://localhost:8888/screenshot.png",
- "/tmp/screen_shot.png",
+ name,
onLoaded,
onError);
+ memset(name, 0, 30);
emscripten_set_main_loop(wait_wgets, 0, 0);
diff --git a/tests/fs/test_trackingdelegate.c b/tests/fs/test_trackingdelegate.c
new file mode 100644
index 00000000..6cdece72
--- /dev/null
+++ b/tests/fs/test_trackingdelegate.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <emscripten.h>
+
+int main() {
+
+ EM_ASM(
+ FS.trackingDelegate['willMovePath'] = function(oldpath, newpath) {
+ Module.print('About to move "' + oldpath + '" to "' + newpath + '"');
+ };
+ FS.trackingDelegate['onMovePath'] = function(oldpath, newpath) {
+ Module.print('Moved "' + oldpath + '" to "' + newpath + '"');
+ };
+ FS.trackingDelegate['willDeletePath'] = function(path) {
+ Module.print('About to delete "' + path + '"');
+ };
+ FS.trackingDelegate['onDeletePath'] = function(path) {
+ Module.print('Deleted "' + path + '"');
+ };
+ FS.trackingDelegate['onOpenFile'] = function(path, flags) {
+ Module.print('Opened "' + path + '" with flags ' + flags);
+ };
+ FS.trackingDelegate['onWriteToFile'] = function(path) {
+ Module.print('Wrote to file "' + path + '"');
+ };
+ );
+
+ FILE *file;
+ file = fopen("/file.txt", "w");
+ fputs("hello!", file);
+ fclose(file);
+ rename("/file.txt", "/renamed.txt");
+ file = fopen("/renamed.txt", "r");
+ char str[256] = {};
+ fgets(str, 255, file);
+ printf("File read returned '%s'\n", str);
+ fclose(file);
+ remove("/renamed.txt");
+}
diff --git a/tests/fs/test_trackingdelegate.out b/tests/fs/test_trackingdelegate.out
new file mode 100644
index 00000000..b3c941c2
--- /dev/null
+++ b/tests/fs/test_trackingdelegate.out
@@ -0,0 +1,9 @@
+Opened "/file.txt" with flags 2
+Wrote to file "/file.txt"
+About to move "/file.txt" to "/renamed.txt"
+Moved "/file.txt" to "/renamed.txt"
+Opened "/renamed.txt" with flags 1
+File read returned 'hello!'
+Wrote to file "/dev/tty"
+About to delete "/renamed.txt"
+Deleted "/renamed.txt"
diff --git a/tests/fs/test_writeFile.cc b/tests/fs/test_writeFile.cc
new file mode 100644
index 00000000..31466b8e
--- /dev/null
+++ b/tests/fs/test_writeFile.cc
@@ -0,0 +1,43 @@
+// https://github.com/kripken/emscripten/issues/2334
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#include <emscripten/emscripten.h>
+
+int main()
+{
+ EM_ASM(
+ FS.writeFile("testfile", "a=1\nb=2\nc=3");
+ );
+
+ std::ifstream file("testfile");
+
+ while(!file.eof() && !file.fail())
+ {
+ std::string line;
+ getline(file, line);
+ std::string name;
+
+ std::cout << "read " << line << std::endl;
+
+ size_t equalsPos = 1;
+
+ size_t notSpace = line.find_first_not_of(" \t", equalsPos);
+
+ if(notSpace != std::string::npos && notSpace != equalsPos)
+ {
+ line.erase(std::remove_if(line.begin(), line.begin() + notSpace, isspace), line.end());
+
+ equalsPos = line.find('=');
+ }
+
+ if(equalsPos == std::string::npos)
+ continue;
+
+ name = line.substr(0, equalsPos);
+ }
+
+ return 0;
+}
diff --git a/tests/fs/test_writeFile.out b/tests/fs/test_writeFile.out
new file mode 100644
index 00000000..16e520be
--- /dev/null
+++ b/tests/fs/test_writeFile.out
@@ -0,0 +1,3 @@
+read a=1
+read b=2
+read c=3
diff --git a/tests/fuzz/19.c b/tests/fuzz/19.c
new file mode 100644
index 00000000..d94318c5
--- /dev/null
+++ b/tests/fuzz/19.c
@@ -0,0 +1,1408 @@
+/*
+ * This is a RANDOMLY GENERATED PROGRAM.
+ *
+ * Generator: csmith 2.2.0
+ * Git version: bf42ffd
+ * Options: --no-volatiles --no-packed-struct --no-math64
+ * Seed: 2524651702
+ */
+
+#include "csmith.h"
+
+
+static long __undefined;
+
+/* --- Struct/Union Declarations --- */
+/* --- GLOBAL VARIABLES --- */
+static uint32_t g_2[5][1] = {{0xF1124F01L},{0x1F2C29A3L},{0xF1124F01L},{0x1F2C29A3L},{0xF1124F01L}};
+static int32_t g_3 = 0x3FA75C19L;
+static uint32_t g_14[6] = {0xD1A4E665L,0xD1A4E665L,0xD1A4E665L,0xD1A4E665L,0xD1A4E665L,0xD1A4E665L};
+static uint32_t g_15 = 18446744073709551615UL;
+static int32_t g_34 = 1L;
+static int8_t g_36 = 0x6DL;
+static uint8_t g_40[7] = {0xEAL,0xEAL,0xEAL,0xEAL,0xEAL,0xEAL,0xEAL};
+static uint8_t g_44 = 0UL;
+static uint8_t *g_43 = &g_44;
+static int32_t g_46 = 0x461302D9L;
+static int32_t g_51[2][8][3] = {{{0x0D357E8FL,0x604C38DBL,0x0D357E8FL},{0x0D357E8FL,0x349DDA4AL,0x1ADF561FL},{0x0D357E8FL,0x2D584125L,(-4L)},{0x0D357E8FL,0x604C38DBL,0x0D357E8FL},{0x0D357E8FL,0x349DDA4AL,0x1ADF561FL},{0x0D357E8FL,0x2D584125L,(-4L)},{0x0D357E8FL,0x604C38DBL,0x0D357E8FL},{0x0D357E8FL,0x349DDA4AL,0x1ADF561FL}},{{0x0D357E8FL,0x2D584125L,(-4L)},{0x0D357E8FL,0x1ADF561FL,(-10L)},{(-10L),0x0D357E8FL,0xCF8610F1L},{(-10L),(-4L),(-9L)},{(-10L),0x1ADF561FL,(-10L)},{(-10L),0x0D357E8FL,0xCF8610F1L},{(-10L),(-4L),(-9L)},{(-10L),0x1ADF561FL,(-10L)}}};
+static uint32_t g_52 = 0x171C63CCL;
+static uint32_t g_56 = 0xFBFBE831L;
+static uint32_t *g_55 = &g_56;
+static const int8_t * const g_132 = &g_36;
+static const int8_t * const *g_131 = &g_132;
+static int32_t g_140 = 0L;
+static int32_t *g_143 = &g_140;
+static uint8_t **g_175 = &g_43;
+static uint8_t **g_176 = &g_43;
+static uint8_t **g_177 = (void*)0;
+static int8_t *g_243[6][2][9] = {{{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36}},{{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36}},{{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36}},{{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36}},{{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36}},{{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36}}};
+static int8_t **g_242 = &g_243[5][1][5];
+static int8_t **g_245 = &g_243[5][1][5];
+static uint16_t g_251 = 0x6187L;
+static int8_t g_255 = 0xFEL;
+static int16_t g_290 = 0xF4DEL;
+static int16_t *g_289 = &g_290;
+static uint32_t g_294[5] = {0xFDB146E2L,0xFDB146E2L,0xFDB146E2L,0xFDB146E2L,0xFDB146E2L};
+static int32_t g_297[2] = {1L,1L};
+static int32_t *g_312[2][1][6] = {{{(void*)0,(void*)0,&g_51[0][3][1],(void*)0,(void*)0,&g_51[0][3][1]}},{{(void*)0,(void*)0,&g_51[0][3][1],(void*)0,(void*)0,&g_51[0][3][1]}}};
+static uint8_t g_320 = 0xD4L;
+static int16_t g_347 = 0x586CL;
+static int16_t g_419 = 0xDAAFL;
+static uint32_t g_477 = 0x661A1A9FL;
+static uint32_t g_705[6] = {1UL,1UL,1UL,1UL,1UL,1UL};
+static uint32_t ** const g_736 = &g_55;
+static uint32_t ** const *g_735 = &g_736;
+static uint8_t ****g_897 = (void*)0;
+static uint8_t ***g_905 = &g_175;
+static uint8_t ****g_904[3][6] = {{&g_905,&g_905,&g_905,&g_905,&g_905,&g_905},{&g_905,&g_905,&g_905,&g_905,&g_905,&g_905},{&g_905,&g_905,&g_905,&g_905,&g_905,&g_905}};
+static int32_t **g_961 = &g_312[1][0][4];
+static int32_t ***g_960 = &g_961;
+static uint16_t g_969 = 5UL;
+static int8_t ***g_1019[7][1][1] = {{{&g_242}},{{&g_242}},{{&g_242}},{{&g_242}},{{&g_242}},{{&g_242}},{{&g_242}}};
+static int8_t ****g_1018 = &g_1019[3][0][0];
+static int32_t g_1055 = (-8L);
+static uint32_t g_1099 = 0xAD3B6902L;
+static int32_t g_1132 = (-9L);
+static int16_t * const *g_1185 = &g_289;
+static int16_t * const * const *g_1184 = &g_1185;
+static int16_t g_1189 = 0L;
+static uint32_t **g_1238 = &g_55;
+static uint32_t ***g_1237[8][4][4] = {{{&g_1238,(void*)0,&g_1238,(void*)0},{&g_1238,(void*)0,&g_1238,&g_1238},{(void*)0,&g_1238,&g_1238,(void*)0},{(void*)0,&g_1238,(void*)0,&g_1238}},{{&g_1238,(void*)0,(void*)0,&g_1238},{&g_1238,&g_1238,&g_1238,(void*)0},{&g_1238,&g_1238,&g_1238,(void*)0},{&g_1238,(void*)0,&g_1238,&g_1238}},{{&g_1238,&g_1238,&g_1238,(void*)0},{&g_1238,&g_1238,&g_1238,&g_1238},{&g_1238,(void*)0,(void*)0,&g_1238},{(void*)0,&g_1238,(void*)0,(void*)0}},{{&g_1238,(void*)0,&g_1238,(void*)0},{&g_1238,&g_1238,(void*)0,(void*)0},{(void*)0,(void*)0,&g_1238,&g_1238},{&g_1238,&g_1238,&g_1238,&g_1238}},{{&g_1238,&g_1238,&g_1238,&g_1238},{&g_1238,&g_1238,&g_1238,&g_1238},{&g_1238,&g_1238,&g_1238,&g_1238},{&g_1238,(void*)0,(void*)0,(void*)0}},{{&g_1238,&g_1238,&g_1238,(void*)0},{&g_1238,(void*)0,&g_1238,(void*)0},{(void*)0,&g_1238,(void*)0,&g_1238},{&g_1238,(void*)0,(void*)0,&g_1238}},{{&g_1238,&g_1238,&g_1238,(void*)0},{&g_1238,&g_1238,&g_1238,&g_1238},{&g_1238,(void*)0,&g_1238,(void*)0},{&g_1238,&g_1238,&g_1238,(void*)0}},{{&g_1238,&g_1238,&g_1238,&g_1238},{(void*)0,(void*)0,&g_1238,&g_1238},{(void*)0,&g_1238,&g_1238,(void*)0},{&g_1238,&g_1238,&g_1238,&g_1238}}};
+static uint32_t ***g_1241 = (void*)0;
+static uint32_t g_1254[8][1][8] = {{{0x441F7909L,0x441F7909L,0UL,0x5B976413L,18446744073709551610UL,0UL,18446744073709551610UL,0x5B976413L}},{{0x0ECD52E7L,0x5B976413L,0x0ECD52E7L,0xD72EFABCL,0x5B976413L,0x6701CBD7L,0x6701CBD7L,0x5B976413L}},{{0x5B976413L,0x6701CBD7L,0x6701CBD7L,0x5B976413L,0xD72EFABCL,0x0ECD52E7L,0x5B976413L,0x0ECD52E7L}},{{0x5B976413L,18446744073709551610UL,0UL,18446744073709551610UL,0x5B976413L,0UL,0x441F7909L,0x441F7909L}},{{0x0ECD52E7L,18446744073709551610UL,0xD72EFABCL,0xD72EFABCL,18446744073709551610UL,0x0ECD52E7L,0x6701CBD7L,18446744073709551610UL}},{{0x441F7909L,0x6701CBD7L,0xD72EFABCL,0x441F7909L,0xD72EFABCL,0x6701CBD7L,0x441F7909L,0x0ECD52E7L}},{{18446744073709551610UL,0x5B976413L,0UL,0x441F7909L,0x441F7909L,0UL,0x5B976413L,18446744073709551610UL}},{{0x0ECD52E7L,0x441F7909L,0x6701CBD7L,0xD72EFABCL,0x441F7909L,0xD72EFABCL,0x6701CBD7L,0x441F7909L}}};
+static int16_t g_1285 = 0L;
+static uint8_t * const **g_1295 = (void*)0;
+static uint8_t g_1298 = 0xB8L;
+static int16_t g_1333 = 0x34D4L;
+static uint32_t g_1334 = 0x1191E655L;
+static int32_t g_1509 = 1L;
+static uint8_t ***g_1548 = &g_176;
+static uint8_t ***g_1549 = (void*)0;
+static uint8_t ***g_1550 = (void*)0;
+static uint8_t ***g_1551[3][5] = {{&g_176,&g_176,&g_176,&g_176,&g_176},{&g_176,&g_176,&g_176,&g_176,&g_176},{&g_176,&g_176,&g_176,&g_176,&g_176}};
+static uint8_t ***g_1552[10][9] = {{&g_175,&g_177,&g_175,(void*)0,&g_175,&g_175,(void*)0,&g_175,&g_177},{(void*)0,&g_175,&g_175,(void*)0,&g_175,&g_177,&g_176,&g_175,&g_175},{&g_175,&g_175,&g_177,(void*)0,&g_177,&g_175,&g_175,&g_177,&g_175},{&g_176,&g_175,&g_176,(void*)0,&g_177,&g_176,&g_176,&g_176,&g_177},{&g_176,&g_177,&g_177,&g_176,&g_175,&g_176,(void*)0,&g_177,&g_176},{&g_175,&g_177,&g_175,(void*)0,&g_175,&g_175,(void*)0,&g_175,&g_177},{(void*)0,&g_175,&g_175,(void*)0,&g_175,&g_177,&g_176,&g_175,&g_175},{&g_175,&g_175,&g_177,(void*)0,&g_177,&g_175,&g_175,&g_177,&g_175},{&g_176,&g_175,&g_176,(void*)0,&g_177,&g_176,&g_176,&g_176,&g_177},{&g_176,&g_177,&g_177,&g_176,&g_175,&g_176,(void*)0,&g_177,&g_176}};
+static uint8_t **** const g_1547[1][6][2] = {{{&g_1551[1][3],&g_1552[7][4]},{&g_1551[1][3],&g_1551[1][3]},{&g_1552[7][4],&g_1551[1][3]},{&g_1551[1][3],&g_1552[7][4]},{&g_1551[1][3],&g_1551[1][3]},{&g_1552[7][4],&g_1551[1][3]}}};
+static uint8_t **** const *g_1546[5] = {&g_1547[0][2][0],&g_1547[0][2][0],&g_1547[0][2][0],&g_1547[0][2][0],&g_1547[0][2][0]};
+static int8_t ***g_1656 = &g_245;
+static uint16_t g_1766 = 0x2A71L;
+static const uint32_t g_1776 = 4294967288UL;
+static const uint32_t g_1782[6][8][5] = {{{9UL,1UL,0xC7DDDB76L,0x6C0C4151L,0x8031E06CL},{4294967288UL,0x67522ABBL,4294967289UL,9UL,0x6B1862C6L},{4294967289UL,0x035D4646L,0x4BD87A52L,0xF04D3E88L,0x02BA768FL},{0x67522ABBL,1UL,0xFBE5C2AFL,0x09838561L,0x6E51EAD8L},{0x67522ABBL,0x8031E06CL,0xFC56E314L,0x5133D18EL,0xF04D3E88L},{4294967289UL,0xFBE5C2AFL,4294967286UL,4294967295UL,4294967295UL},{4294967288UL,4294967289UL,4294967288UL,0xFC56E314L,0x4BD87A52L},{9UL,0x09838561L,4294967295UL,1UL,3UL}},{{0xD3C5907BL,0x6C0C4151L,4294967289UL,0x8031E06CL,0x035D4646L},{0x6B1862C6L,0x6E51EAD8L,4294967295UL,3UL,0x02BA768FL},{4294967294UL,0xD3C5907BL,4294967288UL,0x67522ABBL,4294967289UL},{0x6C0C4151L,0x8031E06CL,4294967286UL,4294967295UL,0xB9EFEB98L},{8UL,4294967291UL,0xFC56E314L,4294967295UL,0x2B8C1A21L},{4294967291UL,0x6B1862C6L,0xFBE5C2AFL,1UL,0x2B8C1A21L},{9UL,0x1C34F8ADL,0x4BD87A52L,4294967288UL,0xB9EFEB98L},{1UL,4294967288UL,4294967289UL,0xB9EFEB98L,4294967289UL}},{{0xE9241C7AL,0xE9241C7AL,0x6E51EAD8L,1UL,0x09838561L},{4294967288UL,3UL,0x8031E06CL,4294967291UL,0x37358859L},{1UL,4294967295UL,0xD83C2DFAL,1UL,4294967286UL},{0x4478B581L,3UL,0x2B8C1A21L,8UL,0x5A8F52F4L},{0xB9EFEB98L,0xE9241C7AL,0xF04D3E88L,0xC7DDDB76L,8UL},{1UL,1UL,0UL,7UL,0x5133D18EL},{0xF04D3E88L,4294967291UL,0x084A6D3FL,4294967286UL,0x02BA768FL},{0x02BA768FL,0xB3D218BBL,4294967289UL,4294967286UL,0x09838561L}},{{0x2BAF5CEFL,9UL,0xFDF9E1B7L,7UL,0xB3D218BBL},{4294967291UL,4294967295UL,0xC7DDDB76L,0xC7DDDB76L,4294967295UL},{0x37358859L,0x9D243B0BL,4294967295UL,8UL,4294967289UL},{0xFDF9E1B7L,0x02BA768FL,0x9D243B0BL,1UL,0x6B1862C6L},{1UL,0xFBE5C2AFL,0x6B1862C6L,4294967291UL,4294967286UL},{0xFDF9E1B7L,0x2BAF5CEFL,0x084A6D3FL,1UL,0x731D77D9L},{0x37358859L,0x084A6D3FL,0x035D4646L,0xFC56E314L,0x09838561L},{4294967291UL,0xB9EFEB98L,9UL,1UL,0x4478B581L}},{{0x2BAF5CEFL,4294967295UL,4294967291UL,4294967295UL,1UL},{0x02BA768FL,0x8031E06CL,4294967291UL,8UL,0UL},{0xF04D3E88L,0x37358859L,9UL,0x2B8C1A21L,0x6E51EAD8L},{1UL,0xD3C5907BL,0x035D4646L,0xD3C5907BL,1UL},{0xB9EFEB98L,4294967288UL,0x084A6D3FL,4294967286UL,0xE9241C7AL},{0x4478B581L,0x731D77D9L,0x6B1862C6L,4294967295UL,0x09838561L},{1UL,0xFDF9E1B7L,0x9D243B0BL,4294967288UL,0xE9241C7AL},{4294967288UL,4294967295UL,4294967295UL,0x4BD87A52L,1UL}},{{0xE9241C7AL,0xF04D3E88L,0xC7DDDB76L,8UL,0x6E51EAD8L},{0x8031E06CL,0x4478B581L,0xFDF9E1B7L,4294967291UL,0UL},{1UL,7UL,4294967289UL,0x2BAF5CEFL,1UL},{9UL,7UL,0x084A6D3FL,0x5133D18EL,0x4478B581L},{0x731D77D9L,0x4478B581L,0UL,1UL,0x09838561L},{0xFBE5C2AFL,0xF04D3E88L,0xF04D3E88L,0xFBE5C2AFL,0x731D77D9L},{7UL,4294967295UL,0x2B8C1A21L,0xD83C2DFAL,4294967286UL},{0xB3D218BBL,0xFDF9E1B7L,0xD83C2DFAL,8UL,0x6B1862C6L}}};
+static const uint32_t *g_1781 = &g_1782[2][3][4];
+static int8_t g_1857 = 0L;
+static const uint8_t *g_1941 = (void*)0;
+static const uint8_t ** const g_1940[7] = {&g_1941,&g_1941,&g_1941,&g_1941,&g_1941,&g_1941,&g_1941};
+static const uint8_t ** const *g_1939 = &g_1940[2];
+static const uint8_t ** const **g_1938 = &g_1939;
+static const uint8_t ** const ***g_1937 = &g_1938;
+static int16_t g_1961 = (-2L);
+static const int8_t g_2067 = (-1L);
+static const uint32_t ***g_2068[3] = {(void*)0,(void*)0,(void*)0};
+static int8_t g_2147[10] = {0x23L,0x23L,0x23L,0x23L,0x23L,0x23L,0x23L,0x23L,0x23L,0x23L};
+static uint16_t g_2148 = 0x794EL;
+static int16_t g_2207 = 0L;
+
+
+/* --- FORWARD DECLARATIONS --- */
+static uint16_t func_1(void);
+static int8_t func_10(uint32_t p_11);
+static int32_t func_16(int8_t p_17, uint32_t * p_18, uint32_t * p_19, uint16_t p_20, uint32_t p_21);
+static uint32_t * func_22(int16_t p_23, uint32_t p_24, uint32_t * p_25);
+static int32_t func_62(int32_t * p_63, uint8_t p_64);
+static int32_t * func_65(int8_t p_66, uint16_t p_67, uint8_t p_68, int32_t * p_69, uint32_t * p_70);
+static uint8_t * func_71(uint32_t p_72, int8_t p_73);
+static int32_t * func_94(uint32_t * p_95, int32_t p_96, const int32_t p_97, int32_t p_98, int8_t p_99);
+static int8_t func_100(int32_t * p_101, uint8_t p_102, uint8_t p_103, uint32_t p_104);
+static int32_t * func_105(uint32_t p_106);
+
+
+/* --- FUNCTIONS --- */
+/* ------------------------------------------ */
+/*
+ * reads : g_2 g_14 g_15 g_36 g_40 g_43 g_3 g_52 g_46 g_51 g_55 g_56 g_44 g_251 g_143 g_140 g_176 g_705 g_289 g_290 g_297 g_255 g_34 g_131 g_132 g_243 g_347 g_320 g_736 g_294 g_175 g_897 g_905 g_735 g_960 g_969 g_961 g_312 g_1334 g_1132 g_1184 g_1185 g_1099 g_1656 g_1238 g_1548 g_1018 g_1019 g_1254 g_1766 g_1776 g_1857 g_477 g_1298 g_1937 g_1961 g_242 g_1781 g_1782 g_419 g_2068 g_245 g_1938 g_2147 g_2148 g_1333 g_2207
+ * writes: g_3 g_14 g_15 g_34 g_36 g_40 g_52 g_51 g_46 g_255 g_297 g_140 g_312 g_294 g_56 g_44 g_347 g_290 g_897 g_904 g_419 g_251 g_969 g_1334 g_1132 g_1298 g_175 g_1099 g_1055 g_477 g_55 g_1766 g_1781 g_960 g_242 g_961 g_705 g_2068 g_2148 g_2207
+ */
+static uint16_t func_1(void)
+{ /* block id: 0 */
+ int32_t l_38 = 0xCA862934L;
+ int32_t l_1612 = 0xB952CD69L;
+ int32_t l_1634 = 0x1D6D5307L;
+ int16_t l_1658[5][6] = {{0x1999L,0L,0x1999L,0x1999L,0L,0x1999L},{0x1999L,0L,0x1999L,0x1999L,0L,0x0361L},{0x0361L,0x1999L,0x0361L,0x0361L,0x1999L,0x0361L},{0x0361L,0x1999L,0x0361L,0x0361L,0x1999L,0x0361L},{0x0361L,0x1999L,0x0361L,0x0361L,0x1999L,0x0361L}};
+ uint8_t * const ***l_1712 = &g_1295;
+ uint8_t * const ****l_1711[9] = {&l_1712,&l_1712,&l_1712,&l_1712,&l_1712,&l_1712,&l_1712,&l_1712,&l_1712};
+ uint8_t **l_1725 = &g_43;
+ int16_t l_1756[10][2] = {{0xB2C0L,(-1L)},{(-1L),0xB2C0L},{(-1L),(-1L)},{0xB2C0L,(-1L)},{(-1L),0xB2C0L},{(-1L),(-1L)},{0xB2C0L,(-1L)},{(-1L),0xB2C0L},{(-1L),(-1L)},{0xB2C0L,(-1L)}};
+ int32_t l_1763 = (-8L);
+ uint32_t *l_1783 = &g_14[1];
+ int32_t ***l_1785 = &g_961;
+ uint32_t *****l_1788 = (void*)0;
+ uint8_t l_1831 = 0x9CL;
+ uint8_t *l_1877 = &g_40[0];
+ uint32_t l_2046 = 18446744073709551609UL;
+ int8_t l_2047 = 1L;
+ uint32_t l_2048 = 2UL;
+ int32_t l_2056 = 1L;
+ int32_t l_2058 = 0L;
+ int32_t l_2072 = 9L;
+ uint32_t l_2099 = 4UL;
+ uint32_t l_2116 = 4UL;
+ uint32_t l_2184 = 0xE4A882E7L;
+ int16_t **l_2189[6][6][7] = {{{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{(void*)0,&g_289,&g_289,(void*)0,(void*)0,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{(void*)0,&g_289,&g_289,&g_289,(void*)0,&g_289,(void*)0},{&g_289,(void*)0,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,(void*)0,&g_289,(void*)0,&g_289,&g_289,&g_289}},{{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0,(void*)0}},{{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{(void*)0,(void*)0,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,(void*)0,&g_289,&g_289,&g_289},{(void*)0,&g_289,&g_289,&g_289,&g_289,(void*)0,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,(void*)0,&g_289,&g_289,(void*)0}},{{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0,&g_289},{&g_289,(void*)0,(void*)0,(void*)0,(void*)0,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0,&g_289},{&g_289,&g_289,(void*)0,&g_289,(void*)0,&g_289,&g_289}},{{&g_289,&g_289,&g_289,(void*)0,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,(void*)0,(void*)0,&g_289,&g_289,&g_289,&g_289}},{{&g_289,(void*)0,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,(void*)0,&g_289,&g_289,(void*)0,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{(void*)0,&g_289,&g_289,(void*)0,(void*)0,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{(void*)0,&g_289,&g_289,&g_289,(void*)0,&g_289,(void*)0}}};
+ int16_t ***l_2188 = &l_2189[0][5][4];
+ int16_t ****l_2187[1];
+ int i, j, k;
+ for (i = 0; i < 1; i++)
+ l_2187[i] = &l_2188;
+lbl_2208:
+ for (g_3 = 0; (g_3 <= 0); g_3 += 1)
+ { /* block id: 3 */
+ uint32_t *l_12 = (void*)0;
+ uint32_t *l_13[2][9][7] = {{{&g_14[4],&g_14[2],&g_14[1],&g_14[1],&g_14[1],(void*)0,&g_14[4]},{(void*)0,&g_14[1],&g_14[3],&g_14[1],&g_14[1],&g_14[3],&g_14[1]},{&g_14[4],&g_14[2],&g_14[1],&g_14[1],&g_14[1],(void*)0,&g_14[4]},{(void*)0,&g_14[1],&g_14[3],&g_14[1],&g_14[1],&g_14[3],&g_14[1]},{&g_14[4],&g_14[2],&g_14[1],&g_14[1],&g_14[1],(void*)0,&g_14[4]},{(void*)0,&g_14[1],&g_14[3],&g_14[1],&g_14[1],&g_14[3],&g_14[1]},{&g_14[4],&g_14[2],&g_14[1],&g_14[1],&g_14[1],(void*)0,&g_14[4]},{(void*)0,&g_14[1],&g_14[3],&g_14[1],&g_14[1],&g_14[3],&g_14[1]},{&g_14[4],&g_14[2],&g_14[1],&g_14[1],&g_14[1],(void*)0,&g_14[4]}},{{(void*)0,&g_14[1],&g_14[3],&g_14[1],&g_14[1],&g_14[3],&g_14[1]},{&g_14[4],&g_14[2],&g_14[1],&g_14[1],&g_14[1],(void*)0,&g_14[4]},{(void*)0,&g_14[1],&g_14[3],&g_14[1],(void*)0,&g_14[1],&g_14[0]},{&g_14[1],&g_14[3],&g_14[1],(void*)0,&g_14[4],&g_14[1],&g_14[1]},{&g_14[1],&g_14[0],&g_14[1],(void*)0,(void*)0,&g_14[1],&g_14[0]},{&g_14[1],&g_14[3],&g_14[1],(void*)0,&g_14[4],&g_14[1],&g_14[1]},{&g_14[1],&g_14[0],&g_14[1],(void*)0,(void*)0,&g_14[1],&g_14[0]},{&g_14[1],&g_14[3],&g_14[1],(void*)0,&g_14[4],&g_14[1],&g_14[1]},{&g_14[1],&g_14[0],&g_14[1],(void*)0,(void*)0,&g_14[1],&g_14[0]}}};
+ int8_t *l_35 = &g_36;
+ int32_t l_37 = 0x129EC6EAL;
+ uint8_t *l_39 = &g_40[1];
+ uint32_t l_1611 = 1UL;
+ const int16_t l_1613 = (-7L);
+ int32_t l_1616 = 0xF7091F80L;
+ int32_t l_1618 = 0x81A177EAL;
+ int32_t l_1623 = (-3L);
+ int8_t ***l_1657 = &g_245;
+ int i, j, k;
+ if ((((((safe_mul_func_int8_t_s_s(((safe_div_func_uint8_t_u_u(((safe_mod_func_int8_t_s_s(func_10((((g_15 &= (g_14[4] ^= g_2[1][0])) == func_16(g_2[2][0], func_22((safe_div_func_int8_t_s_s((safe_mul_func_int16_t_s_s(((safe_div_func_int32_t_s_s((safe_rshift_func_uint8_t_u_s((g_34 = 1UL), ((*l_35) ^= 0x4DL))), l_37)) == (((((*l_39) = l_38) , (--(*l_39))) >= l_37) ^ 0UL)), ((void*)0 == g_43))), g_3)), l_38, l_13[1][1][2]), g_55, l_37, g_56)) >= l_37)), l_38)) == 0x3C9EL), l_38)) , 0xBCL), l_1611)) | l_1612) == 1UL) < l_1613) == 0x39F7L))
+ { /* block id: 771 */
+ int32_t *l_1614 = &g_1055;
+ if (l_1613)
+ break;
+ (**g_960) = l_1614;
+ if (l_1611)
+ continue;
+ }
+ else
+ { /* block id: 775 */
+ int32_t *l_1615 = &g_51[1][6][2];
+ int32_t *l_1617 = &g_297[1];
+ int32_t *l_1619 = &l_1616;
+ int32_t *l_1620 = (void*)0;
+ int32_t *l_1621 = &l_1618;
+ int32_t *l_1622 = &g_297[1];
+ int32_t *l_1624 = &g_51[0][3][1];
+ int32_t *l_1625 = &l_37;
+ int32_t *l_1626 = (void*)0;
+ int32_t *l_1627 = &g_1132;
+ int32_t *l_1628 = &g_297[1];
+ int32_t *l_1629 = &l_1618;
+ int32_t *l_1630[9] = {&g_297[0],&g_297[0],&g_297[0],&g_297[0],&g_297[0],&g_297[0],&g_297[0],&g_297[0],&g_297[0]};
+ uint8_t l_1631 = 6UL;
+ int i;
+ --l_1631;
+ return (*l_1617);
+ }
+ l_1634 |= 0xB346B708L;
+ for (g_1298 = 0; (g_1298 <= 0); g_1298 += 1)
+ { /* block id: 782 */
+ uint32_t l_1635 = 0xEF083A2AL;
+ int32_t l_1644 = 0x4F483357L;
+ (*g_143) ^= l_1635;
+ (*g_143) = (safe_mul_func_uint16_t_u_u(((safe_sub_func_int8_t_s_s(((!(l_38 , l_1611)) != (l_1644 &= (safe_lshift_func_int8_t_s_s((safe_add_func_int8_t_s_s(0x2CL, l_1612)), 4)))), (safe_unary_minus_func_uint32_t_u((safe_div_func_int8_t_s_s(((g_320 <= (((l_38 <= (((safe_add_func_int16_t_s_s((safe_sub_func_uint16_t_u_u((l_1618 & (((safe_div_func_uint16_t_u_u((((((safe_rshift_func_int16_t_s_s(0x3853L, l_1635)) >= l_1612) , g_1656) != l_1657) & l_38), 65531UL)) ^ l_1623) && l_1635)), l_1658[1][1])), 0x80FFL)) == 7UL) == (**g_1238))) > 0x43L) || g_14[5])) , 5L), l_1612)))))) > l_1658[1][1]), 0UL));
+ }
+ for (g_1099 = 0; (g_1099 <= 0); g_1099 += 1)
+ { /* block id: 789 */
+ int16_t l_1661 = 0x12BEL;
+ uint16_t *l_1666[10][9] = {{(void*)0,&g_969,&g_251,&g_969,&g_251,&g_969,&g_969,&g_251,&g_969},{(void*)0,&g_969,(void*)0,(void*)0,(void*)0,&g_969,(void*)0,(void*)0,(void*)0},{&g_969,(void*)0,&g_251,&g_969,&g_251,&g_251,&g_969,&g_251,(void*)0},{&g_969,&g_969,&g_969,(void*)0,&g_969,(void*)0,&g_969,&g_969,&g_969},{&g_251,&g_251,&g_251,&g_969,&g_969,&g_251,&g_251,&g_251,&g_251},{(void*)0,&g_969,(void*)0,&g_969,(void*)0,&g_969,(void*)0,&g_969,(void*)0},{&g_251,(void*)0,&g_251,&g_251,(void*)0,&g_251,&g_251,&g_969,&g_251},{&g_969,&g_969,&g_969,&g_969,&g_969,&g_969,&g_969,&g_969,&g_969},{&g_969,&g_969,&g_969,&g_969,&g_251,&g_969,&g_251,&g_251,(void*)0},{(void*)0,&g_969,(void*)0,&g_969,(void*)0,&g_969,(void*)0,&g_969,(void*)0}};
+ int16_t l_1667 = 0xD2A4L;
+ int32_t l_1680 = 0x06D2A1F8L;
+ int32_t l_1681 = 0xB17E7D5CL;
+ int8_t l_1682 = (-5L);
+ int32_t *l_1683 = &g_1055;
+ int i, j;
+ l_37 ^= ((*l_1683) = ((*g_143) = ((safe_add_func_uint32_t_u_u((--(***g_735)), (safe_mul_func_uint8_t_u_u(((l_1681 = (!((g_969 = (l_1667 &= 1UL)) != ((*g_132) != (((((safe_mul_func_int16_t_s_s(((***g_1548) && (safe_div_func_uint8_t_u_u((((safe_sub_func_int16_t_s_s(((safe_add_func_int32_t_s_s((safe_lshift_func_uint16_t_u_u(g_34, ((*g_1018) != (*g_1018)))), (*g_143))) , (((safe_add_func_uint16_t_u_u((l_1680 = ((((l_1618 = ((***g_1184) | ((((**g_1185) ^ l_1661) && l_1661) , l_1661))) < 1L) || 65533UL) | l_1616)), (-2L))) == l_1658[3][5]) != l_1661)), l_1623)) , 0L) | l_1661), l_1661))), l_1634)) <= (*g_143)) , l_38) || (*g_143)) != (***g_1184)))))) , (*g_43)), (***g_1548))))) <= l_1682)));
+ }
+ }
+ for (l_38 = 2; (l_38 <= (-27)); l_38 = safe_sub_func_int8_t_s_s(l_38, 6))
+ { /* block id: 803 */
+ int32_t l_1692 = 0L;
+ int32_t l_1702 = 0xA1267D64L;
+ uint32_t l_1722 = 8UL;
+ uint8_t * const * const l_1726 = &g_43;
+ uint32_t *l_1737 = &g_1099;
+ int8_t *l_1793 = (void*)0;
+ int32_t *l_1797 = (void*)0;
+ uint32_t l_1859 = 0x82CF6B6FL;
+ int8_t l_1899 = 1L;
+ uint16_t l_1902 = 65534UL;
+ int8_t ***l_1936[8] = {(void*)0,&g_242,&g_242,(void*)0,&g_242,&g_242,(void*)0,&g_242};
+ uint32_t l_1957 = 5UL;
+ int32_t **l_2005 = &g_143;
+ uint32_t l_2007 = 18446744073709551615UL;
+ int32_t l_2050 = (-1L);
+ int32_t l_2051 = 5L;
+ int32_t l_2052[8][1];
+ const int8_t *l_2066 = &g_2067;
+ const int8_t **l_2065[10] = {(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0};
+ uint32_t l_2071[3][7][7] = {{{0x30CE76AEL,0UL,18446744073709551615UL,1UL,1UL,1UL,0UL},{0xAD0A2372L,0xEA6E9C20L,0UL,0x324BC3A3L,0xF442972AL,0x911E4A42L,0x911E4A42L},{18446744073709551608UL,18446744073709551610UL,0x1262E29EL,18446744073709551610UL,18446744073709551608UL,0x9477AE01L,0xF442972AL},{1UL,5UL,0x30CE76AEL,18446744073709551611UL,0x99881E2AL,0xDA83510BL,18446744073709551615UL},{0xF442972AL,0x911E4A42L,0xFCFF20AAL,0x23F69BAEL,18446744073709551608UL,0x30CE76AEL,0xAD0A2372L},{0x1262E29EL,0UL,18446744073709551615UL,1UL,0x6F0D46CCL,0x1262E29EL,0x7CF12E04L},{18446744073709551615UL,0xF442972AL,0x5F49E352L,5UL,18446744073709551615UL,0UL,0UL}},{{18446744073709551611UL,18446744073709551615UL,0x23F69BAEL,0x30CE76AEL,0UL,18446744073709551615UL,1UL},{0x250C5BC2L,18446744073709551615UL,6UL,0x30CE76AEL,1UL,1UL,0UL},{18446744073709551615UL,0x6F0D46CCL,1UL,5UL,0x911E4A42L,1UL,0x911E4A42L},{1UL,18446744073709551615UL,18446744073709551615UL,1UL,0x9477AE01L,0x23E5CD91L,0x30CE76AEL},{0x2665B0F5L,0UL,1UL,0x23F69BAEL,0xDA83510BL,0x9D1F30D5L,0UL},{18446744073709551611UL,0x5F49E352L,0x84F3CCEFL,0UL,0x9A4CA65DL,18446744073709551610UL,0x30CE76AEL},{6UL,0UL,0x324BC3A3L,0x5F49E352L,1UL,5UL,0x911E4A42L}},{{1UL,18446744073709551608UL,18446744073709551613UL,0xDC003897L,1UL,0UL,0UL},{1UL,18446744073709551615UL,18446744073709551615UL,0x324BC3A3L,18446744073709551608UL,0xCC0F1D77L,1UL},{0x9D1F30D5L,0x7DDAB611L,18446744073709551615UL,0xFCFF20AAL,0UL,0x9D1F30D5L,0UL},{18446744073709551615UL,18446744073709551615UL,18446744073709551613UL,0x7CF12E04L,0UL,0UL,0x7CF12E04L},{0x324BC3A3L,0UL,0x324BC3A3L,0x30CE76AEL,0x7CF12E04L,6UL,0xAD0A2372L},{0x5F49E352L,18446744073709551615UL,0x84F3CCEFL,18446744073709551615UL,18446744073709551614UL,18446744073709551615UL,0UL},{1UL,0UL,1UL,0x27C4E890L,0x911E4A42L,6UL,18446744073709551615UL}}};
+ uint16_t l_2191 = 0UL;
+ uint32_t l_2194 = 0x1CA07694L;
+ uint8_t *****l_2202 = &g_904[0][3];
+ uint8_t ******l_2201 = &l_2202;
+ uint8_t *l_2205 = &l_1831;
+ int32_t *l_2206[1][2];
+ int i, j, k;
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 1; j++)
+ l_2052[i][j] = 1L;
+ }
+ for (i = 0; i < 1; i++)
+ {
+ for (j = 0; j < 2; j++)
+ l_2206[i][j] = &l_2052[2][0];
+ }
+ if (((((0xEC18D826L > 0xC2623D2EL) == (safe_add_func_int32_t_s_s(((void*)0 == (*g_1018)), (*g_143)))) < ((*g_43) |= (((safe_add_func_int8_t_s_s(l_1658[4][2], (**g_131))) == (l_1634 = ((((safe_lshift_func_uint16_t_u_s(g_294[0], 5)) , l_1692) , 0x47L) && 0x07L))) != 0x6DDD7AF3L))) <= l_1692))
+ { /* block id: 806 */
+ int8_t l_1727 = 0x36L;
+ uint16_t l_1730 = 0x5E85L;
+ int32_t l_1758 = 1L;
+ int32_t l_1760 = 0x8ED80A0BL;
+ int32_t l_1762 = 0xC5EE06D0L;
+ int32_t l_1764 = 0x9C30C92FL;
+ uint8_t l_1773 = 0x04L;
+ uint32_t l_1795 = 0x25B5191FL;
+ int32_t *l_1832 = (void*)0;
+ int32_t l_1850 = 3L;
+ uint16_t l_1876 = 0xC3DDL;
+ uint32_t *****l_1891 = (void*)0;
+ uint16_t l_1901 = 65528UL;
+ for (g_419 = 0; (g_419 < 27); ++g_419)
+ { /* block id: 809 */
+ int32_t l_1697[6] = {(-8L),(-8L),(-8L),(-8L),(-8L),(-8L)};
+ uint16_t *l_1698[10][3] = {{&g_251,&g_251,&g_251},{&g_251,&g_251,&g_251},{&g_251,&g_251,&g_251},{&g_251,&g_969,&g_251},{&g_251,&g_251,&g_251},{&g_251,&g_251,&g_251},{&g_969,&g_251,&g_251},{&g_251,&g_251,&g_251},{&g_251,&g_251,&g_251},{&g_251,&g_969,&g_969}};
+ int i, j;
+ (*g_143) ^= ((**g_736) , l_1612);
+ l_1634 = (safe_lshift_func_uint16_t_u_s((g_969 = l_1697[1]), 5));
+ }
+ for (g_255 = 0; (g_255 > 7); g_255 = safe_add_func_int16_t_s_s(g_255, 8))
+ { /* block id: 816 */
+ uint8_t l_1701 = 0xB3L;
+ uint8_t * const ***l_1709 = (void*)0;
+ uint8_t * const ****l_1708 = &l_1709;
+ uint8_t * const *****l_1710[10][10][2] = {{{&l_1708,(void*)0},{&l_1708,&l_1708},{(void*)0,&l_1708},{&l_1708,(void*)0},{&l_1708,&l_1708},{(void*)0,&l_1708},{&l_1708,(void*)0},{&l_1708,&l_1708},{(void*)0,&l_1708},{&l_1708,(void*)0}},{{&l_1708,&l_1708},{(void*)0,&l_1708},{&l_1708,(void*)0},{&l_1708,&l_1708},{(void*)0,&l_1708},{&l_1708,(void*)0},{&l_1708,&l_1708},{(void*)0,&l_1708},{&l_1708,&l_1708},{(void*)0,(void*)0}},{{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0}},{{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708}},{{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0}},{{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0}},{{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708}},{{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0}},{{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0}},{{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708}}};
+ int32_t l_1721 = 1L;
+ uint32_t *l_1728 = &g_477;
+ int32_t *l_1729[5][7] = {{(void*)0,&l_38,&l_38,&l_38,(void*)0,&l_1692,&l_1692},{&g_34,(void*)0,&l_1612,(void*)0,&g_34,&g_1509,&g_1509},{(void*)0,&l_38,&l_38,&l_38,(void*)0,&l_1692,&l_1692},{&g_34,(void*)0,&l_1612,(void*)0,&g_34,&g_1509,&l_1612},{&l_1692,&l_1692,&g_34,&l_1692,&l_1692,&l_38,&l_38}};
+ int8_t *l_1731 = &l_1727;
+ int32_t l_1739 = 0xD1196770L;
+ int32_t l_1759 = 0L;
+ uint16_t *l_1806[2][8] = {{&l_1730,&l_1730,&l_1730,&l_1730,&l_1730,&l_1730,&l_1730,&l_1730},{&l_1730,&l_1730,&l_1730,&l_1730,&l_1730,&l_1730,&l_1730,&l_1730}};
+ int32_t *l_1833 = &g_3;
+ int i, j, k;
+ l_1702 = l_1701;
+ if ((safe_lshift_func_uint8_t_u_u((l_38 , 0xE4L), (((safe_mul_func_int8_t_s_s(((*l_1731) = (((safe_unary_minus_func_int8_t_s((&g_1547[0][2][1] != (l_1711[7] = l_1708)))) == (safe_add_func_int8_t_s_s((((**g_736) = (**g_736)) < (((safe_mod_func_uint16_t_u_u(((l_1634 = (((*l_1728) = (safe_mul_func_uint8_t_u_u((((**l_1726) = (((safe_add_func_uint8_t_u_u((l_1721 = l_1701), (l_1722 != (safe_div_func_int32_t_s_s((((l_1725 == l_1726) , 0x32L) > l_1727), (*g_143)))))) , 0UL) <= 0xB756L)) && 0UL), l_1612))) < 0UL)) , g_1132), (**g_1185))) && 0x6EL) | g_1254[7][0][7])), 0xB8L))) >= l_1730)), l_1730)) > 0xF123L) || (*g_43)))))
+ { /* block id: 825 */
+ uint32_t *l_1738 = &g_56;
+ for (g_477 = (-18); (g_477 >= 4); g_477 = safe_add_func_int32_t_s_s(g_477, 1))
+ { /* block id: 828 */
+ int8_t l_1736 = 0xE8L;
+ (*g_143) |= l_1727;
+ l_1721 = (l_1721 < (l_1739 = ((l_1736 , 0x13L) <= ((l_1738 = l_1737) == ((*g_736) = (*g_736))))));
+ if ((*g_143))
+ break;
+ }
+ }
+ else
+ { /* block id: 836 */
+ int32_t l_1761 = 0x3F63D84DL;
+ int32_t l_1784[6] = {0xC54599E7L,0xC54599E7L,0x4344EDEAL,0xC54599E7L,0xC54599E7L,0x4344EDEAL};
+ int32_t ***l_1794[9] = {(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0};
+ int16_t **l_1796[5][2][9] = {{{&g_289,&g_289,(void*)0,&g_289,&g_289,&g_289,(void*)0,(void*)0,&g_289},{(void*)0,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289}},{{(void*)0,&g_289,&g_289,&g_289,(void*)0,&g_289,(void*)0,&g_289,&g_289},{&g_289,&g_289,(void*)0,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289}},{{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0,&g_289,(void*)0},{&g_289,(void*)0,(void*)0,(void*)0,&g_289,&g_289,&g_289,(void*)0,&g_289}},{{(void*)0,(void*)0,&g_289,&g_289,&g_289,(void*)0,(void*)0,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0,&g_289,&g_289,&g_289}},{{(void*)0,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0,&g_289},{&g_289,(void*)0,(void*)0,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289}}};
+ int i, j, k;
+ for (g_1132 = 0; (g_1132 >= 0); g_1132 -= 1)
+ { /* block id: 839 */
+ int32_t l_1757 = 0x90288987L;
+ int32_t l_1765 = 0x82B8DD8AL;
+ const uint32_t *l_1775 = &g_1776;
+ const uint32_t **l_1774 = &l_1775;
+ const uint32_t *l_1778 = (void*)0;
+ const uint32_t **l_1777 = &l_1778;
+ const uint32_t *l_1780 = &g_1776;
+ const uint32_t **l_1779 = &l_1780;
+ int i, j, k;
+ l_1784[5] = ((safe_sub_func_int32_t_s_s((safe_mul_func_int8_t_s_s((safe_add_func_uint8_t_u_u((++(**l_1725)), ((((l_1761 = ((safe_mod_func_uint32_t_u_u((safe_lshift_func_uint16_t_u_s(0x6591L, g_1254[(g_1132 + 4)][g_1132][(g_1132 + 2)])), (l_1721 & (((safe_add_func_int16_t_s_s(l_1721, (**g_1185))) , &g_1019[3][0][0]) != &g_1019[6][0][0])))) || ((safe_add_func_uint16_t_u_u(((g_1781 = ((*l_1779) = ((*l_1777) = ((*l_1774) = func_22(((((*g_143) = ((++g_1766) < (((((((safe_add_func_int16_t_s_s(((**g_1238) , (safe_rshift_func_uint8_t_u_s(l_1765, 6))), (**g_1185))) , 0xDFL) == l_1721) | (*g_289)) & l_1739) | l_1764) < 0UL))) , l_1761) , l_1773), l_1762, (**g_735)))))) != l_1783), 0x2B14L)) & 0x69A24093L))) > l_1701) >= 1L) == l_1739))), l_1730)), 0xBDA5626EL)) | l_1701);
+ (*g_143) = l_1761;
+ l_1797 = func_105((((g_960 = l_1785) != (((safe_mul_func_uint8_t_u_u((l_1788 != (void*)0), (g_14[2] , ((((+(safe_sub_func_uint8_t_u_u((((***g_905) = (safe_mul_func_int8_t_s_s((**g_131), ((*l_1731) = ((*g_131) != l_1793))))) <= (l_1794[4] != (void*)0)), l_1795))) , (void*)0) == l_1796[1][0][3]) && g_1254[(g_1132 + 4)][g_1132][(g_1132 + 2)])))) >= l_1722) , (void*)0)) < 0xA30C448CL));
+ return l_1727;
+ }
+ (*g_143) ^= ((safe_mul_func_int8_t_s_s(0xA2L, ((safe_div_func_uint8_t_u_u(((**g_1185) < (7L < l_1701)), (*g_43))) && 0x80504E05L))) > 0UL);
+ }
+ (**g_960) = (l_1833 = (l_1832 = ((l_1773 | ((safe_mul_func_uint8_t_u_u(((++g_251) , (((--(**l_1726)) ^ ((safe_mod_func_uint32_t_u_u(0xE9892A02L, 0x6E452460L)) | (0xDA1EL && (!(((safe_div_func_int16_t_s_s((safe_rshift_func_uint16_t_u_u((g_251 = ((((safe_add_func_uint16_t_u_u((safe_mul_func_uint16_t_u_u((g_969++), 0UL)), (g_1334 & (!(((l_1758 ^= (safe_div_func_int32_t_s_s(((+((safe_lshift_func_int8_t_s_s((safe_div_func_int32_t_s_s(0x469EB03BL, ((((safe_mod_func_int32_t_s_s(l_1730, l_1773)) | l_1701) , (**g_1238)) , 4294967295UL))), 7)) != (**g_1185))) ^ 65530UL), 0x7B945D20L))) , l_1721) && l_1758))))) < 0x75L) , l_1773) != 0xD86B841BL)), g_1099)), (**g_1185))) == g_1776) != l_1759))))) , (**g_176))), 0x8EL)) || l_1831)) , (void*)0)));
+ }
+ if ((safe_div_func_uint8_t_u_u((~(safe_mod_func_uint8_t_u_u((safe_div_func_int32_t_s_s(((***g_1548) < (l_1634 |= (safe_add_func_int16_t_s_s((-3L), ((safe_mul_func_int8_t_s_s((((~(safe_mod_func_int8_t_s_s((**g_131), (safe_mul_func_uint8_t_u_u((safe_div_func_int32_t_s_s((l_1702 , ((l_1850 == (safe_rshift_func_uint16_t_u_s(1UL, (0x3DCC7414L | ((0x04DDBC4DL && (((((safe_mul_func_uint8_t_u_u(255UL, l_1760)) > (***g_1184)) >= (**g_736)) >= g_1857) == 0xD4CEL)) >= l_1763))))) > g_477)), (-1L))), (*g_132)))))) , (void*)0) != &g_961), (*g_43))) >= (**g_1185)))))), 0x7424D03BL)), l_1850))), (***g_905))))
+ { /* block id: 868 */
+ uint16_t l_1858 = 0x3EA7L;
+ (*g_143) ^= (l_1858 = 0x9CFAB74FL);
+ }
+ else
+ { /* block id: 871 */
+ int16_t **l_1864 = &g_289;
+ int16_t ***l_1863[5] = {(void*)0,(void*)0,(void*)0,(void*)0,(void*)0};
+ const int8_t *l_1873 = &g_36;
+ const int8_t **l_1872 = &l_1873;
+ const int8_t ***l_1871 = &l_1872;
+ int32_t l_1888 = 0x7ACDB461L;
+ uint32_t ****l_1893 = &g_1241;
+ uint32_t **** const *l_1892[1][10] = {{&l_1893,&l_1893,&l_1893,&l_1893,&l_1893,&l_1893,&l_1893,&l_1893,&l_1893,&l_1893}};
+ uint8_t **l_1898[8] = {&l_1877,&l_1877,&l_1877,&l_1877,&l_1877,&l_1877,&l_1877,&l_1877};
+ int32_t l_1900 = 0x122D3568L;
+ int8_t l_1931 = 0x34L;
+ int i, j;
+ (*g_143) |= l_1859;
+ for (l_1762 = 1; (l_1762 >= 0); l_1762 -= 1)
+ { /* block id: 875 */
+ uint32_t l_1860[3];
+ int16_t **l_1862 = &g_289;
+ int16_t ***l_1861 = &l_1862;
+ const int8_t ***l_1875 = &l_1872;
+ const int8_t ****l_1874 = &l_1875;
+ int i;
+ for (i = 0; i < 3; i++)
+ l_1860[i] = 18446744073709551614UL;
+ (*g_143) |= ((l_1860[0] != (l_1861 == l_1863[2])) & (safe_mul_func_uint8_t_u_u(((safe_mod_func_int32_t_s_s((+((***g_1184) < (safe_div_func_uint8_t_u_u((l_1871 == ((*l_1874) = (void*)0)), l_1876)))), ((*g_55) = ((g_297[l_1762] = (((**g_736) , l_1877) != (*l_1726))) , (**g_736))))) || 0xE5L), l_1860[2])));
+ }
+ (*g_143) = (((safe_lshift_func_uint16_t_u_u(((safe_sub_func_int8_t_s_s((*g_132), (safe_add_func_int16_t_s_s(0x0DE1L, (safe_sub_func_int16_t_s_s((safe_mod_func_uint16_t_u_u(((l_1888 , (*g_55)) && (g_969 < (g_1766 = (((**l_1725) = (((((l_1891 != l_1892[0][2]) , (safe_mul_func_uint8_t_u_u((safe_mul_func_int16_t_s_s(((l_1888 |= ((l_1898[7] != (void*)0) != 0x581BL)) || l_1634), 8UL)), 0x19L))) , (*g_289)) , l_1899) < 0x06L)) <= 0UL)))), l_1900)), (**g_1185))))))) >= 0x94L), l_1901)) != 4294967295UL) , (*g_143));
+ if (l_1902)
+ { /* block id: 885 */
+ int32_t l_1905 = 1L;
+ for (l_1760 = (-2); (l_1760 < (-23)); l_1760 = safe_sub_func_int32_t_s_s(l_1760, 3))
+ { /* block id: 888 */
+ (*g_143) ^= l_1905;
+ if (l_1905)
+ continue;
+ }
+ }
+ else
+ { /* block id: 892 */
+ uint16_t *l_1908[5][4] = {{&g_1766,&g_1766,&g_969,&l_1901},{(void*)0,&g_1766,&g_1766,(void*)0},{&g_1766,(void*)0,&g_1766,&g_969},{&g_1766,&g_1766,&g_1766,&g_969},{(void*)0,&g_969,&g_969,&g_969}};
+ int32_t l_1919 = 0x8D5F8744L;
+ int i, j;
+ (*g_143) = (l_1702 ^= ((((safe_sub_func_uint16_t_u_u((g_1766 = (++g_251)), ((((safe_div_func_int32_t_s_s(((++g_969) | (safe_mul_func_uint8_t_u_u(l_1919, (l_1919 != l_1658[2][1])))), l_1756[4][1])) <= ((safe_sub_func_int16_t_s_s((safe_lshift_func_uint8_t_u_s(l_1888, l_1730)), (((safe_lshift_func_int16_t_s_s((safe_rshift_func_uint16_t_u_s((((!(l_1919 , 0x59L)) ^ (l_1900 < l_1900)) >= l_1900), 4)), 14)) , (void*)0) != (void*)0))) <= 0xD049L)) > 0x779C7159L) , g_255))) ^ l_1900) | 1L) <= (***g_905)));
+ for (g_1298 = (-14); (g_1298 >= 3); g_1298++)
+ { /* block id: 900 */
+ int32_t l_1930 = (-1L);
+ if (l_1930)
+ break;
+ if (l_1931)
+ continue;
+ l_1919 &= 0xDF650B0EL;
+ }
+ for (g_34 = 0; (g_34 <= 3); g_34 += 1)
+ { /* block id: 907 */
+ return g_36;
+ }
+ }
+ }
+ }
+ else
+ { /* block id: 912 */
+ int16_t l_1932 = (-4L);
+ const uint8_t ** const ***l_1943 = &g_1938;
+ int8_t **l_1974 = &l_1793;
+ int32_t l_1990 = (-4L);
+ int32_t *l_2009[3];
+ int16_t **l_2027 = &g_289;
+ int16_t ***l_2026 = &l_2027;
+ const int16_t *l_2030 = &g_1285;
+ const int16_t **l_2029 = &l_2030;
+ const int16_t ***l_2028[3][5][2] = {{{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029}},{{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029}},{{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029}}};
+ int32_t l_2031[7][5] = {{0x7B32F464L,0x31A52CFCL,(-1L),0x1CB357FAL,(-1L)},{(-1L),(-1L),0xFE12D187L,0x1CB357FAL,(-10L)},{0x31A52CFCL,0x7B32F464L,0x7B32F464L,0x31A52CFCL,(-1L)},{0x31A52CFCL,0x1CB357FAL,0L,0L,0x1CB357FAL},{(-1L),0x7B32F464L,0L,0xFE12D187L,0xFE12D187L},{0x7B32F464L,(-1L),0x7B32F464L,0L,0xFE12D187L},{0x1CB357FAL,0x31A52CFCL,0xFE12D187L,0x31A52CFCL,0x1CB357FAL}};
+ int32_t l_2032 = 4L;
+ int i, j, k;
+ for (i = 0; i < 3; i++)
+ l_2009[i] = &g_3;
+ if (l_1932)
+ { /* block id: 913 */
+ uint16_t l_1966 = 0xAA16L;
+ uint8_t l_1967 = 9UL;
+ int32_t l_1989 = 0x49AFD519L;
+ int32_t **l_2003 = &g_312[1][0][5];
+ for (g_347 = 0; (g_347 <= 18); g_347++)
+ { /* block id: 916 */
+ uint8_t l_1935[1][10][2] = {{{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL}}};
+ int32_t l_1975 = (-9L);
+ uint8_t l_2006 = 0x8EL;
+ int i, j, k;
+ if (l_1935[0][3][1])
+ { /* block id: 917 */
+ const uint8_t ** const ****l_1942[3][1];
+ int i, j;
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 1; j++)
+ l_1942[i][j] = &g_1937;
+ }
+ (*g_143) = ((((((void*)0 != l_1936[2]) & (-1L)) , &g_897) != (l_1943 = g_1937)) & (safe_lshift_func_uint16_t_u_s((safe_add_func_int8_t_s_s((*g_132), (0UL <= l_1932))), 4)));
+ }
+ else
+ { /* block id: 920 */
+ int32_t *l_1952 = &l_1612;
+ int32_t l_1960 = 0x13E80650L;
+ uint16_t *l_1968[9] = {&g_1766,&g_251,&g_1766,&g_1766,&g_251,&g_1766,&g_1766,&g_251,&g_1766};
+ int32_t *l_1969 = &g_3;
+ int32_t ***l_2004[4] = {&l_2003,&l_2003,&l_2003,&l_2003};
+ uint32_t *l_2008 = &g_705[2];
+ int i;
+ (*l_1969) ^= ((safe_mul_func_int16_t_s_s((*g_289), (safe_sub_func_uint8_t_u_u(((((*l_1952) = 0x79EFCB11L) , (((0x39L >= ((safe_div_func_int32_t_s_s(((*g_143) = (safe_add_func_int8_t_s_s(l_1957, (g_1857 && (g_251 = (safe_mul_func_uint8_t_u_u((l_1960 | g_1961), ((((safe_mod_func_int32_t_s_s(((safe_lshift_func_uint16_t_u_u(g_1298, l_1960)) == l_1966), l_1967)) && (*g_289)) , (*g_55)) != (*g_55))))))))), l_1960)) && l_1966)) , (***g_1184)) , l_1966)) || (**g_131)), (***g_1548))))) || l_1935[0][6][1]);
+ l_1990 &= (safe_rshift_func_int16_t_s_u((safe_rshift_func_int8_t_s_s((l_1975 = ((g_320 , ((**g_1018) = (**g_1018))) != l_1974)), 7)), ((l_1935[0][3][1] & (safe_add_func_int16_t_s_s((safe_div_func_int16_t_s_s((((((*l_1969) = ((***g_1184) > ((*l_1969) ^ (l_1989 = (safe_add_func_uint8_t_u_u(((safe_unary_minus_func_uint16_t_u(((((((((safe_lshift_func_int8_t_s_u(((safe_rshift_func_uint8_t_u_u(l_1935[0][6][0], l_1902)) > (((g_1766 = ((l_1967 , (*g_143)) & (*g_143))) , &g_1184) != (void*)0)), l_1935[0][3][1])) , l_1966) , 0x5DL) || 0x87L) <= l_1935[0][3][1]) || (*g_1781)) , &l_1692) == &g_1509))) ^ l_1932), 0xE0L)))))) || 251UL) | 0x46L) > l_1967), 0x3894L)), 0UL))) , g_1782[2][3][4])));
+ l_2009[0] = func_105(((*l_2008) |= (safe_mod_func_int8_t_s_s((safe_rshift_func_uint16_t_u_s((g_1766++), ((((**g_1185) || (safe_rshift_func_uint16_t_u_u((((**g_736) = ((((+l_1935[0][3][1]) ^ 0x452888BFL) || ((((+((safe_rshift_func_int16_t_s_u((((l_1763 &= (safe_add_func_uint32_t_u_u((*g_55), ((((((*g_289) = ((*g_143) != ((*l_1969) = (*g_55)))) || 0x3A0FL) , ((((*l_1785) = (*g_960)) != (l_2005 = l_2003)) && l_1989)) , (*l_1969)) < l_1990)))) < 0xC6L) || 0xF854188CL), l_1975)) != l_2006)) <= 6L) , (void*)0) == (void*)0)) , l_2007)) | l_2006), g_251))) || 1L) | 0x7544L))), 4L))));
+ }
+ if (l_1935[0][3][1])
+ continue;
+ }
+ (*g_143) &= 0xCBD7ED2CL;
+ }
+ else
+ { /* block id: 944 */
+ int32_t l_2014 = 0x16460141L;
+ uint8_t l_2033 = 0x2EL;
+ uint16_t *l_2039 = &g_251;
+ int32_t l_2049 = 0L;
+ int16_t l_2053[3];
+ int32_t l_2054 = 0x72FC0805L;
+ int32_t l_2055 = (-4L);
+ int32_t l_2057 = 0x441D13AEL;
+ int32_t l_2059 = 0xB129E460L;
+ uint32_t l_2060[3][6] = {{1UL,1UL,18446744073709551615UL,1UL,1UL,18446744073709551615UL},{1UL,1UL,18446744073709551615UL,1UL,1UL,18446744073709551615UL},{1UL,1UL,18446744073709551615UL,1UL,1UL,18446744073709551615UL}};
+ int i, j;
+ for (i = 0; i < 3; i++)
+ l_2053[i] = (-9L);
+ if (((**l_2005) > ((safe_div_func_uint16_t_u_u(((((**g_736) = (safe_mul_func_int8_t_s_s(0xC9L, l_2014))) & (safe_sub_func_int32_t_s_s((safe_sub_func_uint8_t_u_u((**l_2005), ((safe_mul_func_uint16_t_u_u((((safe_unary_minus_func_int16_t_s(((l_2032 = (l_2014 , (safe_mod_func_int32_t_s_s(0L, (safe_rshift_func_int8_t_s_s(((((((**g_1185) = (l_1658[1][1] == l_2014)) > ((l_2026 = l_2026) == l_2028[1][2][1])) || 1L) < g_1254[4][0][0]) <= g_297[1]), l_2031[3][2])))))) >= 0xFCL))) < (*g_143)) != 65529UL), l_2033)) , l_2014))), 0L))) >= (**l_2005)), (-4L))) || 4L)))
+ { /* block id: 949 */
+ int32_t *l_2036 = (void*)0;
+ for (g_1298 = 3; (g_1298 < 13); g_1298++)
+ { /* block id: 952 */
+ (*g_961) = l_2036;
+ (*g_143) = l_2033;
+ }
+ }
+ else
+ { /* block id: 956 */
+ if ((*g_143))
+ break;
+ }
+ l_2049 ^= ((safe_mod_func_uint16_t_u_u((g_1766 = ((1L ^ (((*l_2039) = ((void*)0 != &g_52)) <= (**g_1185))) , ((((safe_add_func_int16_t_s_s((((((+(safe_mod_func_int32_t_s_s((safe_sub_func_int16_t_s_s(((l_2046 ^ l_2047) >= ((!((l_2048 && (*g_1781)) , (254UL >= 0x4AL))) || 0xC4L)), g_51[0][3][1])), 0xD7857D83L))) , g_419) > g_40[1]) ^ l_2014) | 0x90L), g_1334)) & 0x40A7L) >= 0x889DL) | (**l_2005)))), 0x2C7FL)) != (**g_131));
+ l_2060[2][2]--;
+ l_2059 |= (safe_sub_func_int32_t_s_s(l_2057, (0x662AL ^ (((l_2065[3] = (void*)0) != ((**g_1018) = (**g_1018))) >= ((0x53A4L & ((*l_2039) &= ((&g_736 != (g_2068[0] = g_2068[1])) >= (safe_mul_func_uint8_t_u_u(l_2049, (**g_131)))))) ^ l_2071[1][4][6])))));
+ }
+ }
+ if (((*g_143) = l_2072))
+ { /* block id: 971 */
+ uint8_t l_2089 = 0x87L;
+ int32_t l_2095 = 1L;
+ const uint16_t l_2097 = 0xBF4DL;
+ int32_t l_2102[7][4];
+ int32_t l_2108 = 0x7BAB6EA1L;
+ int8_t l_2128 = 0x3DL;
+ uint32_t *l_2168 = &l_1957;
+ int32_t l_2182 = 0x479FFEDCL;
+ int32_t *l_2190[4];
+ int i, j;
+ for (i = 0; i < 7; i++)
+ {
+ for (j = 0; j < 4; j++)
+ l_2102[i][j] = 0x0A83AFD4L;
+ }
+ for (i = 0; i < 4; i++)
+ l_2190[i] = &g_3;
+ for (l_1692 = 2; (l_1692 >= 0); l_1692 -= 1)
+ { /* block id: 974 */
+ uint32_t l_2085 = 0xB0246361L;
+ int8_t l_2086 = 0xB9L;
+ int32_t l_2094 = (-10L);
+ const uint32_t l_2096[1] = {0xC2A82A10L};
+ uint32_t *l_2098 = &l_2071[1][5][2];
+ int32_t *l_2100 = &l_1634;
+ int32_t *l_2101[4];
+ uint16_t *l_2179 = &g_2148;
+ int i, j;
+ for (i = 0; i < 4; i++)
+ l_2101[i] = &l_2050;
+ if ((l_2102[6][0] |= ((*l_2100) &= (safe_mul_func_int8_t_s_s(((safe_div_func_uint8_t_u_u((g_705[2] , (safe_mod_func_int8_t_s_s((((*l_2098) = (safe_lshift_func_uint8_t_u_u((safe_sub_func_int8_t_s_s((((safe_mul_func_int8_t_s_s((l_2085 < l_2086), (g_1782[3][1][1] >= ((((safe_lshift_func_uint8_t_u_s(l_2089, 2)) == (g_705[2] ^ (((safe_mod_func_int16_t_s_s(((***g_1184) = (((((safe_mod_func_int32_t_s_s(((+(l_2095 = (l_2094 = l_2089))) , ((*g_143) = ((*g_143) > l_2085))), (**g_1238))) < (***g_1184)) == l_2089) || l_2096[0]) , 0x2B74L)), l_2089)) == l_2085) , 0x2251L))) != l_2089) || 65535UL)))) <= l_2089) , (-10L)), l_2089)), l_2097))) , l_2099), 0x69L))), l_2089)) <= (*g_55)), (**g_131))))))
+ { /* block id: 982 */
+ int8_t l_2115 = 1L;
+ int8_t * const *l_2118 = &g_243[5][0][8];
+ int16_t *l_2136 = &l_1658[1][1];
+ int16_t **l_2137 = &l_2136;
+ int32_t l_2146 = 1L;
+ int32_t ***l_2157 = &g_961;
+ int32_t ****l_2167 = &g_960;
+ for (l_1722 = 0; (l_1722 <= 4); l_1722 += 1)
+ { /* block id: 985 */
+ uint16_t *l_2117 = &l_1902;
+ int16_t *l_2127 = &g_347;
+ uint32_t l_2135 = 8UL;
+ int i, j;
+ l_2095 = (l_2102[6][0] = (((safe_unary_minus_func_uint8_t_u(l_1658[l_1722][(l_1692 + 3)])) != (((((*l_2117) &= (l_1658[l_1692][(l_1722 + 1)] >= (safe_mod_func_uint8_t_u_u((((0L < (((void*)0 != (*g_1656)) , (l_2108 > (safe_add_func_int32_t_s_s(((*l_2100) = ((safe_mod_func_uint32_t_u_u(l_2108, ((safe_mul_func_int8_t_s_s(0xACL, (l_2115 , (**g_175)))) & l_2116))) >= 0x6E903ADFL)), l_2115))))) || (**g_131)) ^ 0UL), l_1658[l_1722][(l_1692 + 3)])))) , (void*)0) != l_2118) & (***g_1184))) || 0xFCE3BADFL));
+ (*g_143) = (safe_mod_func_int8_t_s_s(((0xCFL > (safe_rshift_func_uint16_t_u_s((((((*g_1937) == (void*)0) != (*g_143)) && (safe_lshift_func_uint16_t_u_u((((~((*g_289) = (((((safe_lshift_func_uint8_t_u_s(l_2115, 4)) > (-6L)) && ((*l_2127) ^= (*g_289))) , (l_2128 >= (((safe_mod_func_uint16_t_u_u((safe_sub_func_uint8_t_u_u((((*l_2100) = ((safe_add_func_uint8_t_u_u(l_1658[l_1722][(l_1692 + 3)], l_2102[2][1])) ^ l_2135)) < l_2102[0][3]), (**g_175))), l_1658[l_1692][(l_1722 + 1)])) & 3L) , 1L))) >= 1UL))) & l_2108) > 1L), 6))) ^ 0xA1E6L), 14))) <= (*g_132)), (-6L)));
+ }
+ (*l_2100) &= (((*l_2137) = l_2136) == (void*)0);
+ l_2050 &= ((safe_mod_func_int8_t_s_s((l_1634 = (*g_132)), (safe_mod_func_int16_t_s_s((((*g_143) = (*g_143)) > (g_1857 < (l_2058 && (g_2148 |= (((((((void*)0 != &l_2086) == ((***g_735) = (((+(((l_2146 ^= (~(((safe_div_func_int32_t_s_s(0xBFC11C93L, (safe_mod_func_uint32_t_u_u(l_2095, (((*g_289) < 4L) , (*g_1781)))))) ^ 0x95679D65L) >= 0xA1895B12L))) >= (**g_131)) && 4294967293UL)) >= (**g_131)) , g_2147[7]))) , l_2146) <= l_2102[6][0]) , 0xB3BFL) == (-1L)))))), g_705[2])))) == 0x3157L);
+ if ((*g_143))
+ { /* block id: 1003 */
+ int32_t ****l_2158 = (void*)0;
+ int32_t ****l_2159 = &l_2157;
+ uint16_t *l_2160 = &l_1902;
+ l_2102[6][0] = (((safe_rshift_func_int16_t_s_u((0L ^ (safe_rshift_func_int8_t_s_s((((*l_2160) = (safe_div_func_int32_t_s_s((safe_mod_func_uint16_t_u_u((((*l_2159) = l_2157) == (void*)0), g_1333)), (*l_2100)))) > ((safe_add_func_int32_t_s_s(0x43A31542L, (safe_rshift_func_uint8_t_u_s((((*l_2136) = ((*g_289) = 0x48A9L)) <= l_2146), (((((((**g_736)--) , &g_960) == l_2167) & l_2089) <= (*g_1781)) < (**g_131)))))) < (*g_143))), 5))), 5)) ^ 0xDFCAL) & 65532UL);
+ (**g_960) = (***l_2167);
+ }
+ else
+ { /* block id: 1011 */
+ int32_t l_2169 = 0xB5AD6469L;
+ (**g_960) = func_22((*g_289), (*g_1781), l_2168);
+ (*g_143) = l_2169;
+ }
+ }
+ else
+ { /* block id: 1015 */
+ int32_t **l_2170[5];
+ int i;
+ for (i = 0; i < 5; i++)
+ l_2170[i] = &l_1797;
+ l_2100 = ((**l_1785) = (**g_960));
+ }
+ (**g_960) = func_22((safe_div_func_uint16_t_u_u(((((safe_add_func_uint16_t_u_u((l_1692 , g_34), (safe_add_func_uint8_t_u_u(l_2095, 250UL)))) ^ (*g_132)) & ((safe_mod_func_uint32_t_u_u((5UL < (((*l_2179) = ((void*)0 == (**g_1656))) && (safe_mul_func_int16_t_s_s((((l_2182 > 1UL) <= (*g_143)) != (*g_289)), 1UL)))), 0x328F77E6L)) , 1L)) | 1L), g_140)), (***g_735), &l_2048);
+ for (l_2099 = 0; (l_2099 <= 2); l_2099 += 1)
+ { /* block id: 1023 */
+ int32_t l_2183 = 0x7A6C031CL;
+ ++l_2184;
+ l_2102[2][3] = ((*g_143) = (l_2187[0] == &g_1184));
+ }
+ return g_1099;
+ }
+ l_2191++;
+ }
+ else
+ { /* block id: 1031 */
+ return l_2194;
+ }
+ g_2207 |= ((*g_143) = (safe_sub_func_int32_t_s_s(l_2056, (safe_div_func_uint8_t_u_u(((((!(*g_289)) , ((safe_sub_func_int8_t_s_s(((((*l_2201) = &g_904[2][1]) != &g_1547[0][5][0]) & 0x784FL), (safe_sub_func_uint16_t_u_u((l_2205 == (void*)0), g_1132)))) || (0L > (-1L)))) , &g_1019[4][0][0]) != &g_1019[5][0][0]), l_1612)))));
+ if (l_2050)
+ goto lbl_2208;
+ }
+ return l_1658[1][1];
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_290 g_143 g_905 g_1298
+ * writes: g_290 g_140 g_175 g_1298
+ */
+static int8_t func_10(uint32_t p_11)
+{ /* block id: 756 */
+ uint32_t l_1605 = 3UL;
+ uint8_t **l_1608[3][5] = {{&g_43,&g_43,&g_43,&g_43,&g_43},{&g_43,&g_43,&g_43,&g_43,&g_43},{&g_43,&g_43,&g_43,&g_43,&g_43}};
+ int i, j;
+ for (g_290 = 0; (g_290 >= 1); g_290++)
+ { /* block id: 759 */
+ int32_t l_1603 = (-1L);
+ int32_t *l_1604[10];
+ int i;
+ for (i = 0; i < 10; i++)
+ l_1604[i] = &g_297[1];
+ (*g_143) = (safe_mod_func_int32_t_s_s(l_1603, p_11));
+ l_1605++;
+ if (p_11)
+ break;
+ }
+ (*g_905) = l_1608[2][0];
+ for (g_1298 = (-1); (g_1298 == 37); g_1298 = safe_add_func_uint16_t_u_u(g_1298, 9))
+ { /* block id: 767 */
+ return l_1605;
+ }
+ return l_1605;
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_52 g_43 g_44 g_51 g_251 g_143 g_140 g_176 g_705 g_289 g_290 g_297 g_255 g_55 g_56 g_36 g_34 g_131 g_132 g_243 g_347 g_320 g_736 g_294 g_175 g_897 g_905 g_735 g_960 g_969 g_961 g_312 g_1334 g_1132 g_1184 g_1185 g_1099 g_1298 g_40
+ * writes: g_46 g_36 g_255 g_297 g_140 g_312 g_294 g_51 g_34 g_56 g_44 g_347 g_290 g_897 g_904 g_419 g_251 g_969 g_1334 g_1132 g_1298 g_175
+ */
+static int32_t func_16(int8_t p_17, uint32_t * p_18, uint32_t * p_19, uint16_t p_20, uint32_t p_21)
+{ /* block id: 16 */
+ uint32_t l_57 = 0xB31DF952L;
+ uint32_t *l_58 = &g_56;
+ int32_t * const l_59[10] = {&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2]};
+ uint32_t l_74[2][9] = {{0x548DC091L,0x548DC091L,0x548DC091L,0x548DC091L,0x548DC091L,0x548DC091L,0x548DC091L,0x548DC091L,0x548DC091L},{0UL,0x253094EEL,0UL,0x253094EEL,0UL,0x253094EEL,0UL,0x253094EEL,0UL}};
+ uint8_t *l_1340[8][7] = {{&g_40[1],&g_40[5],&g_1298,&g_1298,&g_40[5],&g_40[1],&g_40[1]},{&g_40[5],&g_40[1],(void*)0,&g_1298,&g_1298,(void*)0,&g_40[1]},{&g_40[5],&g_40[1],&g_40[1],&g_40[5],&g_1298,&g_1298,&g_40[5]},{&g_40[1],&g_40[1],&g_40[1],&g_1298,&g_40[1],&g_40[1],&g_40[1]},{&g_40[1],&g_40[5],(void*)0,&g_40[5],&g_40[1],(void*)0,&g_1298},{&g_1298,&g_40[1],&g_1298,&g_1298,&g_1298,&g_40[1],&g_1298},{&g_40[1],&g_1298,&g_40[1],&g_1298,&g_1298,&g_1298,&g_40[1]},{&g_1298,&g_40[1],&g_1298,&g_40[1],&g_1298,&g_1298,&g_1298}};
+ uint8_t *l_1341 = (void*)0;
+ uint8_t l_1385 = 0UL;
+ const int8_t *l_1399 = &g_255;
+ const int8_t ** const l_1398 = &l_1399;
+ const int8_t ** const *l_1397 = &l_1398;
+ int16_t **l_1400 = &g_289;
+ int8_t l_1404 = 0xDEL;
+ int16_t l_1460 = 0x14BCL;
+ uint8_t ** const *l_1553 = &g_175;
+ int32_t *l_1557[2];
+ const uint32_t *l_1564[2];
+ const uint32_t **l_1563[9][8][3] = {{{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[0],(void*)0,(void*)0},{&l_1564[1],&l_1564[0],&l_1564[1]},{(void*)0,&l_1564[1],&l_1564[1]},{&l_1564[0],&l_1564[1],(void*)0},{(void*)0,&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]}},{{(void*)0,&l_1564[0],&l_1564[1]},{&l_1564[1],(void*)0,&l_1564[1]},{&l_1564[0],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[0],&l_1564[1]},{&l_1564[1],&l_1564[1],(void*)0},{&l_1564[0],&l_1564[1],&l_1564[1]},{&l_1564[0],&l_1564[1],&l_1564[0]},{&l_1564[0],&l_1564[1],&l_1564[1]}},{{&l_1564[0],&l_1564[1],&l_1564[0]},{&l_1564[0],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[0],&l_1564[0],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{(void*)0,&l_1564[1],&l_1564[0]},{&l_1564[1],&l_1564[1],&l_1564[0]}},{{&l_1564[1],&l_1564[0],&l_1564[0]},{(void*)0,&l_1564[1],&l_1564[0]},{&l_1564[0],&l_1564[1],&l_1564[0]},{(void*)0,&l_1564[1],&l_1564[1]},{&l_1564[1],(void*)0,&l_1564[1]},{&l_1564[0],(void*)0,&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]}},{{&l_1564[1],&l_1564[1],&l_1564[0]},{&l_1564[1],(void*)0,&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[0]},{&l_1564[1],(void*)0,&l_1564[1]},{&l_1564[1],&l_1564[1],(void*)0},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],(void*)0,&l_1564[1]}},{{&l_1564[1],(void*)0,&l_1564[1]},{&l_1564[0],&l_1564[1],&l_1564[1]},{(void*)0,&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[0],(void*)0},{&l_1564[1],&l_1564[1],&l_1564[1]},{(void*)0,&l_1564[1],&l_1564[1]},{&l_1564[0],&l_1564[1],(void*)0}},{{&l_1564[1],&l_1564[0],&l_1564[1]},{&l_1564[1],&l_1564[1],(void*)0},{&l_1564[1],&l_1564[1],&l_1564[0]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]}},{{&l_1564[1],&l_1564[1],&l_1564[0]},{&l_1564[1],&l_1564[0],(void*)0},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[0],(void*)0,(void*)0},{&l_1564[1],&l_1564[0],&l_1564[1]},{(void*)0,&l_1564[1],&l_1564[0]},{&l_1564[1],&l_1564[1],&l_1564[1]},{(void*)0,&l_1564[1],&l_1564[0]}},{{&l_1564[1],&l_1564[1],&l_1564[0]},{&l_1564[1],&l_1564[1],&l_1564[1]},{(void*)0,&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[0]},{(void*)0,&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{(void*)0,&l_1564[0],(void*)0},{(void*)0,(void*)0,&l_1564[1]}}};
+ const uint32_t ***l_1562 = &l_1563[2][1][2];
+ const uint32_t ****l_1561 = &l_1562;
+ int32_t l_1574 = (-3L);
+ int32_t l_1577 = (-2L);
+ const uint8_t *l_1594 = &g_320;
+ const uint8_t **l_1593 = &l_1594;
+ int i, j, k;
+ for (i = 0; i < 2; i++)
+ l_1557[i] = &g_1132;
+ for (i = 0; i < 2; i++)
+ l_1564[i] = (void*)0;
+ if (((*g_143) = ((((((*p_18) = l_57) > ((l_58 = &l_57) != ((((l_59[2] != ((safe_rshift_func_int8_t_s_s(g_52, (((void*)0 == p_19) , ((*g_43) , (func_62(func_65((((l_1340[5][0] = func_71(l_74[0][4], p_20)) != l_1341) >= (-1L)), p_17, p_17, p_18, p_19), p_20) & l_1385))))) , (void*)0)) , 5L) == p_21) , (void*)0))) , 1L) | p_21) < p_17)))
+ { /* block id: 667 */
+ int16_t l_1396[4];
+ int32_t l_1421 = 7L;
+ int32_t l_1462 = 0x12662E75L;
+ int32_t l_1465 = 0x863BF099L;
+ int32_t l_1467 = 0L;
+ int32_t l_1470 = 2L;
+ int32_t l_1477 = 0x4CD2A26BL;
+ int32_t l_1490[10][2][5] = {{{0L,1L,8L,0x286E9DC0L,0x5DE9A0F1L},{0L,0x8BAB543FL,0x040A2369L,0x8BAB543FL,0L}},{{0x5DE9A0F1L,0x286E9DC0L,8L,1L,0L},{0L,0xF9205F80L,0x3F2E14FAL,0x8BAB543FL,(-1L)}},{{0L,0x286E9DC0L,(-4L),0x286E9DC0L,0L},{(-1L),0x8BAB543FL,0x3F2E14FAL,0xF9205F80L,0L}},{{0L,1L,8L,0x286E9DC0L,0x5DE9A0F1L},{0L,0x8BAB543FL,0x040A2369L,0x8BAB543FL,0L}},{{0x5DE9A0F1L,0x286E9DC0L,8L,1L,0L},{0L,0xF9205F80L,0x3F2E14FAL,0x8BAB543FL,(-1L)}},{{0L,0x286E9DC0L,(-4L),0x286E9DC0L,0L},{(-1L),0x8BAB543FL,0x3F2E14FAL,0xF9205F80L,0L}},{{0L,1L,8L,0x286E9DC0L,0x5DE9A0F1L},{0L,0x8BAB543FL,0x040A2369L,0x8BAB543FL,0L}},{{0x5DE9A0F1L,0x286E9DC0L,8L,1L,0L},{0L,0xF9205F80L,0x3F2E14FAL,0x8BAB543FL,(-1L)}},{{0L,0x286E9DC0L,(-4L),0x286E9DC0L,0L},{(-1L),0x8BAB543FL,0x3F2E14FAL,0xF9205F80L,0L}},{{0L,1L,8L,0x286E9DC0L,0x5DE9A0F1L},{0L,0x8BAB543FL,0x040A2369L,0x8BAB543FL,0L}}};
+ uint8_t l_1499 = 0xACL;
+ const int32_t l_1539[1][3] = {{0L,0L,0L}};
+ uint32_t ****l_1575 = &g_1237[6][2][0];
+ int32_t **l_1579 = (void*)0;
+ int i, j, k;
+ for (i = 0; i < 4; i++)
+ l_1396[i] = (-1L);
+ for (g_1298 = 1; (g_1298 <= 5); g_1298 += 1)
+ { /* block id: 670 */
+ int16_t **l_1401 = (void*)0;
+ uint16_t *l_1402 = &g_969;
+ int32_t l_1403 = (-1L);
+ uint32_t ***l_1405 = &g_1238;
+ uint32_t **l_1406 = &g_55;
+ uint32_t *l_1422[9];
+ uint16_t l_1431 = 3UL;
+ int32_t l_1432 = 0xD4EEA904L;
+ int16_t ***l_1449 = &l_1401;
+ int32_t l_1464 = (-8L);
+ int32_t l_1468 = (-7L);
+ int32_t l_1469[8][4] = {{0x419228AFL,0xBFCFCC48L,0x419228AFL,2L},{0x3A8515F3L,0xBFCFCC48L,0x213DF6CAL,0xBFCFCC48L},{0x3A8515F3L,2L,0x419228AFL,0xBFCFCC48L},{0x419228AFL,0xBFCFCC48L,0x419228AFL,2L},{0x3A8515F3L,0xBFCFCC48L,0x213DF6CAL,0xBFCFCC48L},{0x3A8515F3L,2L,0x419228AFL,0xBFCFCC48L},{0x419228AFL,0xBFCFCC48L,0x419228AFL,2L},{0x3A8515F3L,0xBFCFCC48L,0x213DF6CAL,0xBFCFCC48L}};
+ int8_t l_1493 = 0L;
+ int32_t **l_1532 = &g_312[0][0][4];
+ int i, j;
+ for (i = 0; i < 9; i++)
+ l_1422[i] = &g_1099;
+ }
+ }
+ else
+ { /* block id: 747 */
+ int16_t l_1580 = (-1L);
+ const uint8_t ***l_1595 = &l_1593;
+ uint8_t *l_1598[2];
+ int i;
+ for (i = 0; i < 2; i++)
+ l_1598[i] = &g_1298;
+ (*g_143) = l_1580;
+ l_1557[1] = ((safe_lshift_func_int8_t_s_s((!(safe_rshift_func_uint8_t_u_s((l_1580 & (((safe_lshift_func_int16_t_s_u((safe_mod_func_uint8_t_u_u((safe_sub_func_uint16_t_u_u((((g_40[1] != g_34) , ((*l_1595) = l_1593)) == ((*g_905) = &l_1340[5][4])), (safe_sub_func_int32_t_s_s((((void*)0 != l_1598[0]) , ((*g_143) |= p_20)), (((l_1580 ^ l_1580) && p_21) , p_20))))), p_17)), p_20)) && p_17) < p_21)), l_1580))), l_1580)) , (*g_961));
+ return l_1580;
+ }
+ return p_21;
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_52 g_46 g_51
+ * writes: g_52 g_51 g_36 g_40
+ */
+static uint32_t * func_22(int16_t p_23, uint32_t p_24, uint32_t * p_25)
+{ /* block id: 10 */
+ int32_t *l_45 = &g_46;
+ int32_t *l_47 = (void*)0;
+ int32_t *l_48 = &g_46;
+ int32_t *l_49 = &g_46;
+ int32_t *l_50[1];
+ int i;
+ for (i = 0; i < 1; i++)
+ l_50[i] = &g_46;
+ --g_52;
+ g_51[0][3][1] &= (*l_48);
+ for (g_52 = 0; g_52 < 2; g_52 += 1)
+ {
+ for (g_36 = 0; g_36 < 8; g_36 += 1)
+ {
+ for (p_24 = 0; p_24 < 3; p_24 += 1)
+ {
+ g_51[g_52][g_36][p_24] = 0x6F67A21EL;
+ }
+ }
+ }
+ for (p_24 = 0; p_24 < 7; p_24 += 1)
+ {
+ g_40[p_24] = 248UL;
+ }
+ return l_50[0];
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_143 g_140
+ * writes: g_140
+ */
+static int32_t func_62(int32_t * p_63, uint8_t p_64)
+{ /* block id: 663 */
+ uint32_t l_1384 = 4294967295UL;
+ (*g_143) &= l_1384;
+ return (*g_143);
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_143 g_140 g_1132 g_735 g_736 g_55 g_289 g_290 g_56 g_176 g_43 g_1184 g_1185 g_1099 g_44 g_297 g_36 g_51 g_705 g_34 g_131 g_132 g_243 g_347 g_320 g_294 g_175 g_255 g_897 g_905 g_251 g_960 g_969 g_961 g_312 g_1334
+ * writes: g_1132 g_44 g_36 g_140 g_312 g_51 g_34 g_56 g_297 g_347 g_290 g_255 g_897 g_904 g_294 g_419 g_251 g_969 g_1334
+ */
+static int32_t * func_65(int8_t p_66, uint16_t p_67, uint8_t p_68, int32_t * p_69, uint32_t * p_70)
+{ /* block id: 647 */
+ int32_t *l_1342 = &g_1132;
+ int8_t *l_1361 = &g_36;
+ uint16_t *l_1362[3][5][2] = {{{&g_969,&g_969},{&g_969,&g_969},{&g_969,&g_969},{&g_969,&g_969},{&g_969,&g_969}},{{&g_969,&g_969},{&g_969,&g_969},{&g_969,&g_969},{&g_969,&g_969},{&g_969,&g_969}},{{&g_969,&g_969},{&g_969,&g_969},{&g_969,(void*)0},{&g_969,&g_969},{&g_251,&g_251}}};
+ int32_t l_1363[2];
+ uint32_t *l_1375[6][5] = {{(void*)0,&g_477,&g_1099,&g_1099,&g_477},{(void*)0,&g_294[0],&g_1099,&g_477,&g_1334},{&g_294[0],&g_1099,&g_1099,(void*)0,&g_1099},{&g_1334,&g_1334,&g_1099,(void*)0,(void*)0},{&g_294[0],(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,&g_294[2],(void*)0,(void*)0,&g_1334}};
+ int32_t l_1376 = 1L;
+ uint32_t l_1379 = 0xCFCA353CL;
+ const uint32_t **l_1382 = (void*)0;
+ const uint32_t ***l_1381 = &l_1382;
+ const uint32_t ****l_1380[2][1][7] = {{{(void*)0,&l_1381,&l_1381,&l_1381,(void*)0,&l_1381,&l_1381}},{{(void*)0,&l_1381,&l_1381,&l_1381,(void*)0,&l_1381,&l_1381}}};
+ const uint32_t ***l_1383 = &l_1382;
+ int i, j, k;
+ for (i = 0; i < 2; i++)
+ l_1363[i] = 0xABF6ADA9L;
+ (*l_1342) ^= (*g_143);
+ if (g_140)
+ goto lbl_1364;
+ p_69 = func_94((**g_735), (*l_1342), (((((((safe_div_func_int32_t_s_s((safe_mul_func_uint16_t_u_u((safe_rshift_func_int16_t_s_u(p_66, (0xC741L && (((safe_div_func_int8_t_s_s((((safe_mul_func_uint8_t_u_u(0xD3L, (safe_rshift_func_int16_t_s_s((safe_add_func_uint16_t_u_u(((0L > (*g_289)) & (((l_1363[0] = ((p_68 = (safe_mul_func_uint8_t_u_u((((*l_1361) = ((((**g_176) = (safe_mod_func_int16_t_s_s(((((***g_735) , 0x0EL) >= (*l_1342)) || (*g_289)), p_68))) <= 0x01L) < (*l_1342))) , (*l_1342)), p_68))) != 0xDAL)) != p_66) == (*l_1342))), (***g_1184))), 10)))) & 0xF1L) != 249UL), (*l_1342))) != (***g_1184)) > 0x40L)))), (*l_1342))), (*p_70))) , (void*)0) == l_1361) <= g_1099) < (*l_1342)) < (*l_1342)) , (*g_143)), (*l_1342), (*l_1342));
+lbl_1364:
+ (*g_143) = (+(*l_1342));
+ (*g_143) = (1UL == (((safe_rshift_func_int8_t_s_u((safe_lshift_func_int8_t_s_s(((void*)0 != (*g_905)), (3UL != ((safe_rshift_func_int8_t_s_s(((l_1383 = ((((safe_div_func_uint32_t_u_u((p_66 <= (*l_1342)), (l_1376 = (++(*p_70))))) == g_251) && (g_34 <= (p_67 = (((*l_1342) = (safe_sub_func_int16_t_s_s((((((*l_1342) || (-1L)) != (*l_1342)) == l_1379) <= p_67), 0xD1CDL))) & l_1376)))) , (void*)0)) != (void*)0), 0)) != p_68)))), p_66)) ^ 65535UL) || 1UL));
+ return p_69;
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_51 g_44 g_251 g_143 g_140 g_176 g_43 g_705 g_289 g_290 g_297 g_255 g_55 g_56 g_36 g_34 g_131 g_132 g_243 g_347 g_320 g_736 g_294 g_175 g_897 g_905 g_735 g_960 g_969 g_961 g_312 g_1334
+ * writes: g_36 g_255 g_297 g_140 g_312 g_294 g_51 g_34 g_56 g_44 g_347 g_290 g_897 g_904 g_419 g_251 g_969 g_1334
+ */
+static uint8_t * func_71(uint32_t p_72, int8_t p_73)
+{ /* block id: 19 */
+ int32_t *l_75 = &g_51[0][3][1];
+ int32_t *l_76 = &g_51[0][2][2];
+ int32_t *l_77 = &g_51[0][7][1];
+ int32_t *l_78 = &g_51[0][3][1];
+ int32_t *l_79 = &g_51[0][5][2];
+ int32_t *l_80 = &g_51[0][0][0];
+ int32_t *l_81 = &g_51[1][3][1];
+ int32_t *l_82 = &g_51[1][0][1];
+ int32_t *l_83 = &g_51[0][3][1];
+ int32_t *l_84 = (void*)0;
+ int32_t l_85[9][2][7] = {{{(-4L),(-7L),0x7DDA0CFDL,(-8L),0x77CB2DEBL,0x5D6CB7F0L,0L},{0x9A3785E6L,0x69DBBC94L,(-10L),0x74D9FAD1L,(-10L),0x69DBBC94L,0x9A3785E6L}},{{0x5D6CB7F0L,0x6F9888A1L,1L,0x139E91ECL,0xC7048B0AL,0xFEAE78DFL,0x4ABCDCAFL},{(-10L),(-8L),(-1L),3L,0x74D9FAD1L,4L,0x204C5B33L}},{{0x7DDA0CFDL,4L,1L,7L,0x6F9888A1L,7L,1L},{0xB031E64CL,0xB031E64CL,(-10L),1L,0x2DE0ECACL,0x40782372L,0x501D8DD5L}},{{0x6F9888A1L,0x24FAE1B8L,0x7DDA0CFDL,1L,0x4ABCDCAFL,4L,(-7L)},{(-1L),0xEF1A95A0L,0x40782372L,0x53E6AFD1L,0x2DE0ECACL,1L,0x2DE0ECACL}},{{0L,0x4ABCDCAFL,0x4ABCDCAFL,0L,0x6F9888A1L,(-1L),0xE2E886BEL},{0x53E6AFD1L,0x40782372L,0xEF1A95A0L,(-1L),0x74D9FAD1L,0x204C5B33L,1L}},{{1L,0x7DDA0CFDL,0x24FAE1B8L,0x6F9888A1L,0xC7048B0AL,(-4L),0xE2E886BEL},{1L,(-10L),0xB031E64CL,0xB031E64CL,(-10L),1L,0x2DE0ECACL}},{{7L,1L,4L,0x7DDA0CFDL,0x77CB2DEBL,(-1L),(-7L)},{3L,(-1L),(-8L),(-10L),0x53E6AFD1L,0x9A3785E6L,0x501D8DD5L}},{{0x139E91ECL,1L,0x6F9888A1L,0x5D6CB7F0L,0x5D6CB7F0L,0x6F9888A1L,1L},{0x74D9FAD1L,(-10L),0x69DBBC94L,0x9A3785E6L,0x75422B1FL,(-1L),0x204C5B33L}},{{(-8L),0x7DDA0CFDL,(-7L),(-4L),(-1L),0xA96CD894L,0x4ABCDCAFL},{0x69DBBC94L,0x40782372L,0x204C5B33L,0x9A3785E6L,(-8L),(-8L),0x9A3785E6L}}};
+ int32_t *l_86 = &l_85[0][1][0];
+ int32_t *l_87 = (void*)0;
+ int32_t *l_88 = &l_85[1][1][4];
+ int32_t *l_89 = &g_51[0][3][1];
+ int32_t *l_90[3][9] = {{(void*)0,(void*)0,&g_51[0][5][2],(void*)0,(void*)0,&g_51[0][5][2],(void*)0,(void*)0,&g_51[0][5][2]},{&g_3,&g_3,(void*)0,&g_3,&g_3,(void*)0,&g_51[0][3][1],&g_51[0][3][1],&g_3},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0}};
+ uint8_t l_91[9][7][4] = {{{0x14L,253UL,255UL,0x88L},{0x51L,0x35L,0x0BL,254UL},{0xC0L,255UL,1UL,0x5BL},{253UL,0x8DL,0x88L,0x2BL},{0xD1L,0x2CL,0UL,0x01L},{0x9AL,0xD1L,0x35L,0x80L},{0x16L,0x3AL,0x9AL,0x39L}},{{6UL,1UL,0xF3L,0UL},{0x51L,1UL,0x4FL,1UL},{1UL,0x01L,0x50L,0xE4L},{0x30L,0x9AL,1UL,0UL},{0x93L,0x2CL,0x2CL,0x93L},{255UL,1UL,0xA9L,255UL},{4UL,2UL,0x4CL,0x88L}},{{0x5BL,254UL,0xF3L,0x88L},{0UL,2UL,1UL,255UL},{0xDFL,1UL,0x24L,0x93L},{0x23L,0x2CL,0x41L,0UL},{0xD1L,0x9AL,4UL,0xE4L},{0x16L,0x01L,0x23L,1UL},{0x2CL,1UL,248UL,0UL}},{{0x5BL,1UL,255UL,0x39L},{1UL,0x3AL,0x50L,0x80L},{0x80L,0xD1L,0x16L,0x01L},{0x5EL,0x2CL,1UL,0x2BL},{0xE4L,0x8DL,0xF0L,0x5BL},{4UL,255UL,0x51L,254UL},{0x4CL,0x35L,248UL,0x88L}},{{6UL,253UL,0UL,255UL},{253UL,0xF9L,0x24L,0x4DL},{248UL,6UL,0UL,0x01L},{0x23L,0x9AL,0x88L,5UL},{4UL,0UL,0x9AL,1UL},{0x2CL,0x14L,0xEBL,248UL},{0x4CL,1UL,0x4CL,0x39L}},{{0x14L,0xFDL,254UL,251UL},{0x30L,0x23L,0x16L,0xFDL},{0x4DL,6UL,0x16L,0x93L},{0x30L,0x8DL,254UL,0x4FL},{0x14L,0x30L,0x4CL,0xB0L},{0x4CL,0xB0L,0xEBL,254UL},{0x2CL,2UL,0x9AL,255UL}},{{4UL,1UL,0x88L,0x16L},{0x23L,0UL,0UL,0xFDL},{248UL,0xD1L,0x24L,0x8DL},{0xA2L,0xC0L,0x24L,2UL},{0x6AL,0x80L,0xDFL,4UL},{0xFDL,255UL,0x2CL,253UL},{0x80L,0xD2L,255UL,0UL}},{{0x8DL,0x88L,0x2BL,0x16L},{0xA5L,0xF0L,0x5EL,0UL},{0x39L,0x30L,0xEBL,0UL},{0x04L,1UL,0UL,1UL},{0UL,1UL,0xDFL,4UL},{0x4DL,0xF0L,1UL,0x41L},{255UL,1UL,1UL,1UL}},{{4UL,0x16L,0x16L,0x16L},{1UL,1UL,1UL,0x39L},{255UL,0x2CL,0x35L,0x30L},{0xF0L,0x80L,250UL,0x35L},{0UL,0x80L,0xFDL,0x30L},{0x80L,0x2CL,1UL,0x39L},{1UL,1UL,0x4DL,0x16L}}};
+ uint32_t *l_115[8] = {&g_56,&g_56,&g_56,&g_56,&g_56,&g_56,&g_56,&g_56};
+ int8_t *l_118 = &g_36;
+ int8_t **l_119 = &l_118;
+ int8_t *l_121 = &g_36;
+ int8_t **l_120 = &l_121;
+ int8_t **l_122 = (void*)0;
+ int8_t *l_124 = &g_36;
+ int8_t **l_123 = &l_124;
+ int8_t *l_126 = &g_36;
+ int8_t **l_125 = &l_126;
+ int8_t *l_127[7][8][4] = {{{&g_36,&g_36,&g_36,&g_36},{(void*)0,&g_36,&g_36,&g_36},{(void*)0,(void*)0,&g_36,&g_36},{(void*)0,(void*)0,(void*)0,(void*)0},{&g_36,&g_36,&g_36,(void*)0},{(void*)0,&g_36,&g_36,(void*)0},{&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,(void*)0}},{{(void*)0,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36},{(void*)0,&g_36,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36}},{{&g_36,&g_36,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36},{&g_36,&g_36,&g_36,(void*)0},{&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36},{(void*)0,&g_36,&g_36,(void*)0},{&g_36,&g_36,&g_36,(void*)0},{&g_36,&g_36,&g_36,&g_36}},{{&g_36,(void*)0,&g_36,(void*)0},{&g_36,&g_36,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36},{(void*)0,(void*)0,&g_36,&g_36},{&g_36,&g_36,(void*)0,&g_36},{&g_36,(void*)0,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36},{&g_36,&g_36,(void*)0,&g_36}},{{(void*)0,&g_36,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36},{(void*)0,&g_36,(void*)0,&g_36},{&g_36,&g_36,&g_36,&g_36},{&g_36,(void*)0,(void*)0,&g_36},{&g_36,(void*)0,(void*)0,(void*)0},{&g_36,&g_36,&g_36,&g_36}},{{&g_36,&g_36,&g_36,&g_36},{(void*)0,&g_36,(void*)0,(void*)0},{&g_36,(void*)0,&g_36,&g_36},{(void*)0,(void*)0,(void*)0,&g_36},{&g_36,&g_36,&g_36,&g_36},{(void*)0,&g_36,(void*)0,&g_36},{(void*)0,&g_36,&g_36,&g_36},{&g_36,(void*)0,(void*)0,&g_36}},{{&g_36,&g_36,(void*)0,&g_36},{&g_36,&g_36,&g_36,&g_36},{(void*)0,(void*)0,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36},{&g_36,&g_36,&g_36,(void*)0},{&g_36,&g_36,&g_36,&g_36}}};
+ int8_t *l_129 = &g_36;
+ int8_t **l_128 = &l_129;
+ int8_t *l_130[4][2] = {{(void*)0,(void*)0},{(void*)0,(void*)0},{(void*)0,(void*)0},{(void*)0,(void*)0}};
+ int32_t l_690 = (-1L);
+ int i, j, k;
+ ++l_91[2][2][0];
+ (*g_961) = func_94(&g_56, ((g_51[1][1][2] >= func_100(func_105(((g_44 ^ ((g_44 , (safe_sub_func_int8_t_s_s((g_36 = (safe_add_func_uint8_t_u_u((safe_sub_func_int8_t_s_s(((*l_86) |= (((~(&g_56 != l_115[6])) , (((((safe_rshift_func_uint16_t_u_u(1UL, 14)) < ((((l_127[6][3][0] = ((*l_125) = ((*l_123) = ((*l_120) = ((*l_119) = l_118))))) == ((*l_128) = &p_73)) ^ 255UL) == p_73)) == 0xCAL) && 8L) ^ 0x2359L)) , p_72)), p_72)), g_51[1][2][0]))), 0xA4L))) == 6UL)) < 0xD5L)), l_690, (*l_79), g_251)) <= 255UL), p_72, (*l_77), p_73);
+ return (**g_905);
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_36 g_176 g_43 g_44 g_297 g_143 g_140 g_51 g_705 g_34 g_131 g_132 g_55 g_56 g_243 g_289 g_347 g_320 g_736 g_294 g_175 g_255 g_897 g_905 g_290 g_735 g_251 g_960 g_969 g_961 g_312 g_1334
+ * writes: g_36 g_140 g_312 g_51 g_34 g_56 g_297 g_44 g_347 g_290 g_255 g_897 g_904 g_294 g_419 g_251 g_969 g_1334
+ */
+static int32_t * func_94(uint32_t * p_95, int32_t p_96, const int32_t p_97, int32_t p_98, int8_t p_99)
+{ /* block id: 395 */
+ int8_t l_778 = (-5L);
+ int32_t l_868[8] = {0xC949261DL,0xC949261DL,0xC949261DL,0xC949261DL,0xC949261DL,0xC949261DL,0xC949261DL,0xC949261DL};
+ int32_t l_885 = 0L;
+ int32_t l_891 = 0x3573B375L;
+ int16_t * const l_916 = &g_419;
+ uint8_t *** const l_948 = &g_175;
+ int32_t l_982 = (-1L);
+ uint32_t *l_983 = &g_294[4];
+ int32_t l_984 = 1L;
+ int8_t l_998 = 0L;
+ uint8_t ****l_1044[3];
+ uint8_t l_1256 = 3UL;
+ int16_t l_1325[10][7] = {{0x9403L,(-1L),0x5345L,0x2B69L,0x41E0L,0x8199L,0x8199L},{0x640AL,(-1L),0x93F5L,(-1L),0x640AL,0xF19AL,0x93F5L},{(-1L),0x9403L,(-1L),0x5345L,0x2B69L,0x41E0L,0x8199L},{0xD399L,1L,0x6F08L,0xF19AL,0x6F08L,1L,0xD399L},{(-1L),0x5345L,0x8199L,0x2B69L,0x9403L,0x23E0L,(-1L)},{0x640AL,1L,1L,8L,0x640AL,8L,1L},{0x9403L,0x9403L,0x8199L,(-1L),(-1L),0x41E0L,0x5345L},{0x6F08L,(-1L),0x6F08L,8L,0xD399L,(-1L),0xD399L},{0x2B69L,(-1L),(-1L),0x2B69L,(-1L),0x8199L,0x23E0L},{0x640AL,0xF19AL,0x93F5L,0xF19AL,0x640AL,(-1L),0x93F5L}};
+ int32_t *l_1339 = &g_51[1][1][1];
+ int i, j;
+ for (i = 0; i < 3; i++)
+ l_1044[i] = &g_905;
+ for (g_36 = 0; (g_36 <= (-2)); --g_36)
+ { /* block id: 398 */
+ if (l_778)
+ break;
+ }
+ (*g_143) = ((safe_mod_func_int32_t_s_s((safe_sub_func_uint8_t_u_u(l_778, (**g_176))), (safe_div_func_int16_t_s_s((-1L), (safe_add_func_int16_t_s_s(((void*)0 == &p_95), p_99)))))) , (safe_mul_func_int8_t_s_s(((safe_div_func_uint16_t_u_u((((safe_add_func_int32_t_s_s(p_96, 4294967286UL)) >= 0xB233L) && p_99), g_297[1])) & p_96), 0xFEL)));
+ for (g_36 = 1; (g_36 >= 0); g_36 -= 1)
+ { /* block id: 404 */
+ int16_t l_806[2];
+ int32_t l_814 = (-9L);
+ uint8_t *l_846[6][2][10] = {{{&g_40[1],&g_44,&g_320,&g_44,(void*)0,(void*)0,(void*)0,(void*)0,&g_320,(void*)0},{&g_40[0],&g_44,(void*)0,&g_40[1],&g_320,&g_40[5],&g_40[5],&g_320,&g_40[1],(void*)0}},{{(void*)0,(void*)0,&g_320,&g_320,&g_40[0],&g_40[3],(void*)0,&g_40[1],&g_44,&g_320},{&g_320,&g_40[1],&g_44,(void*)0,&g_40[1],&g_44,(void*)0,(void*)0,&g_40[6],&g_40[5]}},{{&g_40[5],(void*)0,&g_40[1],&g_40[1],&g_320,&g_320,&g_40[5],&g_40[5],&g_40[5],&g_40[1]},{(void*)0,&g_44,(void*)0,&g_44,&g_40[2],&g_40[5],(void*)0,&g_44,(void*)0,&g_40[1]}},{{(void*)0,&g_44,&g_40[0],(void*)0,&g_40[1],(void*)0,&g_40[0],&g_44,(void*)0,(void*)0},{&g_40[1],&g_40[1],&g_320,&g_44,&g_40[0],(void*)0,&g_44,(void*)0,&g_44,(void*)0}},{{&g_40[0],&g_320,(void*)0,&g_44,&g_40[6],&g_320,(void*)0,&g_40[3],(void*)0,&g_320},{(void*)0,(void*)0,&g_40[5],(void*)0,&g_40[1],&g_40[6],&g_40[1],&g_320,(void*)0,&g_44}},{{&g_40[2],&g_320,&g_320,&g_44,&g_40[3],&g_320,&g_44,&g_40[5],&g_40[5],&g_44},{(void*)0,(void*)0,&g_40[1],&g_40[1],(void*)0,(void*)0,(void*)0,&g_40[0],&g_40[6],(void*)0}}};
+ int32_t l_870 = 0x0B9A60E1L;
+ int32_t l_872 = (-5L);
+ int32_t l_879 = 0x68AC52C0L;
+ int32_t l_880 = 1L;
+ int32_t l_882 = (-3L);
+ int32_t l_883 = 0x329F4C9FL;
+ int32_t l_884 = (-2L);
+ int32_t l_887 = 0x1D6C2448L;
+ int32_t l_888[9];
+ uint8_t ***l_903 = &g_175;
+ uint8_t ****l_902[5][1] = {{&l_903},{&l_903},{&l_903},{&l_903},{&l_903}};
+ int8_t **l_919 = &g_243[1][0][1];
+ int i, j, k;
+ for (i = 0; i < 2; i++)
+ l_806[i] = 0xDFCAL;
+ for (i = 0; i < 9; i++)
+ l_888[i] = 0xAEB8A862L;
+ for (g_140 = 0; (g_140 <= 1); g_140 += 1)
+ { /* block id: 407 */
+ const uint16_t l_807 = 0UL;
+ int32_t *l_809 = (void*)0;
+ int32_t *l_864 = &g_297[1];
+ int32_t l_867 = 0xB4D5446DL;
+ int32_t l_869 = 1L;
+ int32_t l_871 = 0L;
+ int32_t l_873 = (-1L);
+ int8_t l_874 = 1L;
+ int32_t l_875 = 0x566BCB73L;
+ int32_t l_876 = 0x640B2514L;
+ int32_t l_877 = (-10L);
+ int32_t l_878 = 0L;
+ int32_t l_881[1][2][1];
+ int32_t l_890 = (-10L);
+ int i, j, k;
+ for (i = 0; i < 1; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ for (k = 0; k < 1; k++)
+ l_881[i][j][k] = (-1L);
+ }
+ }
+ for (p_98 = 0; (p_98 <= 1); p_98 += 1)
+ { /* block id: 410 */
+ uint16_t *l_837[7][2][10] = {{{&g_251,(void*)0,&g_251,(void*)0,&g_251,&g_251,&g_251,(void*)0,&g_251,(void*)0},{(void*)0,&g_251,&g_251,&g_251,(void*)0,&g_251,&g_251,&g_251,&g_251,&g_251}},{{&g_251,&g_251,&g_251,(void*)0,&g_251,&g_251,&g_251,(void*)0,&g_251,&g_251},{(void*)0,&g_251,&g_251,(void*)0,&g_251,&g_251,(void*)0,&g_251,&g_251,&g_251}},{{&g_251,&g_251,(void*)0,&g_251,(void*)0,&g_251,&g_251,&g_251,&g_251,(void*)0},{(void*)0,&g_251,&g_251,(void*)0,&g_251,&g_251,&g_251,(void*)0,&g_251,(void*)0}},{{&g_251,&g_251,&g_251,&g_251,(void*)0,(void*)0,&g_251,&g_251,&g_251,(void*)0},{(void*)0,&g_251,(void*)0,&g_251,&g_251,(void*)0,&g_251,(void*)0,(void*)0,&g_251}},{{&g_251,&g_251,&g_251,(void*)0,&g_251,&g_251,&g_251,&g_251,&g_251,&g_251},{(void*)0,&g_251,&g_251,&g_251,&g_251,&g_251,(void*)0,&g_251,(void*)0,&g_251}},{{&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,(void*)0,&g_251},{&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,(void*)0,&g_251,&g_251,(void*)0}},{{&g_251,&g_251,&g_251,&g_251,&g_251,(void*)0,&g_251,(void*)0,&g_251,&g_251},{&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,&g_251}}};
+ int32_t l_848 = (-7L);
+ uint8_t *l_856 = &g_40[0];
+ int32_t *l_860 = &l_848;
+ int i, j, k;
+ g_312[0][0][5] = (void*)0;
+ g_51[g_36][(p_98 + 1)][g_140] ^= 0x87124F79L;
+ for (g_34 = 0; (g_34 <= 1); g_34 += 1)
+ { /* block id: 415 */
+ uint32_t l_805[5];
+ int32_t *l_808 = &g_297[1];
+ int i, j, k;
+ for (i = 0; i < 5; i++)
+ l_805[i] = 0UL;
+ (*l_808) ^= (((safe_mod_func_int32_t_s_s((!(~((g_51[g_36][g_140][g_36] != (g_705[p_98] && ((*g_55) |= ((g_705[(g_34 + 3)] <= ((safe_add_func_int16_t_s_s(g_705[(g_34 + 3)], (safe_sub_func_int32_t_s_s((2UL != ((safe_sub_func_int8_t_s_s(p_98, p_97)) , (safe_mul_func_int16_t_s_s((safe_add_func_int8_t_s_s((((g_51[0][3][1] < l_778) || l_805[0]) > (*g_143)), (**g_131))), l_806[0])))), l_778)))) > 0x76L)) & g_34)))) | l_807))), p_96)) > l_778) ^ p_99);
+ l_809 = &p_98;
+ }
+ for (p_96 = 0; (p_96 <= 1); p_96 += 1)
+ { /* block id: 422 */
+ uint8_t l_847 = 1UL;
+ int i, j, k;
+ if (g_51[p_98][(g_36 + 5)][g_140])
+ break;
+ l_814 = ((safe_mul_func_uint16_t_u_u(0x9540L, 65535UL)) <= (++(*g_43)));
+ for (g_347 = 4; (g_347 >= 0); g_347 -= 1)
+ { /* block id: 428 */
+ int8_t *l_851 = &g_255;
+ int32_t *l_859 = &g_297[1];
+ int i, j, k;
+ l_848 = (safe_rshift_func_int16_t_s_s((-1L), ((safe_mod_func_uint32_t_u_u(((g_51[g_140][(g_140 + 5)][g_140] = (safe_sub_func_int8_t_s_s((((safe_div_func_uint32_t_u_u(g_51[g_140][(g_36 + 2)][(g_140 + 1)], 2L)) <= (safe_unary_minus_func_uint32_t_u((safe_sub_func_int8_t_s_s((((safe_rshift_func_int8_t_s_s(((safe_add_func_int8_t_s_s((p_98 ^ (safe_add_func_int16_t_s_s((safe_sub_func_int16_t_s_s((safe_mul_func_uint8_t_u_u((((~(safe_unary_minus_func_int8_t_s((((((&g_251 == l_837[2][0][1]) ^ ((-1L) == ((*g_289) = (safe_lshift_func_uint16_t_u_s((l_814 = ((safe_lshift_func_int16_t_s_u(g_51[g_140][(g_36 + 2)][(g_140 + 1)], 13)) >= (safe_sub_func_uint8_t_u_u(((safe_div_func_int8_t_s_s((((g_243[(g_36 + 1)][g_36][(p_96 + 3)] == l_846[0][1][8]) == 0xC75DL) <= g_51[g_140][(g_36 + 2)][(g_140 + 1)]), g_51[p_98][(g_36 + 5)][g_140])) | p_99), 255UL)))), p_98))))) > l_847) , l_778) < 0x4EDBL)))) | g_347) != l_778), (*g_132))), g_51[p_98][(g_36 + 5)][g_140])), 0x4155L))), (*g_43))) <= (-4L)), 4)) < g_320) <= p_97), 0x7DL))))) | 0xE6F3L), p_96))) && (**g_736)), 1UL)) | 0x59L)));
+ if (p_97)
+ break;
+ (*l_859) ^= ((*p_95) && (((safe_div_func_int8_t_s_s(((*l_851) = (g_294[0] >= 0x74B3L)), ((**g_175) = (**g_176)))) , (safe_sub_func_uint8_t_u_u(((!(l_814 = (safe_mod_func_int8_t_s_s(((*l_851) ^= (l_856 == (void*)0)), (p_99 = (safe_lshift_func_int16_t_s_u(g_51[g_140][(g_140 + 5)][g_140], 2))))))) > g_51[g_36][(p_98 + 1)][g_140]), l_778))) , 0UL));
+ l_860 = &l_814;
+ }
+ for (g_56 = 0; (g_56 <= 1); g_56 += 1)
+ { /* block id: 444 */
+ int32_t **l_861 = &l_809;
+ (*l_861) = &g_51[0][3][1];
+ if (p_99)
+ break;
+ }
+ }
+ }
+ (*l_864) = (((l_806[0] , (safe_lshift_func_uint8_t_u_u((p_97 ^ 0UL), 2))) & (~1UL)) == (**g_736));
+ for (p_98 = 1; (p_98 >= 0); p_98 -= 1)
+ { /* block id: 453 */
+ int32_t *l_865 = &l_814;
+ int32_t *l_866[5];
+ int16_t l_886[3];
+ int32_t l_889 = 0xF193AD92L;
+ uint32_t l_892 = 4294967295UL;
+ uint16_t *l_920 = &g_251;
+ uint32_t l_931 = 4UL;
+ const uint8_t *l_951[4];
+ const uint8_t **l_950 = &l_951[3];
+ const uint8_t *** const l_949 = &l_950;
+ int32_t ***l_962[9] = {&g_961,&g_961,&g_961,&g_961,&g_961,&g_961,&g_961,&g_961,&g_961};
+ int i;
+ for (i = 0; i < 5; i++)
+ l_866[i] = (void*)0;
+ for (i = 0; i < 3; i++)
+ l_886[i] = 0x4E3AL;
+ for (i = 0; i < 4; i++)
+ l_951[i] = (void*)0;
+ l_892--;
+ for (l_877 = 4; (l_877 >= 0); l_877 -= 1)
+ { /* block id: 457 */
+ uint8_t *****l_898 = (void*)0;
+ uint8_t *****l_899 = (void*)0;
+ uint8_t *****l_900 = (void*)0;
+ uint8_t *****l_901 = (void*)0;
+ int32_t l_929 = 0x9F81C2E6L;
+ int32_t l_930[6];
+ uint32_t l_954 = 0UL;
+ int i, j, k;
+ for (i = 0; i < 6; i++)
+ l_930[i] = 0xF1E80E14L;
+ if ((safe_rshift_func_uint16_t_u_s((&g_736 == &g_736), (((g_294[g_140] != g_294[p_98]) && (((1UL != (((g_897 = g_897) != (g_904[0][3] = l_902[0][0])) != ((*g_289) = (((g_294[(g_140 + 1)] = ((safe_mod_func_int16_t_s_s(((**g_131) , (((p_97 || l_882) != 0x37DD31F2L) | 0L)), p_97)) || (*g_143))) ^ (*l_865)) , 1L)))) == (***g_905)) , (*g_289))) ^ (-7L)))))
+ { /* block id: 462 */
+ uint16_t l_921 = 1UL;
+ int32_t l_922 = 0xB991C690L;
+ l_922 &= (safe_rshift_func_int8_t_s_u((((safe_div_func_uint8_t_u_u((((l_921 = (((((safe_lshift_func_uint8_t_u_u((1UL != (((safe_rshift_func_uint8_t_u_s((((void*)0 == l_916) == 0xDFCCF46BL), (((((*l_864) | ((p_99 = ((l_920 = (((l_868[1] , l_919) != &g_243[(p_98 + 3)][g_36][(p_98 + 6)]) , (void*)0)) == (void*)0)) <= g_294[(g_140 + 1)])) & 3UL) <= (***g_735)) || (**g_736)))) <= (***g_905)) > g_294[(g_140 + 1)])), p_98)) == (*g_289)) < g_51[0][3][1]) | p_98) , (**g_175))) < 0x64L) < l_814), l_888[1])) , (-4L)) , l_868[6]), 1));
+ }
+ else
+ { /* block id: 467 */
+ uint8_t l_923 = 0xE8L;
+ int32_t l_926 = (-9L);
+ int32_t l_927 = 8L;
+ int32_t l_928 = (-1L);
+ --l_923;
+ if (p_96)
+ continue;
+ l_931++;
+ }
+ (*l_864) = (safe_sub_func_uint8_t_u_u((((*l_865) = (((safe_div_func_uint8_t_u_u(((safe_mod_func_uint16_t_u_u(0xDC88L, (safe_rshift_func_int16_t_s_s(((0UL ^ (-6L)) > p_97), ((safe_add_func_uint16_t_u_u(l_868[6], (safe_add_func_int16_t_s_s((safe_rshift_func_uint8_t_u_s((l_948 == l_949), ((safe_sub_func_int16_t_s_s((l_954 > ((&g_289 != (void*)0) & g_140)), 0x0045L)) > 0UL))), 0xB58DL)))) < (*g_289)))))) < (***g_735)), l_868[6])) != p_98) | p_99)) & (*g_55)), 0x4AL));
+ (*l_864) &= 0xD1CAA0FBL;
+ }
+ for (l_778 = 1; (l_778 >= 0); l_778 -= 1)
+ { /* block id: 478 */
+ int16_t *l_959 = &l_806[1];
+ int32_t l_965 = (-8L);
+ int8_t *l_966 = &g_255;
+ uint16_t *l_967 = &g_251;
+ uint16_t *l_968 = &g_969;
+ int i, j, k;
+ (*l_864) = (p_96 |= l_888[6]);
+ p_96 = (((6UL <= ((safe_mod_func_int8_t_s_s((g_251 , (((*g_289) <= (safe_mod_func_int16_t_s_s(((*l_959) &= ((*l_916) = 0x3137L)), (((g_960 != l_962[4]) , ((*l_968) &= ((*l_967) = ((((safe_add_func_uint16_t_u_u(0xEADCL, ((((((*l_966) &= (l_965 == l_879)) == 0xA5L) , p_96) >= p_96) ^ (*p_95)))) , 5UL) & (*g_143)) , p_99)))) , (*g_289))))) ^ (**g_176))), 3L)) == (*g_55))) && (**g_131)) <= p_97);
+ }
+ }
+ }
+ if (l_868[6])
+ break;
+ }
+ if ((p_98 = (safe_mod_func_int16_t_s_s((*g_289), (safe_add_func_uint32_t_u_u(((l_984 = (0x4C7D768FL <= ((*l_983) ^= (safe_mul_func_int8_t_s_s(((**g_736) || (l_982 &= ((p_98 == (safe_sub_func_uint32_t_u_u((((l_948 == l_948) | (safe_lshift_func_int8_t_s_s((0x454BL <= l_868[3]), 0))) ^ ((safe_lshift_func_uint8_t_u_s((!255UL), 0)) <= l_885)), (*p_95)))) || (*g_55)))), 0x15L))))) & l_778), (*p_95)))))))
+ { /* block id: 496 */
+ uint8_t ***l_993 = &g_175;
+ int16_t l_999 = 0x1B88L;
+ int8_t *** const *l_1034 = &g_1019[1][0][0];
+ int32_t *l_1046 = &l_982;
+ int32_t l_1048[1][2][7] = {{{0xEA46108CL,0xEA46108CL,0xEA46108CL,0xEA46108CL,0xEA46108CL,0xEA46108CL,0xEA46108CL},{(-1L),(-1L),(-1L),(-1L),(-1L),(-1L),(-1L)}}};
+ uint32_t l_1093[3];
+ uint16_t l_1131 = 0xE112L;
+ int16_t **l_1135[6][2][5] = {{{&g_289,&g_289,&g_289,&g_289,(void*)0},{&g_289,&g_289,&g_289,&g_289,&g_289}},{{&g_289,(void*)0,&g_289,(void*)0,&g_289},{&g_289,&g_289,&g_289,(void*)0,(void*)0}},{{&g_289,(void*)0,(void*)0,&g_289,&g_289},{&g_289,(void*)0,(void*)0,&g_289,(void*)0}},{{(void*)0,&g_289,&g_289,&g_289,&g_289},{(void*)0,&g_289,(void*)0,&g_289,&g_289}},{{&g_289,&g_289,&g_289,&g_289,(void*)0},{&g_289,&g_289,&g_289,&g_289,&g_289}},{{&g_289,&g_289,&g_289,(void*)0,(void*)0},{&g_289,(void*)0,(void*)0,(void*)0,(void*)0}}};
+ int32_t l_1180 = 0L;
+ uint8_t l_1276[9];
+ int32_t *l_1294 = &g_1132;
+ int32_t *l_1320 = &g_51[0][3][1];
+ int32_t *l_1321 = &g_140;
+ int32_t *l_1322 = &g_297[1];
+ int32_t *l_1323 = &l_1048[0][1][0];
+ int32_t *l_1324[1];
+ int16_t l_1326 = 0x2195L;
+ int32_t l_1327 = 0x947976B8L;
+ uint16_t l_1328 = 0x24D6L;
+ int i, j, k;
+ for (i = 0; i < 3; i++)
+ l_1093[i] = 1UL;
+ for (i = 0; i < 9; i++)
+ l_1276[i] = 255UL;
+ for (i = 0; i < 1; i++)
+ l_1324[i] = &l_1048[0][0][6];
+ for (g_44 = 0; (g_44 <= 6); g_44 += 1)
+ { /* block id: 499 */
+ uint8_t ***l_994 = &g_175;
+ int8_t l_997 = 0xA6L;
+ int8_t ***l_1017 = &g_245;
+ int8_t ****l_1016 = &l_1017;
+ int32_t l_1050 = 0xF31EAA3DL;
+ int32_t l_1051 = 0x0917F34DL;
+ int32_t l_1056 = 0x36E77B1BL;
+ int32_t l_1057 = 0x4D998F65L;
+ int8_t l_1113 = 0x9DL;
+ uint32_t l_1114[6];
+ int32_t l_1168 = 0xF8E5B00AL;
+ int32_t l_1170 = 0x729BDDB8L;
+ int32_t l_1171 = 1L;
+ int32_t l_1172 = (-1L);
+ int32_t l_1173 = 0L;
+ int32_t l_1176[5][7][6] = {{{0xBDCB05A3L,0L,0xCD8737B6L,0L,0xBDCB05A3L,0xC7DD3347L},{0L,0xBDCB05A3L,0xC7DD3347L,0xC7DD3347L,0xBDCB05A3L,0L},{(-6L),0L,0xF426EDDCL,0xBDCB05A3L,0xF426EDDCL,0L},{0xF426EDDCL,(-6L),0xC7DD3347L,0xCD8737B6L,0xCD8737B6L,0xCD8737B6L},{0xA0CC386BL,0xA0CC386BL,0xF426EDDCL,0xC7DD3347L,0L,0xC7DD3347L},{0xBDCB05A3L,0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL},{(-6L),0xBDCB05A3L,0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L}},{{0xC7DD3347L,(-6L),0xF426EDDCL,(-6L),0xC7DD3347L,0xCD8737B6L},{(-6L),0xC7DD3347L,0xCD8737B6L,0xCD8737B6L,0xC7DD3347L,(-6L)},{0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L,0xA0CC386BL,(-6L)},{0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL,0xCD8737B6L},{0xA0CC386BL,0xA0CC386BL,0xF426EDDCL,0xC7DD3347L,0L,0xC7DD3347L},{0xBDCB05A3L,0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL},{(-6L),0xBDCB05A3L,0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L}},{{0xC7DD3347L,(-6L),0xF426EDDCL,(-6L),0xC7DD3347L,0xCD8737B6L},{(-6L),0xC7DD3347L,0xCD8737B6L,0xCD8737B6L,0xC7DD3347L,(-6L)},{0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L,0xA0CC386BL,(-6L)},{0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL,0xCD8737B6L},{0xA0CC386BL,0xA0CC386BL,0xF426EDDCL,0xC7DD3347L,0L,0xC7DD3347L},{0xBDCB05A3L,0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL},{(-6L),0xBDCB05A3L,0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L}},{{0xC7DD3347L,(-6L),0xF426EDDCL,(-6L),0xC7DD3347L,0xCD8737B6L},{(-6L),0xC7DD3347L,0xCD8737B6L,0xCD8737B6L,0xC7DD3347L,(-6L)},{0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L,0xA0CC386BL,(-6L)},{0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL,0xCD8737B6L},{0xA0CC386BL,0xA0CC386BL,0xF426EDDCL,0xC7DD3347L,0L,0xC7DD3347L},{0xBDCB05A3L,0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL},{(-6L),0xBDCB05A3L,0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L}},{{0xC7DD3347L,(-6L),0xF426EDDCL,(-6L),0xC7DD3347L,0xCD8737B6L},{(-6L),0xC7DD3347L,0xCD8737B6L,0xCD8737B6L,0xC7DD3347L,(-6L)},{0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L,0xA0CC386BL,(-6L)},{0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL,0xCD8737B6L},{0xA0CC386BL,0xA0CC386BL,0xF426EDDCL,0xC7DD3347L,0L,0xC7DD3347L},{0xBDCB05A3L,0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL},{(-6L),0xBDCB05A3L,0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L}}};
+ uint32_t l_1319 = 0x3CC17454L;
+ int i, j, k;
+ for (i = 0; i < 6; i++)
+ l_1114[i] = 1UL;
+ }
+ --l_1328;
+ (*g_143) ^= ((*g_960) == (void*)0);
+ return (**g_960);
+ }
+ else
+ { /* block id: 635 */
+ int32_t *l_1331 = &g_51[0][1][1];
+ int32_t *l_1332[6] = {&g_1055,&g_1055,&g_1055,&g_1055,&g_1055,&g_1055};
+ int i;
+ ++g_1334;
+ for (g_347 = 0; (g_347 == 26); g_347 = safe_add_func_uint16_t_u_u(g_347, 7))
+ { /* block id: 639 */
+ return (*g_961);
+ }
+ }
+ return l_1339;
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_143 g_140 g_176 g_43 g_44 g_705 g_289 g_290 g_297 g_255 g_55 g_56
+ * writes: g_255 g_297 g_140 g_312 g_294
+ */
+static int8_t func_100(int32_t * p_101, uint8_t p_102, uint8_t p_103, uint32_t p_104)
+{ /* block id: 323 */
+ int8_t ***l_692 = (void*)0;
+ int8_t ****l_691 = &l_692;
+ int32_t l_697 = 0xB23966F9L;
+ int32_t l_704 = 0x17C47AB5L;
+ int32_t l_712 = 0x92F85846L;
+ uint32_t l_724 = 1UL;
+ uint32_t l_754 = 0x40901257L;
+ uint32_t l_755[9][7] = {{0x3F92B650L,0x3F92B650L,0x59DA734BL,0x3F92B650L,0x3F92B650L,0x59DA734BL,0x3F92B650L},{0x1D3867C8L,4294967286UL,4294967295UL,5UL,4294967295UL,4294967286UL,0x1D3867C8L},{0xB66E3024L,0x3F92B650L,0xB66E3024L,0xB66E3024L,0x3F92B650L,0xB66E3024L,0xB66E3024L},{0x1D3867C8L,5UL,0x67201704L,5UL,0x1D3867C8L,4294967295UL,0x1D3867C8L},{0x3F92B650L,0xB66E3024L,0xB66E3024L,0x3F92B650L,0xB66E3024L,0xB66E3024L,0x3F92B650L},{4294967295UL,5UL,4294967295UL,4294967286UL,0x1D3867C8L,4294967286UL,4294967295UL},{0x3F92B650L,0x3F92B650L,0x59DA734BL,0x3F92B650L,0x3F92B650L,0x59DA734BL,0x3F92B650L},{0x1D3867C8L,4294967286UL,4294967295UL,5UL,4294967295UL,4294967286UL,0x1D3867C8L},{0xB66E3024L,0x3F92B650L,0xB66E3024L,0xB66E3024L,0x3F92B650L,0xB66E3024L,0xB66E3024L}};
+ int i, j;
+ if (((l_691 == &l_692) < (safe_mod_func_int16_t_s_s(((safe_mul_func_int16_t_s_s(((l_697 & (0UL != ((l_697 & ((0L ^ 0UL) <= (safe_mod_func_int32_t_s_s((*g_143), (safe_mod_func_uint8_t_u_u((safe_mul_func_uint8_t_u_u(((l_704 = (p_102 > l_697)) & (**g_176)), 0xD2L)), l_697)))))) && (-1L)))) , g_705[2]), (*g_289))) && l_697), (*g_289)))))
+ { /* block id: 325 */
+ int16_t l_715 = (-7L);
+ int8_t *l_716 = &g_255;
+ int8_t **l_717 = (void*)0;
+ (*g_143) ^= (safe_div_func_int8_t_s_s(((((safe_lshift_func_int8_t_s_u(((((0x7466BED0L && ((safe_rshift_func_int8_t_s_s(l_712, ((0x6627434EL > (safe_mod_func_int16_t_s_s(l_715, 0xA37DL))) == ((((~g_297[1]) & p_102) , ((*p_101) = (p_104 < ((*l_716) ^= l_715)))) > (*g_55))))) && p_102)) , l_704) >= 0x8C828013L) , 0x19L), 6)) > l_715) , l_717) == &l_716), 1UL));
+ return p_102;
+ }
+ else
+ { /* block id: 330 */
+ int32_t **l_718 = &g_312[1][0][5];
+ uint32_t *l_766 = &l_755[0][2];
+ (*l_718) = p_101;
+ for (p_103 = 25; (p_103 != 48); ++p_103)
+ { /* block id: 334 */
+ int8_t l_723[9][8][3] = {{{0x6BL,0L,0xCAL},{0xF4L,0xB1L,0x8BL},{0L,0L,0x53L},{0xBFL,0L,0x76L},{0xBFL,0x39L,0x1BL},{0L,1L,0xDFL},{0xF4L,0xBFL,0x1BL},{0x6BL,0x2AL,0x76L}},{{1L,0x2AL,0x53L},{1L,0xBFL,0x8BL},{0xA4L,1L,0xCAL},{1L,0x39L,0x10L},{1L,0L,0x10L},{0x6BL,0L,0xCAL},{0xF4L,0xB1L,0x8BL},{0L,0L,0x53L}},{{0xBFL,0L,0x76L},{0xBFL,0x39L,0x1BL},{0L,1L,0xDFL},{0xF4L,0xBFL,0x1BL},{0x6BL,0x2AL,0x76L},{1L,0x2AL,0x53L},{1L,0xBFL,0x8BL},{0xA4L,1L,0xCAL}},{{1L,0x39L,0x10L},{1L,0L,0x10L},{0x6BL,0L,0xCAL},{0xF4L,0xB1L,0x8BL},{0L,0L,0x53L},{0xBFL,0L,0x76L},{0xBFL,0x39L,0x1BL},{0L,1L,0xDFL}},{{0xF4L,0xBFL,0x1BL},{0x6BL,0x2AL,0x76L},{1L,0x2AL,0x53L},{1L,0xBFL,0x8BL},{0xA4L,1L,0xCAL},{1L,0x39L,0x10L},{1L,0L,0x10L},{0x6BL,0L,0xCAL}},{{0xF4L,0xB1L,0x8BL},{0L,0L,0x53L},{0x6FL,9L,0x6CL},{0x6FL,0xE5L,0L},{(-1L),0L,1L},{(-9L),0x6FL,0L},{0xE9L,1L,0x6CL},{0xC4L,1L,0xBFL}},{{0L,0x6FL,1L},{1L,0L,0xA4L},{0L,0xE5L,0xB1L},{0xC4L,9L,0xB1L},{0xE9L,(-1L),0xA4L},{(-9L),0x19L,1L},{(-1L),(-1L),0xBFL},{0x6FL,9L,0x6CL}},{{0x6FL,0xE5L,0L},{(-1L),0L,1L},{(-9L),0x6FL,0L},{0xE9L,1L,0x6CL},{0xC4L,1L,0xBFL},{0L,0x6FL,1L},{1L,0L,0xA4L},{0L,0xE5L,0xB1L}},{{0xC4L,9L,0xB1L},{0xE9L,(-1L),0xA4L},{(-9L),0x19L,1L},{(-1L),(-1L),0xBFL},{0x6FL,9L,0x6CL},{0x6FL,0xE5L,0L},{(-1L),0L,1L},{(-9L),0x6FL,0L}}};
+ int8_t ***l_761[10] = {&g_245,&g_245,&g_245,&g_245,&g_245,&g_245,&g_245,&g_245,&g_245,&g_245};
+ int i, j, k;
+ }
+ for (l_704 = 0; l_704 < 5; l_704 += 1)
+ {
+ g_294[l_704] = 1UL;
+ }
+ }
+ (*g_143) = (safe_div_func_int32_t_s_s((*g_143), l_704));
+ return l_697;
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads :
+ * writes:
+ */
+static int32_t * func_105(uint32_t p_106)
+{ /* block id: 29 */
+ int8_t *l_134 = &g_36;
+ int8_t ** const l_133 = &l_134;
+ int32_t l_156 = 0xE85A3F02L;
+ uint32_t l_166 = 0x5E662131L;
+ uint8_t **l_172 = &g_43;
+ uint8_t **l_174[2][7] = {{&g_43,&g_43,&g_43,&g_43,&g_43,&g_43,&g_43},{&g_43,&g_43,&g_43,&g_43,&g_43,&g_43,&g_43}};
+ uint8_t ***l_173[2][9] = {{(void*)0,&l_172,(void*)0,&l_172,(void*)0,&l_172,(void*)0,&l_172,(void*)0},{(void*)0,(void*)0,&l_174[1][0],&l_174[1][0],(void*)0,(void*)0,&l_174[1][0],&l_174[1][0],(void*)0}};
+ int32_t *l_211[6] = {&g_3,&g_3,&g_3,&g_3,&g_3,&g_3};
+ int32_t l_418 = 0xBEDB2E7EL;
+ int32_t l_582 = 8L;
+ int16_t l_587[5][7][2] = {{{0x5323L,1L},{0xDA62L,0xA377L},{0xD174L,0xDA62L},{0x959BL,0x0DAEL},{0x959BL,0xDA62L},{0xD174L,0xA377L},{0xDA62L,1L}},{{0x5323L,(-1L)},{0xA377L,0x9B9BL},{0x9B9BL,0x9B9BL},{0xA377L,(-1L)},{0x5323L,1L},{0xDA62L,0xA377L},{0xD174L,0xDA62L}},{{0x959BL,0x0DAEL},{0x959BL,0xDA62L},{0xD174L,0xA377L},{0xDA62L,1L},{0x5323L,(-1L)},{0xA377L,0x9B9BL},{0x9B9BL,0x9B9BL}},{{0xA377L,(-1L)},{0x5323L,1L},{0xDA62L,0xA377L},{0xD174L,0xDA62L},{0x959BL,0x0DAEL},{(-1L),0x0DAEL},{0x5323L,0x9B9BL}},{{0x0DAEL,0xD174L},{0x959BL,0xA377L},{0x9B9BL,(-7L)},{(-7L),(-7L)},{0x9B9BL,0xA377L},{0x959BL,0xD174L},{0x0DAEL,0x9B9BL}}};
+ uint32_t l_614 = 4294967286UL;
+ int i, j, k;
+ return &g_297[1];
+}
+
+
+
+
+/* ---------------------------------------- */
+int main (int argc, char* argv[])
+{
+ int i, j, k;
+ int print_hash_value = 0;
+ if (argc == 2 && strcmp(argv[1], "1") == 0) print_hash_value = 1;
+ platform_main_begin();
+ crc32_gentab();
+ func_1();
+ for (i = 0; i < 5; i++)
+ {
+ for (j = 0; j < 1; j++)
+ {
+ transparent_crc(g_2[i][j], "g_2[i][j]", print_hash_value);
+ if (print_hash_value) printf("index = [%d][%d]\n", i, j);
+
+ }
+ }
+ transparent_crc(g_3, "g_3", print_hash_value);
+ for (i = 0; i < 6; i++)
+ {
+ transparent_crc(g_14[i], "g_14[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ transparent_crc(g_15, "g_15", print_hash_value);
+ transparent_crc(g_34, "g_34", print_hash_value);
+ transparent_crc(g_36, "g_36", print_hash_value);
+ for (i = 0; i < 7; i++)
+ {
+ transparent_crc(g_40[i], "g_40[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ transparent_crc(g_44, "g_44", print_hash_value);
+ transparent_crc(g_46, "g_46", print_hash_value);
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ for (k = 0; k < 3; k++)
+ {
+ transparent_crc(g_51[i][j][k], "g_51[i][j][k]", print_hash_value);
+ if (print_hash_value) printf("index = [%d][%d][%d]\n", i, j, k);
+
+ }
+ }
+ }
+ transparent_crc(g_52, "g_52", print_hash_value);
+ transparent_crc(g_56, "g_56", print_hash_value);
+ transparent_crc(g_140, "g_140", print_hash_value);
+ transparent_crc(g_251, "g_251", print_hash_value);
+ transparent_crc(g_255, "g_255", print_hash_value);
+ transparent_crc(g_290, "g_290", print_hash_value);
+ for (i = 0; i < 5; i++)
+ {
+ transparent_crc(g_294[i], "g_294[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ for (i = 0; i < 2; i++)
+ {
+ transparent_crc(g_297[i], "g_297[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ transparent_crc(g_320, "g_320", print_hash_value);
+ transparent_crc(g_347, "g_347", print_hash_value);
+ transparent_crc(g_419, "g_419", print_hash_value);
+ transparent_crc(g_477, "g_477", print_hash_value);
+ for (i = 0; i < 6; i++)
+ {
+ transparent_crc(g_705[i], "g_705[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ transparent_crc(g_969, "g_969", print_hash_value);
+ transparent_crc(g_1055, "g_1055", print_hash_value);
+ transparent_crc(g_1099, "g_1099", print_hash_value);
+ transparent_crc(g_1132, "g_1132", print_hash_value);
+ transparent_crc(g_1189, "g_1189", print_hash_value);
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 1; j++)
+ {
+ for (k = 0; k < 8; k++)
+ {
+ transparent_crc(g_1254[i][j][k], "g_1254[i][j][k]", print_hash_value);
+ if (print_hash_value) printf("index = [%d][%d][%d]\n", i, j, k);
+
+ }
+ }
+ }
+ transparent_crc(g_1285, "g_1285", print_hash_value);
+ transparent_crc(g_1298, "g_1298", print_hash_value);
+ transparent_crc(g_1333, "g_1333", print_hash_value);
+ transparent_crc(g_1334, "g_1334", print_hash_value);
+ transparent_crc(g_1509, "g_1509", print_hash_value);
+ transparent_crc(g_1766, "g_1766", print_hash_value);
+ transparent_crc(g_1776, "g_1776", print_hash_value);
+ for (i = 0; i < 6; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ for (k = 0; k < 5; k++)
+ {
+ transparent_crc(g_1782[i][j][k], "g_1782[i][j][k]", print_hash_value);
+ if (print_hash_value) printf("index = [%d][%d][%d]\n", i, j, k);
+
+ }
+ }
+ }
+ transparent_crc(g_1857, "g_1857", print_hash_value);
+ transparent_crc(g_1961, "g_1961", print_hash_value);
+ transparent_crc(g_2067, "g_2067", print_hash_value);
+ for (i = 0; i < 10; i++)
+ {
+ transparent_crc(g_2147[i], "g_2147[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ transparent_crc(g_2148, "g_2148", print_hash_value);
+ transparent_crc(g_2207, "g_2207", print_hash_value);
+ platform_main_end(crc32_context ^ 0xFFFFFFFFUL, print_hash_value);
+ return 0;
+}
+
+/************************ statistics *************************
+XXX max struct depth: 0
+breakdown:
+ depth: 0, occurrence: 652
+XXX total union variables: 0
+
+XXX non-zero bitfields defined in structs: 0
+XXX zero bitfields defined in structs: 0
+XXX const bitfields defined in structs: 0
+XXX volatile bitfields defined in structs: 0
+XXX structs with bitfields in the program: 0
+breakdown:
+XXX full-bitfields structs in the program: 0
+breakdown:
+XXX times a bitfields struct's address is taken: 0
+XXX times a bitfields struct on LHS: 0
+XXX times a bitfields struct on RHS: 0
+XXX times a single bitfield on LHS: 0
+XXX times a single bitfield on RHS: 0
+
+XXX max expression depth: 41
+breakdown:
+ depth: 1, occurrence: 169
+ depth: 2, occurrence: 42
+ depth: 3, occurrence: 3
+ depth: 4, occurrence: 2
+ depth: 6, occurrence: 1
+ depth: 7, occurrence: 1
+ depth: 8, occurrence: 1
+ depth: 10, occurrence: 1
+ depth: 13, occurrence: 1
+ depth: 14, occurrence: 1
+ depth: 15, occurrence: 1
+ depth: 16, occurrence: 3
+ depth: 19, occurrence: 1
+ depth: 20, occurrence: 1
+ depth: 21, occurrence: 4
+ depth: 22, occurrence: 2
+ depth: 23, occurrence: 2
+ depth: 24, occurrence: 2
+ depth: 25, occurrence: 1
+ depth: 26, occurrence: 2
+ depth: 27, occurrence: 3
+ depth: 28, occurrence: 4
+ depth: 30, occurrence: 1
+ depth: 31, occurrence: 1
+ depth: 33, occurrence: 1
+ depth: 35, occurrence: 2
+ depth: 36, occurrence: 2
+ depth: 39, occurrence: 4
+ depth: 41, occurrence: 2
+
+XXX total number of pointers: 428
+
+XXX times a variable address is taken: 1238
+XXX times a pointer is dereferenced on RHS: 347
+breakdown:
+ depth: 1, occurrence: 232
+ depth: 2, occurrence: 83
+ depth: 3, occurrence: 32
+XXX times a pointer is dereferenced on LHS: 261
+breakdown:
+ depth: 1, occurrence: 220
+ depth: 2, occurrence: 32
+ depth: 3, occurrence: 9
+XXX times a pointer is compared with null: 37
+XXX times a pointer is compared with address of another variable: 12
+XXX times a pointer is compared with another pointer: 17
+XXX times a pointer is qualified to be dereferenced: 9414
+
+XXX max dereference level: 5
+breakdown:
+ level: 0, occurrence: 0
+ level: 1, occurrence: 1507
+ level: 2, occurrence: 661
+ level: 3, occurrence: 292
+ level: 4, occurrence: 45
+ level: 5, occurrence: 6
+XXX number of pointers point to pointers: 210
+XXX number of pointers point to scalars: 218
+XXX number of pointers point to structs: 0
+XXX percent of pointers has null in alias set: 29.2
+XXX average alias set size: 1.54
+
+XXX times a non-volatile is read: 2082
+XXX times a non-volatile is write: 921
+XXX times a volatile is read: 0
+XXX times read thru a pointer: 0
+XXX times a volatile is write: 0
+XXX times written thru a pointer: 0
+XXX times a volatile is available for access: 0
+XXX percentage of non-volatile access: 100
+
+XXX forward jumps: 1
+XXX backward jumps: 7
+
+XXX stmts: 175
+XXX max block depth: 5
+breakdown:
+ depth: 0, occurrence: 34
+ depth: 1, occurrence: 30
+ depth: 2, occurrence: 19
+ depth: 3, occurrence: 27
+ depth: 4, occurrence: 30
+ depth: 5, occurrence: 35
+
+XXX percentage a fresh-made variable is used: 16.5
+XXX percentage an existing variable is used: 83.5
+********************* end of statistics **********************/
+
diff --git a/tests/fuzz/19.c.txt b/tests/fuzz/19.c.txt
new file mode 100644
index 00000000..5fac330b
--- /dev/null
+++ b/tests/fuzz/19.c.txt
@@ -0,0 +1 @@
+checksum = 150DAD10
diff --git a/tests/fuzz/20.cpp b/tests/fuzz/20.cpp
new file mode 100644
index 00000000..619ac697
--- /dev/null
+++ b/tests/fuzz/20.cpp
@@ -0,0 +1,977 @@
+/*
+ * This is a RANDOMLY GENERATED PROGRAM.
+ *
+ * Generator: csmith 2.2.0
+ * Git version: bf42ffd
+ * Options: --no-volatiles --no-packed-struct --no-math64 --lang-cpp
+ * Seed: 2354592696
+ */
+
+#include "csmith.h"
+
+
+static long __undefined;
+
+/* --- Struct/Union Declarations --- */
+/* --- GLOBAL VARIABLES --- */
+static int32_t g_8[4] = {(-1L),(-1L),(-1L),(-1L)};
+static int32_t g_10 = 0x095A9796L;
+static uint8_t g_14 = 0xBBL;
+static uint16_t g_68 = 65535UL;
+static int32_t g_89 = (-1L);
+static int32_t *g_88 = &g_89;
+static const uint16_t g_95 = 65535UL;
+static const uint16_t *g_94 = &g_95;
+static int32_t g_101[1][2][5] = {{{0L,0L,0L,0L,0L},{(-1L),(-1L),(-1L),(-1L),(-1L)}}};
+static uint16_t g_168 = 65535UL;
+static int16_t g_175 = (-10L);
+static uint8_t g_177 = 1UL;
+static int8_t g_208 = 1L;
+static int8_t *g_207[4] = {&g_208,&g_208,&g_208,&g_208};
+static int32_t g_263 = (-4L);
+static int32_t **g_311 = NULL;
+static int32_t ***g_310 = &g_311;
+static uint32_t g_324[4][1][5] = {{{0xA3D675C6L,0x497B3AE0L,0xA3D675C6L,1UL,1UL}},{{0xA3D675C6L,0x497B3AE0L,0xA3D675C6L,1UL,1UL}},{{0xA3D675C6L,0x497B3AE0L,0xA3D675C6L,1UL,1UL}},{{0xA3D675C6L,0x497B3AE0L,0xA3D675C6L,1UL,1UL}}};
+static uint32_t g_369 = 0x38F403BAL;
+static int16_t **g_435 = NULL;
+static const int32_t g_490 = (-1L);
+static int8_t g_532 = 0xE9L;
+static uint32_t g_534 = 0UL;
+static int32_t g_679[1][5] = {{0x6C6BABE0L,0x6C6BABE0L,0x6C6BABE0L,0x6C6BABE0L,0x6C6BABE0L}};
+static int16_t *g_691 = &g_175;
+static int32_t *g_735 = NULL;
+static uint16_t g_813 = 1UL;
+static int16_t g_906 = 0x50BEL;
+static uint32_t g_912 = 0x1175B058L;
+static int8_t * const *g_1027 = &g_207[2];
+static int8_t * const **g_1026[5] = {&g_1027,&g_1027,&g_1027,&g_1027,&g_1027};
+static int8_t **g_1029 = &g_207[1];
+static int8_t ***g_1028 = &g_1029;
+static uint8_t g_1098 = 251UL;
+static int16_t ***g_1103 = &g_435;
+static int16_t ****g_1102 = &g_1103;
+static uint32_t *g_1251 = &g_534;
+static uint32_t **g_1250 = &g_1251;
+static uint32_t ***g_1249 = &g_1250;
+static int8_t ***g_1452 = &g_1029;
+static uint8_t *g_1457 = &g_1098;
+static uint8_t **g_1456 = &g_1457;
+static int32_t *g_1463 = &g_10;
+static int32_t **g_1486 = &g_1463;
+static int32_t **g_1487 = &g_735;
+static int16_t **** const *g_1490 = &g_1102;
+static int16_t **** const **g_1489 = &g_1490;
+static int32_t g_1555 = 0x5CD64271L;
+static uint16_t g_1566 = 65531UL;
+static int8_t g_1611 = (-1L);
+static int16_t g_1671[8] = {(-7L),(-7L),(-7L),(-7L),(-7L),(-7L),(-7L),(-7L)};
+static uint32_t g_1726 = 2UL;
+static uint32_t g_1781[2][2] = {{1UL,1UL},{1UL,1UL}};
+static int8_t ****g_1806 = &g_1028;
+static int8_t *****g_1805[10][1][3] = {{{NULL,NULL,NULL}},{{&g_1806,&g_1806,&g_1806}},{{NULL,NULL,NULL}},{{&g_1806,&g_1806,&g_1806}},{{NULL,NULL,NULL}},{{&g_1806,&g_1806,&g_1806}},{{NULL,NULL,NULL}},{{&g_1806,&g_1806,&g_1806}},{{NULL,NULL,NULL}},{{&g_1806,&g_1806,&g_1806}}};
+static uint32_t g_1846[4] = {1UL,1UL,1UL,1UL};
+static const uint32_t g_1878[9][9][3] = {{{18446744073709551609UL,0x41FAE503L,5UL},{4UL,0xB45FB625L,0xBA90DCABL},{0x7859E91FL,18446744073709551609UL,5UL},{0UL,0x87F82538L,1UL},{0xDE88EC26L,0x8F3A2F9CL,0xC2B3141CL},{0x8C538065L,0x49C63EC0L,0x44D75A98L},{18446744073709551615UL,18446744073709551615UL,0x3EA8F13BL},{0x44D75A98L,18446744073709551614UL,18446744073709551606UL},{0xB1C843BDL,18446744073709551615UL,0x384A1D15L}},{{0x5E837D39L,0x49C63EC0L,0x5E837D39L},{18446744073709551615UL,0x8F3A2F9CL,18446744073709551609UL},{0UL,0x87F82538L,0xB7463E48L},{0x384A1D15L,18446744073709551609UL,0x97952306L},{0x03506829L,0xB45FB625L,0xB011D241L},{0x384A1D15L,0x41FAE503L,0x7859E91FL},{0UL,0x0EC69127L,0xD92197E9L},{18446744073709551615UL,5UL,0x06FB78C1L},{0x5E837D39L,0xD81B3B3EL,0UL}},{{0xB1C843BDL,0x5098CCB1L,1UL},{0x44D75A98L,0x37E638FAL,0UL},{18446744073709551615UL,0x06FB78C1L,0x06FB78C1L},{0x8C538065L,18446744073709551607UL,0xD92197E9L},{0xDE88EC26L,0xC2B3141CL,0x7859E91FL},{0UL,0xA98FC4D4L,0xB011D241L},{0x7859E91FL,0xB1C843BDL,0x97952306L},{4UL,0xA98FC4D4L,0xB7463E48L},{18446744073709551609UL,0xC2B3141CL,18446744073709551609UL}},{{0UL,18446744073709551607UL,0x5E837D39L},{5UL,0x06FB78C1L,0x384A1D15L},{0xB7463E48L,0x37E638FAL,18446744073709551606UL},{0x8F3A2F9CL,0x5098CCB1L,0x3EA8F13BL},{0xB7463E48L,0xD81B3B3EL,0x44D75A98L},{5UL,5UL,0xC2B3141CL},{0UL,0x0EC69127L,1UL},{18446744073709551609UL,0x41FAE503L,5UL},{4UL,0xB45FB625L,0xBA90DCABL}},{{0x7859E91FL,18446744073709551609UL,5UL},{0UL,0x87F82538L,1UL},{0xDE88EC26L,0x8F3A2F9CL,0xC2B3141CL},{0x8C538065L,0x49C63EC0L,0x44D75A98L},{18446744073709551615UL,18446744073709551615UL,0x3EA8F13BL},{0x44D75A98L,18446744073709551614UL,18446744073709551606UL},{0xB1C843BDL,18446744073709551615UL,0x384A1D15L},{0x5E837D39L,0x49C63EC0L,0x5E837D39L},{18446744073709551615UL,0x8F3A2F9CL,18446744073709551609UL}},{{0UL,0x87F82538L,0xB7463E48L},{0x384A1D15L,18446744073709551609UL,0x97952306L},{0x03506829L,0xB45FB625L,0UL},{18446744073709551609UL,5UL,0x8F3A2F9CL},{0x44D75A98L,0x36765C43L,0xD909217BL},{0x06FB78C1L,0x7859E91FL,0x97952306L},{0xB513056EL,0x0EC69127L,0x44D75A98L},{0x41FAE503L,0xB1C843BDL,0x384A1D15L},{0x03506829L,0xDAD1FA39L,0x44D75A98L}},{{0xDE88EC26L,0x97952306L,0x97952306L},{0xB011D241L,0UL,0xD909217BL},{0x3EA8F13BL,0x5098CCB1L,0x8F3A2F9CL},{0x8C538065L,0x87F82538L,0UL},{0x8F3A2F9CL,0x41FAE503L,1UL},{0x685D1A38L,0x87F82538L,0x5E837D39L},{0x6768B2D9L,0x5098CCB1L,0x6768B2D9L},{1UL,0UL,0xB513056EL},{0x7859E91FL,0x97952306L,18446744073709551609UL}},{{0x5E837D39L,0xDAD1FA39L,0xBA90DCABL},{18446744073709551615UL,0xB1C843BDL,18446744073709551615UL},{0x5E837D39L,0x0EC69127L,0x03506829L},{0x7859E91FL,0x7859E91FL,0x5098CCB1L},{1UL,0x36765C43L,18446744073709551606UL},{0x6768B2D9L,5UL,0x7859E91FL},{0x685D1A38L,18446744073709551614UL,0xB7463E48L},{0x8F3A2F9CL,0x6768B2D9L,0x7859E91FL},{0x8C538065L,0x2406F886L,18446744073709551606UL}},{{0x3EA8F13BL,18446744073709551615UL,0x5098CCB1L},{0xB011D241L,0xB45FB625L,0x03506829L},{0xDE88EC26L,0x06FB78C1L,18446744073709551615UL},{0x03506829L,0xD81B3B3EL,0xBA90DCABL},{0x41FAE503L,0x06FB78C1L,18446744073709551609UL},{0xB513056EL,0xB45FB625L,0xB513056EL},{0x06FB78C1L,18446744073709551615UL,0x6768B2D9L},{0x44D75A98L,0x2406F886L,0x5E837D39L},{18446744073709551609UL,0x6768B2D9L,1UL}}};
+static uint32_t * const g_1962 = &g_324[3][0][0];
+static uint32_t * const *g_1961 = &g_1962;
+static uint16_t g_2002 = 4UL;
+static int16_t ** const * const g_2016 = &g_435;
+static int16_t ** const * const *g_2015 = &g_2016;
+static int16_t ** const * const **g_2014 = &g_2015;
+static int16_t ** const * const **g_2018 = &g_2015;
+
+
+/* --- FORWARD DECLARATIONS --- */
+static uint32_t func_1(void);
+static int32_t func_5(int32_t p_6, uint32_t p_7);
+static uint8_t func_39(uint32_t p_40, int32_t * p_41, int32_t p_42);
+static const int32_t * func_52(int32_t p_53, uint8_t p_54, uint32_t p_55, int16_t p_56, uint8_t p_57);
+static int32_t * func_64(uint16_t p_65, int32_t * p_66);
+static int32_t * func_69(int8_t p_70);
+static uint8_t func_76(uint8_t p_77, const int32_t * const p_78, int32_t * p_79);
+static int32_t * const func_80(int32_t * p_81);
+static int32_t * func_82(int32_t p_83, uint16_t p_84, int32_t * p_85);
+static int32_t func_92(const uint16_t * p_93);
+
+
+/* --- FUNCTIONS --- */
+/* ------------------------------------------ */
+/*
+ * reads : g_8 g_14 g_10 g_68 g_88 g_912 g_94 g_95 g_735 g_101 g_1250 g_1251 g_534 g_679 g_1029 g_207 g_208 g_691 g_1463 g_168 g_1457 g_1098 g_1249 g_1489 g_263 g_89 g_175 g_813 g_1566 g_1027 g_1611 g_532 g_1726 g_1028 g_1781 g_1490 g_1102 g_1103 g_435 g_177 g_1555 g_906 g_324 g_1671 g_1487 g_1961 g_1456 g_2002 g_1486 g_1962 g_2014
+ * writes: g_14 g_68 g_10 g_735 g_88 g_168 g_534 g_1028 g_1452 g_101 g_1456 g_175 g_1486 g_1487 g_263 g_89 g_94 g_813 g_208 g_1555 g_1566 g_532 g_1098 g_1611 g_1726 g_1102 g_1781 g_435 g_177 g_207 g_2002 g_1463 g_324 g_2014 g_2018
+ */
+static uint32_t func_1(void)
+{ /* block id: 0 */
+ uint32_t l_4 = 0x20398070L;
+ int32_t l_17 = (-1L);
+ int32_t *l_18 = &l_17;
+ int32_t *l_21[4][2][10] = {{{NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},{NULL,NULL,&g_8[0],NULL,NULL,&g_8[3],&g_8[0],&g_8[3],NULL,NULL}},{{NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL},{NULL,NULL,&g_8[1],NULL,NULL,NULL,&g_8[1],NULL,NULL,NULL}},{{NULL,NULL,NULL,&g_8[3],NULL,NULL,NULL,&g_8[3],NULL,NULL},{NULL,&g_8[3],&g_8[0],&g_8[3],NULL,NULL,&g_8[0],NULL,NULL,&g_8[3]}},{{NULL,&g_8[3],NULL,NULL,NULL,&g_8[3],NULL,NULL,NULL,&g_8[3]},{NULL,NULL,&g_8[1],NULL,NULL,NULL,&g_8[1],NULL,NULL,NULL}}};
+ uint16_t l_1947 = 0UL;
+ uint8_t l_1950 = 8UL;
+ int32_t l_1952 = (-7L);
+ int32_t l_1967 = 0x2594DE78L;
+ int8_t *l_1968 = &g_208;
+ uint32_t l_1969 = 0xA55E1FD4L;
+ uint32_t **l_1994 = &g_1251;
+ int32_t l_2003 = 0xD7936716L;
+ int16_t *****l_2013 = &g_1102;
+ int16_t ******l_2012 = &l_2013;
+ int16_t ** const * const ***l_2017[9];
+ int i, j, k;
+ for (i = 0; i < 9; i++)
+ l_2017[i] = NULL;
+ (*l_18) = (safe_rshift_func_uint16_t_u_s((((l_4 , (func_5(g_8[0], l_4) ^ 0x4D07DDBFL)) , 5UL) , (((((+func_5(g_8[0], (l_17 |= ((g_8[0] || (l_4 , l_4)) , g_8[2])))) >= g_10) , 0xA6C2E3A4L) , 0L) < 4294967295UL)), g_8[0]));
+ if (func_5(((*l_18) = (safe_lshift_func_uint8_t_u_u(func_5(g_14, (*l_18)), 3))), (&g_10 == &g_10)))
+ { /* block id: 8 */
+ uint32_t l_30 = 0x8A7E8B7DL;
+ int16_t l_49 = (-1L);
+ const int16_t l_50 = 0xB00FL;
+ int32_t *l_51 = &l_17;
+ uint16_t *l_1948 = NULL;
+ uint16_t *l_1949 = NULL;
+ uint16_t *l_1951[1][8][1] = {{{NULL},{&g_168},{NULL},{&g_168},{NULL},{&g_168},{NULL},{&g_168}}};
+ int8_t l_1953 = (-4L);
+ uint32_t l_1954[8][4][2] = {{{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL},{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL}},{{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL},{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL}},{{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL},{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL}},{{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL},{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL}},{{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL},{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL}},{{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL},{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL}},{{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL},{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL}},{{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL},{0xF7B7F389L,0x84E19BCBL},{0x2B89271DL,0x84E19BCBL}}};
+ int i, j, k;
+ (*l_18) = ((((NULL != &g_8[1]) <= ((((safe_add_func_uint8_t_u_u(((*g_1457) = func_5(((safe_rshift_func_int8_t_s_u((((++g_14) , (-8L)) , (((safe_rshift_func_int16_t_s_s(l_30, 1)) <= (func_5((((safe_mul_func_uint16_t_u_u((l_1952 = (l_30 , ((safe_rshift_func_uint16_t_u_s((safe_rshift_func_uint16_t_u_u((l_1950 ^= (+((safe_mod_func_uint8_t_u_u(func_39((((((func_5((func_5(g_10, func_5((((((((safe_add_func_uint8_t_u_u(((safe_mul_func_uint16_t_u_u((NULL != &g_10), (safe_lshift_func_int8_t_s_s(g_10, 1)))) ^ 0x8CD8B12AL), g_8[0])) <= l_30) != 0x7384L) < (*l_18)) , (*l_18)) , l_49) <= (*l_18)), g_14)) & l_50), g_8[0]) >= 0x8DL) , &g_8[3]) != NULL) , (int32_t*) NULL) != NULL), l_51, g_8[1]), g_906)) < l_1947))), 10)), (*l_51))) , 0xE604L))), 0x59B6L)) ^ (*l_51)) | (*l_51)), (*l_51)) | (*l_51))) <= (*l_51))), g_324[3][0][0])) , (*l_18)), (*l_18))), l_1953)) , (*l_18)) | (*l_18)) & (*l_51))) | (*l_51)) , l_1954[3][2][0]);
+ return g_1671[5];
+ }
+ else
+ { /* block id: 885 */
+ int8_t *l_1963 = &g_1611;
+ int32_t l_1966 = 1L;
+ const int32_t *l_1971 = &g_89;
+ const int32_t **l_1970 = &l_1971;
+ uint16_t *l_1991[2];
+ uint32_t *l_1999 = &l_1969;
+ int i;
+ for (i = 0; i < 2; i++)
+ l_1991[i] = &g_813;
+ (*g_1487) = &l_17;
+ (*l_1970) = func_52((safe_div_func_uint8_t_u_u((safe_mul_func_uint16_t_u_u(((*g_1249) != (*g_1249)), (safe_rshift_func_uint16_t_u_s(((*l_18) & (NULL != (*g_1490))), (NULL == g_1961))))), ((((**g_1028) = l_1963) != ((safe_lshift_func_uint8_t_u_s(((l_1967 |= l_1966) <= 0x55L), 5)) , l_1968)) ^ l_1969))), (*l_18), l_1966, (*l_18), (**g_1456));
+ l_18 = ((*g_1486) = ((((safe_div_func_uint16_t_u_u((safe_div_func_int8_t_s_s(((safe_rshift_func_uint8_t_u_s((safe_rshift_func_uint16_t_u_u(((safe_mul_func_uint8_t_u_u(0UL, ((g_2002 = ((*g_1251) < (safe_lshift_func_int8_t_s_u(((((safe_div_func_int32_t_s_s((((safe_sub_func_uint16_t_u_u((safe_rshift_func_uint8_t_u_u((*l_18), 1)), (g_168 &= (safe_unary_minus_func_int8_t_s(0x8AL))))) < ((safe_mul_func_int16_t_s_s((l_1994 != ((safe_mul_func_int8_t_s_s(((***g_1028) |= (*l_18)), (safe_add_func_uint32_t_u_u((++(*l_1999)), (**g_1487))))) , (*g_1249))), g_2002)) , 0xCDA1EE90L)) && (*l_18)), 0x4EED3296L)) && (**g_1456)) <= (*l_18)) >= 255UL), l_2003)))) , (*l_18)))) == (*l_18)), 8)), 2)) <= (*l_18)), 1L)), 8L)) != 0xEBL) , (*g_1457)) , (int32_t*) NULL));
+ }
+ (**g_1487) = ((safe_add_func_int8_t_s_s(l_1952, (((**g_1456) | (-8L)) <= (safe_mul_func_int16_t_s_s(l_1952, (l_17 , (0x039BF18DL > ((safe_sub_func_int32_t_s_s((safe_add_func_uint16_t_u_u(65535UL, ((((*l_2012) = &g_1102) != (g_2018 = (g_2014 = ((((*g_1962) = 3UL) , (**g_1456)) , g_2014)))) <= l_17))), (*g_735))) <= l_1967)))))))) || l_1952);
+ return (*g_1962);
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_14
+ * writes: g_14
+ */
+static int32_t func_5(int32_t p_6, uint32_t p_7)
+{ /* block id: 1 */
+ int32_t *l_9[2];
+ uint32_t l_11 = 1UL;
+ int i;
+ for (i = 0; i < 2; i++)
+ l_9[i] = &g_10;
+ l_11--;
+ ++g_14;
+ return p_6;
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_8 g_10 g_68 g_14 g_88 g_912 g_94 g_813 g_95 g_735 g_101 g_1250 g_1251 g_534 g_679 g_1029 g_207 g_208 g_691 g_1463 g_168 g_1457 g_1098 g_1249 g_1489 g_175 g_89 g_1566 g_1027 g_1611 g_532 g_1726 g_1028 g_1781 g_1490 g_1102 g_1103 g_435 g_177 g_1555 g_263
+ * writes: g_68 g_10 g_735 g_88 g_168 g_14 g_534 g_1028 g_1452 g_101 g_1456 g_175 g_1486 g_1487 g_263 g_89 g_94 g_813 g_208 g_1555 g_1566 g_532 g_1098 g_1611 g_1726 g_1102 g_1781 g_435 g_177
+ */
+static uint8_t func_39(uint32_t p_40, int32_t * p_41, int32_t p_42)
+{ /* block id: 10 */
+ uint16_t *l_67 = &g_68;
+ int32_t l_75 = 1L;
+ int32_t **l_1491[8] = {&g_735,NULL,&g_735,NULL,&g_735,NULL,&g_735,NULL};
+ int32_t *l_1492 = NULL;
+ const int32_t *l_1680 = &g_10;
+ const int32_t **l_1679 = &l_1680;
+ int32_t *l_1681 = &g_101[0][1][2];
+ uint32_t l_1738 = 0x915B1875L;
+ int16_t ****l_1759 = &g_1103;
+ int8_t l_1785[2][10][5] = {{{0L,0xD1L,0L,0x10L,0xA1L},{(-4L),0xF8L,0L,(-9L),9L},{(-1L),0L,0x19L,0L,0x60L},{0x10L,(-7L),0L,9L,(-1L)},{0x20L,0L,0L,(-4L),0x12L},{1L,(-1L),(-1L),0x89L,0x10L},{0x1CL,0x60L,0x33L,0L,0x8FL},{0x7BL,0x4EL,9L,0L,1L},{0x83L,0x8FL,(-1L),0x89L,0x3AL},{0L,(-4L),(-1L),(-4L),0L}},{{(-1L),(-9L),(-7L),9L,(-8L)},{0x8FL,0x46L,0xD1L,0L,(-4L)},{0xD1L,(-7L),0x60L,(-9L),(-8L)},{(-1L),0L,1L,0x10L,0L},{(-8L),0x50L,(-7L),0x46L,0x3AL},{0x33L,1L,0x3AL,0xC2L,1L},{(-1L),0x20L,0x10L,(-1L),0x8FL},{(-1L),(-1L),(-1L),0x20L,0x10L},{0x33L,9L,0x12L,0L,0x12L},{(-8L),(-8L),1L,0x3AL,(-1L)}}};
+ uint32_t l_1789 = 18446744073709551613UL;
+ uint32_t **l_1796 = &g_1251;
+ int16_t l_1841 = 0x47E8L;
+ int8_t ****l_1864 = &g_1452;
+ const uint32_t *l_1877 = &g_1878[1][2][2];
+ const uint32_t **l_1876 = &l_1877;
+ int16_t l_1889 = 0x474EL;
+ int32_t l_1941 = 0x901B980BL;
+ uint8_t *l_1944 = &g_14;
+ uint8_t *l_1945 = NULL;
+ uint8_t *l_1946 = &g_177;
+ int i, j, k;
+lbl_1744:
+ (*l_1679) = func_52(g_8[0], g_8[0], ((g_10 , (func_5((g_8[0] && ((safe_lshift_func_int8_t_s_u(func_5((safe_mul_func_int8_t_s_s(((l_1492 = func_64(((*l_67) |= 0xAE56L), func_69(((safe_add_func_uint16_t_u_u((g_168 = ((safe_sub_func_int32_t_s_s(l_75, ((l_75 , func_76(g_14, func_80(func_82((g_10 = (safe_rshift_func_uint8_t_u_u(g_8[2], 6))), g_14, g_88)), &g_101[0][1][1])) < 5UL))) || p_40)), l_75)) >= (*g_94))))) != NULL), 0x19L)), p_40), p_40)) <= p_40)), p_40) , (*g_1251))) < p_42), p_40, p_40);
+ if (((p_41 = &p_42) != (l_1681 = &g_89)))
+ { /* block id: 749 */
+ uint16_t l_1684[9][7] = {{0x4D1DL,1UL,0x075BL,0xEA90L,0xD27EL,65526UL,0x9259L},{0x075BL,0xFB9BL,0x10FFL,65526UL,65530UL,6UL,65526UL},{1UL,0x9259L,0xD27EL,0UL,65526UL,0UL,0xD27EL},{6UL,6UL,0x10FFL,0xDC46L,65526UL,0x9922L,0x9259L},{0x9922L,0x3934L,6UL,1UL,0x10FFL,65527UL,0xFC16L},{0x10FFL,1UL,65526UL,65526UL,65526UL,0xFC16L,6UL},{0x861FL,0xD27EL,6UL,65535UL,65530UL,65530UL,65535UL},{0UL,0xD27EL,0UL,6UL,0xFC16L,65526UL,65526UL},{0x4D1DL,1UL,3UL,0xFC16L,65527UL,0x10FFL,1UL}};
+ uint8_t * const *l_1695 = &g_1457;
+ int32_t l_1711 = 0x5C5B3728L;
+ int8_t l_1728 = 0x47L;
+ int32_t l_1733 = 0x9B2D669CL;
+ int32_t l_1735 = 1L;
+ int32_t l_1737 = 0xD5DDB545L;
+ int32_t l_1784 = (-7L);
+ int32_t l_1786 = (-1L);
+ int32_t l_1787 = 0L;
+ int32_t l_1788 = 0xB7C3DCB2L;
+ int i, j;
+ for (g_1611 = 0; (g_1611 > 2); g_1611 = safe_add_func_uint16_t_u_u(g_1611, 8))
+ { /* block id: 752 */
+ int32_t l_1710 = 1L;
+ int32_t l_1731 = 0x84BCF933L;
+ int32_t l_1732 = (-1L);
+ int32_t l_1734 = 0L;
+ int32_t l_1775 = 1L;
+ int32_t l_1776 = 0xE5BFAA72L;
+ int32_t l_1777 = (-6L);
+ int32_t l_1778 = 0x647D0747L;
+ int32_t l_1779 = 0x099AC607L;
+ int32_t l_1780 = 0xD5FEF757L;
+ (*p_41) &= l_1684[1][6];
+ for (g_175 = 3; (g_175 >= 1); g_175 -= 1)
+ { /* block id: 756 */
+ int32_t l_1730 = 8L;
+ int32_t *l_1746 = &g_10;
+ int32_t l_1760 = 1L;
+ int32_t l_1774[1][2][5] = {{{2L,(-1L),2L,2L,(-1L)},{(-1L),2L,2L,(-1L),2L}}};
+ int i, j, k;
+ if ((safe_div_func_int32_t_s_s(g_8[g_175], (safe_sub_func_int8_t_s_s((-1L), g_8[g_175])))))
+ { /* block id: 757 */
+ uint32_t ***l_1724 = &g_1250;
+ int32_t l_1727 = (-7L);
+ int32_t l_1729 = 0x4E2B1F57L;
+ int32_t l_1736 = 0xD335B7D7L;
+ for (p_40 = 0; (p_40 <= 4); p_40 += 1)
+ { /* block id: 760 */
+ uint32_t *l_1725 = &g_1726;
+ int i;
+ l_1711 = (safe_rshift_func_int8_t_s_s(((safe_mul_func_int16_t_s_s(g_8[g_175], (safe_sub_func_int16_t_s_s((l_1695 == ((((((((safe_add_func_uint16_t_u_u((safe_mod_func_int16_t_s_s(((0UL ^ (((p_40 >= (safe_div_func_uint16_t_u_u((!(*g_94)), ((safe_div_func_int16_t_s_s(1L, (safe_rshift_func_int16_t_s_s(((*p_41) , 5L), (safe_mul_func_uint16_t_u_u((safe_lshift_func_int16_t_s_u(((*p_41) < p_42), 14)), g_8[g_175])))))) | 0x7A52D48EL)))) || (*p_41)) , (*p_41))) , 6L), 1UL)), l_1710)) | p_40) , l_1710) | 0x94D1L) , &g_1456) != &g_1456) && 0x35F8L) , l_1695)), (*g_691))))) >= 1UL), 4));
+ (*g_1463) = ((((((safe_sub_func_uint16_t_u_u((l_1711 &= (safe_mod_func_uint8_t_u_u(((p_40 > (*g_1457)) <= ((*g_94) >= (p_40 == (safe_add_func_int32_t_s_s((((p_40 < p_40) & (safe_sub_func_int8_t_s_s((~(safe_lshift_func_uint16_t_u_u(((((l_1727 ^= ((*l_1725) &= ((**g_1250) ^= (safe_sub_func_int16_t_s_s((l_1724 != l_1724), (((((~0xE6FD0E25L) ^ 8L) != 0x1FF1L) <= (*g_94)) | g_8[g_175])))))) == (*p_41)) < p_40) == p_40), 1))), l_1728))) , (*p_41)), (*l_1681)))))), p_42))), l_1728)) <= l_1729) > (*g_94)) , (int32_t***) NULL) == &g_311) & p_40);
+ }
+ if ((*g_1463))
+ { /* block id: 768 */
+ (*g_1463) ^= l_1711;
+ if ((*p_41))
+ continue;
+ }
+ else
+ { /* block id: 771 */
+ return p_42;
+ }
+ l_1738--;
+ }
+ else
+ { /* block id: 775 */
+ uint8_t l_1741 = 0xA9L;
+ l_1741--;
+ if (l_75)
+ goto lbl_1744;
+ }
+ if (l_1735)
+ { /* block id: 779 */
+ (*l_1681) ^= l_1728;
+ }
+ else
+ { /* block id: 781 */
+ int32_t l_1745 = 0xB909AFC6L;
+ int16_t *****l_1747 = NULL;
+ int16_t *****l_1748 = &g_1102;
+ int32_t l_1768[9][4][3] = {{{0xCD9A7C8AL,(-5L),(-4L)},{0xAF3B7215L,0x2196F175L,(-6L)},{1L,(-1L),0x3F1D03C1L},{(-1L),0x2196F175L,(-1L)}},{{0x21C896E3L,(-5L),0L},{0x2196F175L,0x41C49213L,0L},{(-1L),0xAACA832CL,(-1L)},{0x919DCA21L,0x21C896E3L,0x3F1D03C1L}},{{0x41C49213L,0xF437A5A9L,(-6L)},{0x919DCA21L,0xEDA3817EL,(-4L)},{(-1L),(-1L),0x520C3304L},{0x2196F175L,(-1L),0x4D455C86L}},{{0x21C896E3L,0xEDA3817EL,0L},{(-1L),0xF437A5A9L,0xA4D09836L},{1L,0x21C896E3L,0L},{0xAF3B7215L,0xAACA832CL,0x4D455C86L}},{{0xCD9A7C8AL,0x41C49213L,0x520C3304L},{0xCD9A7C8AL,(-5L),(-4L)},{0xAF3B7215L,0x2196F175L,(-6L)},{1L,(-1L),0x3F1D03C1L}},{{(-1L),0x2196F175L,(-1L)},{0x21C896E3L,(-5L),0L},{0x2196F175L,0x41C49213L,0L},{(-1L),0xAACA832CL,(-1L)}},{{0x919DCA21L,0x21C896E3L,0x3F1D03C1L},{0x41C49213L,0xF437A5A9L,(-6L)},{0x919DCA21L,0xEDA3817EL,(-4L)},{(-1L),(-1L),0x520C3304L}},{{0x2196F175L,(-1L),0x4D455C86L},{0x21C896E3L,0xEDA3817EL,0L},{(-1L),0xF437A5A9L,0xA4D09836L},{1L,0x21C896E3L,0L}},{{0xAF3B7215L,0xAACA832CL,0x4D455C86L},{0xCD9A7C8AL,0x41C49213L,0x520C3304L},{0xCD9A7C8AL,(-5L),(-4L)},{0xAF3B7215L,0x2196F175L,(-6L)}}};
+ int i, j, k;
+ for (p_42 = 7; (p_42 >= 0); p_42 -= 1)
+ { /* block id: 784 */
+ int i;
+ if ((*p_41))
+ break;
+ if (l_1745)
+ break;
+ l_1746 = &p_42;
+ if (l_1710)
+ continue;
+ }
+ (*l_1681) = ((0x2EEBL < (((*l_1748) = &g_1103) != (((safe_rshift_func_int8_t_s_u(p_40, l_1745)) ^ ((*l_1746) = (safe_sub_func_int8_t_s_s((safe_mul_func_int16_t_s_s((-1L), (~l_1745))), (((***g_1028) = 0x9DL) != ((((safe_mod_func_int32_t_s_s((-6L), (safe_mod_func_uint32_t_u_u((**g_1250), 0x6072443AL)))) & p_40) != (*l_1746)) ^ 4UL)))))) , l_1759))) < l_1760);
+ if ((*p_41))
+ { /* block id: 794 */
+ int32_t * const l_1767 = &g_263;
+ int32_t * const *l_1766 = &l_1767;
+ int32_t * const * const *l_1765 = &l_1766;
+ int32_t l_1769 = 0xF3C67E0AL;
+ int32_t l_1770 = 0xDE144CE1L;
+ int32_t l_1771 = 0x87004860L;
+ int32_t l_1772 = 0L;
+ int32_t l_1773[4][2][1];
+ int i, j, k;
+ for (i = 0; i < 4; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ for (k = 0; k < 1; k++)
+ l_1773[i][j][k] = 0xCD9C8AADL;
+ }
+ }
+ (*l_1681) ^= ((*l_1746) = (*p_41));
+ (*l_1679) = func_82(((*p_41) = ((p_42 || ((*g_94) != (&g_1250 == &g_1250))) && (((l_1745 , (safe_mul_func_int8_t_s_s((((**g_1029) = ((NULL != (uint32_t*) l_1746) || ((*l_1746) == (p_42 >= 0xAB24L)))) != 0xDAL), l_1737))) , l_1765) == &g_311))), p_40, p_41);
+ g_1781[1][0]++;
+ }
+ else
+ { /* block id: 801 */
+ (*p_41) = 0xF85691D2L;
+ }
+ }
+ l_1789++;
+ }
+ if ((*p_41))
+ break;
+ }
+ }
+ else
+ { /* block id: 809 */
+ int8_t ****l_1797[3][10][8] = {{{NULL,&g_1028,&g_1028,&g_1452,&g_1028,&g_1452,&g_1028,&g_1028},{&g_1028,&g_1028,&g_1028,&g_1028,&g_1028,&g_1028,&g_1452,&g_1028},{NULL,&g_1452,&g_1028,&g_1452,&g_1452,&g_1028,&g_1028,&g_1452},{&g_1452,&g_1028,NULL,&g_1452,&g_1028,&g_1452,NULL,&g_1452},{&g_1452,&g_1452,&g_1028,NULL,&g_1452,&g_1452,NULL,&g_1452},{&g_1028,&g_1028,NULL,&g_1028,&g_1028,&g_1452,&g_1452,NULL},{NULL,&g_1452,&g_1028,&g_1028,&g_1452,&g_1452,&g_1452,&g_1452},{&g_1452,&g_1452,NULL,NULL,&g_1452,&g_1452,NULL,&g_1452},{NULL,&g_1028,&g_1028,&g_1028,&g_1028,&g_1452,&g_1452,NULL},{&g_1028,&g_1452,&g_1452,&g_1028,&g_1452,&g_1452,&g_1452,&g_1452}},{{&g_1452,&g_1452,&g_1028,NULL,&g_1452,&g_1452,NULL,&g_1452},{&g_1028,&g_1028,NULL,&g_1028,&g_1028,&g_1452,&g_1452,NULL},{NULL,&g_1452,&g_1028,&g_1028,&g_1452,&g_1452,&g_1452,&g_1452},{&g_1452,&g_1452,NULL,NULL,&g_1452,&g_1452,NULL,&g_1452},{NULL,&g_1028,&g_1028,&g_1028,&g_1028,&g_1452,&g_1452,NULL},{&g_1028,&g_1452,&g_1452,&g_1028,&g_1452,&g_1452,&g_1452,&g_1452},{&g_1452,&g_1452,&g_1028,NULL,&g_1452,&g_1452,NULL,&g_1452},{&g_1028,&g_1028,NULL,&g_1028,&g_1028,&g_1452,&g_1452,NULL},{NULL,&g_1452,&g_1028,&g_1028,&g_1452,&g_1452,&g_1452,&g_1452},{&g_1452,&g_1452,NULL,NULL,&g_1452,&g_1452,NULL,&g_1452}},{{NULL,&g_1028,&g_1028,&g_1028,&g_1028,&g_1452,&g_1452,NULL},{&g_1028,&g_1452,&g_1452,&g_1028,&g_1452,&g_1452,&g_1452,&g_1452},{&g_1452,&g_1452,&g_1028,NULL,&g_1452,&g_1452,NULL,&g_1452},{&g_1028,&g_1028,NULL,&g_1028,&g_1028,&g_1452,&g_1452,NULL},{NULL,&g_1452,&g_1028,&g_1028,&g_1452,&g_1452,&g_1452,&g_1452},{&g_1452,&g_1452,NULL,NULL,&g_1452,&g_1452,NULL,&g_1452},{NULL,&g_1028,&g_1028,&g_1028,&g_1028,&g_1452,&g_1452,NULL},{&g_1028,&g_1452,&g_1452,&g_1028,&g_1452,&g_1452,NULL,NULL},{NULL,&g_1028,&g_1028,&g_1452,&g_1028,&g_1452,&g_1028,NULL},{&g_1452,&g_1028,&g_1452,NULL,&g_1028,&g_1452,NULL,&g_1028}}};
+ int32_t l_1809 = (-5L);
+ int32_t *l_1811 = &g_89;
+ int32_t l_1828 = 0x18381127L;
+ int32_t l_1830 = 2L;
+ int32_t l_1837 = 1L;
+ int32_t l_1843 = 0x4408EEE1L;
+ int32_t *l_1924 = &l_1809;
+ int i, j, k;
+ for (p_42 = (-7); (p_42 >= (-19)); p_42--)
+ { /* block id: 812 */
+ int8_t *****l_1798 = &l_1797[2][7][5];
+ uint32_t *l_1807[10];
+ int32_t l_1808 = 0x8CAAAE7BL;
+ int32_t l_1810 = (-10L);
+ int16_t l_1813[4];
+ int32_t l_1820 = 0x8E71FA34L;
+ int32_t l_1821 = 8L;
+ int32_t l_1823 = 0L;
+ int32_t l_1824 = 0xE5358F3EL;
+ int32_t l_1827 = 0x2A6C0624L;
+ int32_t l_1829 = 0L;
+ int32_t l_1832 = 0x231C0186L;
+ int32_t l_1835 = 1L;
+ int32_t l_1838 = 1L;
+ int32_t l_1842[4] = {(-1L),(-1L),(-1L),(-1L)};
+ const uint32_t *l_1875 = &g_1846[2];
+ const uint32_t **l_1874[10] = {&l_1875,&l_1875,&l_1875,&l_1875,&l_1875,&l_1875,&l_1875,&l_1875,&l_1875,&l_1875};
+ int i;
+ for (i = 0; i < 10; i++)
+ l_1807[i] = &l_1738;
+ for (i = 0; i < 4; i++)
+ l_1813[i] = (-1L);
+ (*g_1463) = (*p_41);
+ }
+ }
+ g_1555 &= (safe_div_func_uint32_t_u_u((safe_sub_func_int8_t_s_s(0xD7L, (+(safe_sub_func_uint32_t_u_u((((*l_1946) ^= (safe_rshift_func_uint8_t_u_s(((*l_1944) = ((*g_1457) = (((safe_mod_func_int32_t_s_s(((*g_1463) |= (safe_add_func_uint16_t_u_u(0x2230L, ((safe_lshift_func_int8_t_s_s(((safe_add_func_int8_t_s_s((((((****g_1489) = (g_175 , (***g_1490))) != NULL) | ((0xFFA26F57L || 0L) , ((*l_1681) = (l_1941 < (safe_div_func_uint16_t_u_u((((((!(0xFEF0B100L & p_40)) | p_42) ^ (*l_1681)) || 1UL) && (*g_1457)), p_42)))))) != p_40), p_40)) != p_40), 2)) && 0L)))), (*g_1251))) & (*p_41)) , 0UL))), 7))) | 4L), (*p_41)))))), 0x49EE9D83L));
+ return (*g_1457);
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_691 g_175 g_1249 g_1250 g_1251 g_534 g_88 g_89 g_813 g_263 g_1029 g_207 g_1457 g_1098 g_101 g_1463 g_10 g_1566 g_94 g_95 g_1027 g_208 g_1611 g_532 g_68
+ * writes: g_88 g_68 g_263 g_89 g_94 g_813 g_208 g_175 g_10 g_1555 g_1566 g_532 g_1098 g_534 g_14 g_1611
+ */
+static const int32_t * func_52(int32_t p_53, uint8_t p_54, uint32_t p_55, int16_t p_56, uint8_t p_57)
+{ /* block id: 675 */
+ int32_t * const l_1493 = &g_89;
+ int32_t **l_1494 = &g_88;
+ uint16_t l_1523 = 0xBC23L;
+ int32_t l_1626 = (-1L);
+ int32_t l_1630 = 0x2F07589FL;
+ int32_t l_1635 = 0x2A660ECFL;
+ int32_t l_1636 = 0x149622CEL;
+ int32_t l_1638 = 0xF571B7A6L;
+ int32_t l_1640 = 0x4D6D3401L;
+ int32_t l_1641 = 0xE0CBE1D6L;
+ int32_t l_1642 = 0xB844DA30L;
+ int32_t l_1643 = 0xA3C3B5ABL;
+ int32_t l_1644 = (-1L);
+ int32_t l_1645 = 0x1F07B77DL;
+ int32_t l_1646 = 0xE5CFA295L;
+ int32_t l_1649 = (-1L);
+ int32_t l_1650[6][4] = {{0L,0x2CBBE18CL,0L,0L},{0x2CBBE18CL,0x2CBBE18CL,0L,0x2CBBE18CL},{0x2CBBE18CL,0L,0L,0x2CBBE18CL},{0L,0x2CBBE18CL,0L,0L},{0x2CBBE18CL,0x2CBBE18CL,0L,0x2CBBE18CL},{0x2CBBE18CL,0L,0L,0x2CBBE18CL}};
+ int32_t l_1657 = (-4L);
+ int i, j;
+lbl_1575:
+ (*l_1494) = l_1493;
+ for (g_68 = 24; (g_68 == 39); g_68 = safe_add_func_uint8_t_u_u(g_68, 4))
+ { /* block id: 679 */
+ uint16_t l_1504[6];
+ const int32_t *l_1518 = &g_101[0][0][1];
+ int8_t * const l_1535 = &g_532;
+ int8_t *l_1537 = &g_532;
+ int32_t l_1617 = 0xDC512F73L;
+ int32_t l_1629[4][1] = {{(-6L)},{0x1AD9824DL},{(-6L)},{0x1AD9824DL}};
+ int8_t l_1637 = (-10L);
+ int i, j;
+ for (i = 0; i < 6; i++)
+ l_1504[i] = 0UL;
+ for (g_263 = 3; (g_263 >= 0); g_263 -= 1)
+ { /* block id: 682 */
+ const uint16_t l_1513 = 0x834AL;
+ uint8_t *l_1514 = &g_14;
+ const int32_t *l_1517 = &g_89;
+ int32_t *l_1565 = NULL;
+ int32_t **l_1564 = &l_1565;
+ int32_t l_1568[7];
+ int i;
+ for (i = 0; i < 7; i++)
+ l_1568[i] = 0L;
+ for (g_89 = 3; (g_89 >= 1); g_89 -= 1)
+ { /* block id: 685 */
+ int32_t l_1503 = 0x8350D1F8L;
+ const uint16_t *l_1505[7];
+ const uint16_t **l_1506 = &l_1505[1];
+ uint32_t l_1515[2];
+ uint32_t *l_1554[7] = {&l_1515[1],&l_1515[1],&l_1515[1],&l_1515[1],&l_1515[1],&l_1515[1],&l_1515[1]};
+ int32_t l_1567 = (-5L);
+ uint16_t *l_1574 = NULL;
+ uint16_t **l_1573 = &l_1574;
+ int i;
+ for (i = 0; i < 7; i++)
+ l_1505[i] = &g_813;
+ for (i = 0; i < 2; i++)
+ l_1515[i] = 0x234DA6F4L;
+ if (((safe_add_func_int16_t_s_s((((((safe_mul_func_int16_t_s_s((safe_lshift_func_int8_t_s_s(l_1503, 1)), l_1504[0])) , ((((p_57 & (NULL == &p_54)) & 1UL) <= ((((*l_1506) = (g_94 = l_1505[0])) != NULL) , ((safe_mod_func_int16_t_s_s((p_56 = (safe_mod_func_int32_t_s_s(((safe_add_func_int16_t_s_s((*g_691), l_1503)) , p_53), (***g_1249)))), p_53)) == l_1513))) , (**l_1494))) & 0x6641EF11L) , (uint8_t*) NULL) != l_1514), l_1515[1])) & (***g_1249)))
+ { /* block id: 689 */
+ uint32_t l_1516 = 1UL;
+ if (l_1516)
+ { /* block id: 690 */
+ return l_1517;
+ }
+ else
+ { /* block id: 692 */
+ return l_1518;
+ }
+ }
+ else
+ { /* block id: 695 */
+ uint16_t *l_1521 = &g_813;
+ int8_t *l_1536 = &g_532;
+ (*g_1463) = (((((**g_1029) = (safe_mod_func_uint16_t_u_u((NULL != &g_1250), ((*l_1521) ^= 1UL)))) <= (*g_1457)) >= ((safe_unary_minus_func_uint32_t_u((!(**g_1250)))) > (l_1523 <= ((safe_unary_minus_func_uint32_t_u((safe_add_func_uint16_t_u_u((safe_mod_func_int32_t_s_s((safe_rshift_func_int16_t_s_s(((*g_691) = ((safe_mul_func_int16_t_s_s(p_56, (0x2F59L || ((((safe_mod_func_int8_t_s_s(p_53, (*l_1518))) == (-7L)) >= (-1L)) == g_175)))) , 0xBA32L)), p_56)), (*g_1251))), g_89)))) <= p_56)))) , 0xBDB685A7L);
+ if ((*g_1463))
+ continue;
+ (*g_1463) |= (l_1535 != (l_1537 = l_1536));
+ }
+ (*g_1463) |= (safe_mod_func_int8_t_s_s((safe_div_func_int8_t_s_s(p_54, (safe_rshift_func_int8_t_s_u(((safe_rshift_func_uint16_t_u_s(((safe_add_func_int8_t_s_s(((*l_1535) = ((NULL == (*g_1249)) , ((l_1503 || (*g_1251)) > (safe_div_func_int16_t_s_s((safe_add_func_uint32_t_u_u((p_55 = (((safe_sub_func_int32_t_s_s(((g_1555 = 0x02FA4FDCL) != (*l_1493)), (g_1566 ^= (((((safe_sub_func_uint8_t_u_u(((safe_add_func_uint8_t_u_u(p_53, (((safe_mod_func_int8_t_s_s((safe_rshift_func_uint16_t_u_u(((+(p_56 != 0xE9L)) > p_54), (**l_1494))), 0xD9L)) , 0x63D33749L) ^ (**g_1250)))) , l_1515[1]), (*l_1518))) , l_1515[0]) > p_57) , l_1564) != &l_1565)))) , &g_1098) != &p_54)), (**g_1250))), p_57))))), (**l_1494))) | (*l_1493)), l_1515[1])) != (*l_1518)), 0)))), 1L));
+ (*g_1463) = ((l_1568[1] = (!(3L <= l_1567))) && ((safe_rshift_func_int16_t_s_s((safe_sub_func_uint16_t_u_u((*g_94), (*g_94))), (*g_691))) > (((*l_1573) = &g_1566) == &l_1504[0])));
+ if ((*l_1517))
+ break;
+ }
+ for (g_1098 = 1; (g_1098 <= 4); g_1098 += 1)
+ { /* block id: 716 */
+ int8_t l_1596 = (-1L);
+ uint16_t l_1612[10][1];
+ int32_t l_1627[10][8][3] = {{{0xC0858DD3L,0x6CDF6292L,0x0C47EFC1L},{1L,0x2B909333L,(-1L)},{(-1L),0x51500EF7L,8L},{(-3L),1L,(-1L)},{(-10L),0L,0x0C47EFC1L},{0x2B39689EL,(-4L),1L},{0xCF339FD2L,(-4L),0xB192890FL},{0xE885E439L,1L,0xE885E439L}},{{(-1L),(-6L),(-4L)},{0xBA747FABL,0xB96D546FL,(-4L)},{4L,0xCF339FD2L,0x6CDF6292L},{1L,9L,0x05C6FB27L},{4L,0x301C8E77L,8L},{0xBA747FABL,0x28220F40L,4L},{(-1L),0L,0L},{0xE885E439L,0x7AC51D76L,0x7AC51D76L}},{{0xCF339FD2L,0x9B745613L,0x20AF4157L},{0x2B39689EL,(-3L),0xE885E439L},{(-10L),0x0C47EFC1L,6L},{(-3L),0xB96D546FL,0x28220F40L},{(-1L),0x0C47EFC1L,(-6L)},{1L,(-3L),0xC54F3900L},{0xC0858DD3L,0x9B745613L,8L},{0xB96D546FL,0x7AC51D76L,0xE4F7FA0BL}},{{0L,0L,0xCF339FD2L},{0x7085AA06L,0x28220F40L,0xF46FF3C9L},{0xCF339FD2L,0x301C8E77L,0x930F5A2FL},{0x2A0E2F99L,9L,0xE885E439L},{0xE30DA511L,0xCF339FD2L,0x930F5A2FL},{2L,0xB96D546FL,0xF46FF3C9L},{0x1801E895L,(-6L),0xCF339FD2L},{1L,1L,0xE4F7FA0BL}},{{8L,(-4L),8L},{0xC9619119L,(-4L),0xC54F3900L},{0xEF4FC547L,0L,(-6L)},{0x9BB809B8L,1L,0x28220F40L},{0xCF339FD2L,0x51500EF7L,6L},{0x9BB809B8L,0x2B909333L,0xE885E439L},{0xEF4FC547L,0x6CDF6292L,0x20AF4157L},{0xC9619119L,0xB96D546FL,0x7AC51D76L}},{{8L,0L,0L},{0x2A0E2F99L,0xC9619119L,0x2B909333L},{0x930F5A2FL,0xEF4FC547L,6L},{0x28220F40L,0x9BB809B8L,0x4059FABFL},{0x0C47EFC1L,0xCF339FD2L,0x1801E895L},{4L,0x9BB809B8L,0x7085AA06L},{(-1L),0xEF4FC547L,0x51500EF7L},{0xC54F3900L,0xC9619119L,0x05C6FB27L}},{{0xCF339FD2L,8L,(-4L)},{1L,1L,0x2A0E2F99L},{(-4L),0x1801E895L,4L},{0x2A0E2F99L,2L,(-3L)},{0x20AF4157L,0xE30DA511L,6L},{0xF46FF3C9L,0x2A0E2F99L,(-3L)},{0x6CDF6292L,0xCF339FD2L,4L},{(-1L),0x7085AA06L,0x2A0E2F99L}},{{(-1L),0L,(-4L)},{0x05C6FB27L,0xB96D546FL,0x05C6FB27L},{(-6L),0xC0858DD3L,0x51500EF7L},{0x7AC51D76L,1L,0x7085AA06L},{0xB192890FL,(-1L),0x1801E895L},{0x2A0E2F99L,(-3L),0x4059FABFL},{0xB192890FL,(-10L),6L},{0x7AC51D76L,0x2B39689EL,0x2B909333L}},{{(-6L),0xCF339FD2L,8L},{0x05C6FB27L,0xE885E439L,0xE885E439L},{(-1L),(-1L),0x301C8E77L},{(-1L),0xBA747FABL,0x05C6FB27L},{0x6CDF6292L,4L,0x9B745613L},{0xF46FF3C9L,1L,0x2B39689EL},{0x20AF4157L,4L,0xC0858DD3L},{0x2A0E2F99L,0xBA747FABL,9L}},{{(-4L),(-1L),6L},{1L,0xE885E439L,1L},{0xCF339FD2L,0xCF339FD2L,(-1L)},{0xC54F3900L,0x2B39689EL,0x9BB809B8L},{(-1L),(-10L),1L},{4L,(-3L),0x05C6FB27L},{0x0C47EFC1L,(-1L),1L},{0x28220F40L,1L,0x9BB809B8L}}};
+ uint8_t l_1661 = 0x91L;
+ uint8_t l_1672 = 0x8AL;
+ int i, j, k;
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 1; j++)
+ l_1612[i][j] = 0xADEAL;
+ }
+ if (p_53)
+ goto lbl_1575;
+ for (g_813 = 1; (g_813 <= 4); g_813 += 1)
+ { /* block id: 720 */
+ int16_t l_1610[5];
+ int32_t l_1628 = 1L;
+ int32_t l_1631 = 0x2FD5F7A3L;
+ int32_t l_1632 = 0x49EF7935L;
+ int32_t l_1634 = 0xBFA600F1L;
+ int32_t l_1639 = 0xDFC860C3L;
+ int32_t l_1647 = 0x7A248064L;
+ int32_t l_1648 = 0x06A924C2L;
+ int32_t l_1651 = 0x3BAFF8AFL;
+ int32_t l_1652 = 0xE4B57DEBL;
+ int32_t l_1653 = 0x330A2A19L;
+ int32_t l_1654 = 0xF11007C4L;
+ int32_t l_1655 = 1L;
+ int32_t l_1656[6];
+ uint8_t l_1658 = 0x6DL;
+ int32_t l_1675 = 8L;
+ uint16_t l_1676 = 0x29D9L;
+ int i;
+ for (i = 0; i < 5; i++)
+ l_1610[i] = 0xB1EEL;
+ for (i = 0; i < 6; i++)
+ l_1656[i] = 1L;
+ if (((safe_mul_func_uint8_t_u_u((((l_1612[9][0] = ((safe_sub_func_uint8_t_u_u(((++(*g_1251)) & 0x55C69D38L), (((*g_94) , (safe_lshift_func_int16_t_s_u((safe_sub_func_int32_t_s_s(((+(safe_lshift_func_int8_t_s_s((safe_add_func_int8_t_s_s((*l_1517), ((*l_1535) ^= ((safe_mul_func_uint8_t_u_u((safe_add_func_int32_t_s_s((safe_sub_func_int8_t_s_s((((l_1596 & (*l_1517)) || (((*l_1514) = ((safe_mul_func_int8_t_s_s(0xBAL, (p_57 > (!((safe_add_func_int8_t_s_s(((safe_sub_func_uint32_t_u_u((safe_unary_minus_func_int16_t_s(((safe_lshift_func_uint8_t_u_s(0xB1L, 6)) == (safe_rshift_func_uint8_t_u_s(((safe_sub_func_int16_t_s_s((0x08L == p_57), l_1610[4])) , (*g_1457)), 7))))), p_53)) , (**g_1027)), (*l_1518))) | l_1596))))) && (*l_1517))) , p_56)) >= g_1611), l_1596)), 0UL)), l_1596)) < (**g_1027))))), 4))) > (*g_1457)), p_53)), p_54))) ^ l_1596))) | p_57)) || 1UL) , p_55), l_1610[4])) == 8L))
+ { /* block id: 725 */
+ int32_t *l_1613 = &g_89;
+ int32_t *l_1614 = &g_1555;
+ int32_t *l_1615 = &g_1555;
+ int32_t *l_1616 = &l_1568[5];
+ int32_t *l_1618 = &g_101[0][1][4];
+ int32_t *l_1619 = &g_1555;
+ int32_t *l_1620 = &g_10;
+ int32_t *l_1621 = &l_1568[3];
+ int32_t *l_1622 = &g_1555;
+ int32_t *l_1623 = &l_1617;
+ int32_t *l_1624 = &g_89;
+ int32_t *l_1625[8][10][3] = {{{&g_1555,NULL,&g_89},{&l_1568[5],&l_1568[1],&g_89},{&g_89,&l_1568[1],&l_1568[5]},{&l_1568[5],NULL,NULL},{&g_1555,&l_1568[1],&g_89},{&l_1568[1],&l_1568[1],NULL},{&g_89,NULL,&l_1568[5]},{&l_1568[1],NULL,&g_89},{&g_1555,NULL,&g_89},{&l_1568[5],&l_1568[1],&g_89}},{{&g_89,&l_1568[1],&l_1568[5]},{&l_1568[5],NULL,NULL},{&g_1555,&l_1568[1],&g_89},{&l_1568[1],&l_1568[1],NULL},{&g_89,NULL,&l_1568[5]},{&l_1568[1],NULL,&g_89},{&g_1555,NULL,&g_89},{&l_1568[5],&l_1568[1],&g_89},{&g_89,&l_1568[1],&l_1568[5]},{&l_1568[5],NULL,NULL}},{{&g_1555,&l_1568[1],&g_89},{&l_1568[1],&l_1568[1],NULL},{&g_89,NULL,&l_1568[5]},{&l_1568[1],NULL,&g_89},{&g_1555,NULL,&g_101[0][1][4]},{&l_1568[1],&l_1568[1],&l_1617},{&l_1568[5],NULL,NULL},{&l_1568[1],&g_1555,&g_1555},{NULL,NULL,&g_101[0][1][4]},{NULL,&l_1568[1],&g_1555}},{{&l_1568[5],&l_1568[4],NULL},{NULL,&g_1555,&l_1617},{NULL,&l_1568[4],&g_101[0][1][4]},{&l_1568[1],&l_1568[1],&l_1617},{&l_1568[5],NULL,NULL},{&l_1568[1],&g_1555,&g_1555},{NULL,NULL,&g_101[0][1][4]},{NULL,&l_1568[1],&g_1555},{&l_1568[5],&l_1568[4],NULL},{NULL,&g_1555,&l_1617}},{{NULL,&l_1568[4],&g_101[0][1][4]},{&l_1568[1],&l_1568[1],&l_1617},{&l_1568[5],NULL,NULL},{&l_1568[1],&g_1555,&g_1555},{NULL,NULL,&g_101[0][1][4]},{NULL,&l_1568[1],&g_1555},{&l_1568[5],&l_1568[4],NULL},{NULL,&g_1555,&l_1617},{NULL,&l_1568[4],&g_101[0][1][4]},{&l_1568[1],&l_1568[1],&l_1617}},{{&l_1568[5],NULL,NULL},{&l_1568[1],&g_1555,&g_1555},{NULL,NULL,&g_101[0][1][4]},{NULL,&l_1568[1],&g_1555},{&l_1568[5],&l_1568[4],NULL},{NULL,&g_1555,&l_1617},{NULL,&l_1568[4],&g_101[0][1][4]},{&l_1568[1],&l_1568[1],&l_1617},{&l_1568[5],NULL,NULL},{&l_1568[1],&g_1555,&g_1555}},{{NULL,NULL,&g_101[0][1][4]},{NULL,&l_1568[1],&g_1555},{&l_1568[5],&l_1568[4],NULL},{NULL,&g_1555,&l_1617},{NULL,&l_1568[4],&g_101[0][1][4]},{&l_1568[1],&l_1568[1],&l_1617},{&l_1568[5],NULL,NULL},{&l_1568[1],&g_1555,&g_1555},{NULL,NULL,&g_101[0][1][4]},{NULL,&l_1568[1],&g_1555}},{{&l_1568[5],&l_1568[4],NULL},{NULL,&g_1555,&l_1617},{NULL,&l_1568[4],&g_101[0][1][4]},{&l_1568[1],&l_1568[1],&l_1617},{&l_1568[5],NULL,NULL},{&l_1568[1],&g_1555,&g_1555},{NULL,NULL,&g_101[0][1][4]},{NULL,&l_1568[1],&g_1555},{&l_1568[5],&l_1568[4],NULL},{NULL,&g_1555,&l_1617}}};
+ int32_t l_1633[6][3][5] = {{{0x54E12B57L,(-1L),(-1L),0x54E12B57L,0x549A8D90L},{0x54E12B57L,0xD8394710L,0x67A448C4L,0x55C0B040L,0L},{0L,(-1L),0x67A448C4L,0xC213F2D5L,(-1L)}},{{0x2BAA21AFL,0xA4F12C09L,(-1L),0x55C0B040L,(-1L)},{8L,1L,1L,0x54E12B57L,0L},{0L,0x2BAA21AFL,6L,1L,(-1L)}},{{0x5288A55AL,6L,0L,1L,(-4L)},{0L,8L,8L,0L,(-1L)},{0L,0x55C0B040L,0xC213F2D5L,0x9E74C91AL,6L}},{{0x5288A55AL,8L,0xC213F2D5L,(-5L),0xFDBFCCF4L},{0L,6L,8L,0x9E74C91AL,0xFDBFCCF4L},{1L,0x2BAA21AFL,0L,0L,6L}},{{0L,0x2BAA21AFL,6L,1L,(-1L)},{0x5288A55AL,6L,0L,1L,(-4L)},{0L,8L,8L,0L,(-1L)}},{{0L,0x55C0B040L,0xC213F2D5L,0x9E74C91AL,6L},{0x5288A55AL,8L,0xC213F2D5L,(-5L),0xFDBFCCF4L},{0L,6L,8L,0x9E74C91AL,0xFDBFCCF4L}}};
+ int i, j, k;
+ --l_1658;
+ l_1661++;
+ (*l_1623) &= (safe_div_func_uint32_t_u_u((*l_1517), p_54));
+ if (p_57)
+ continue;
+ }
+ else
+ { /* block id: 730 */
+ if (p_57)
+ break;
+ }
+ (*g_1463) = (-4L);
+ for (l_1648 = 4; (l_1648 >= 1); l_1648 -= 1)
+ { /* block id: 736 */
+ int32_t *l_1666 = &l_1654;
+ int32_t *l_1667 = &l_1634;
+ int32_t *l_1668 = NULL;
+ int32_t *l_1669 = &l_1629[1][0];
+ int32_t *l_1670[3][6] = {{&l_1628,&l_1636,&l_1636,&l_1628,NULL,&l_1628},{&l_1628,NULL,&l_1628,&l_1636,&l_1636,&l_1628},{NULL,NULL,&l_1636,&l_1629[1][0],&l_1636,NULL}};
+ int i, j;
+ l_1672++;
+ l_1676--;
+ }
+ }
+ }
+ }
+ }
+ (*l_1494) = NULL;
+ return (*l_1494);
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_94 g_95 g_168 g_1457 g_1098 g_1249 g_1250 g_1251 g_534 g_1489 g_1463 g_88 g_101 g_813
+ * writes: g_168 g_534 g_1486 g_1487 g_10 g_101
+ */
+static int32_t * func_64(uint16_t p_65, int32_t * p_66)
+{ /* block id: 664 */
+ int32_t *l_1470 = &g_8[0];
+ int32_t **l_1471 = &l_1470;
+ int32_t l_1472 = 8L;
+ uint16_t *l_1473[2][3] = {{&g_813,&g_168,&g_168},{&g_813,&g_168,&g_168}};
+ int32_t l_1482 = 4L;
+ int32_t **l_1483[8][2] = {{&g_88,NULL},{&g_88,&g_88},{NULL,&g_88},{&g_88,NULL},{&g_88,&g_88},{NULL,&g_88},{&g_88,NULL},{&g_88,&g_88}};
+ int32_t **l_1485 = &g_1463;
+ int32_t ***l_1484[7];
+ uint16_t *l_1488 = &g_168;
+ int i, j;
+ for (i = 0; i < 7; i++)
+ l_1484[i] = &l_1485;
+ (*g_88) |= (safe_sub_func_int16_t_s_s(((((safe_add_func_int8_t_s_s((((safe_rshift_func_uint16_t_u_s(((((*l_1471) = l_1470) != ((l_1472 , (((g_168 ^= (*g_94)) , (safe_lshift_func_int16_t_s_u((safe_mul_func_uint8_t_u_u((*g_1457), ((safe_div_func_uint32_t_u_u((++(***g_1249)), ((*g_1463) = (((((l_1482 ^= l_1472) && (l_1482 , ((l_1483[2][0] == (g_1487 = (g_1486 = &p_66))) , (((((((~((l_1488 == NULL) == p_65)) , (int16_t******) NULL) == g_1489) <= 0xAAB5L) , l_1488) == l_1488) == p_65)))) & (*g_94)) <= p_65) ^ p_65)))) <= p_65))), 11))) > 0xF0D8L)) , p_66)) < 65535UL), p_65)) != 4UL) <= p_65), p_65)) , (***g_1249)) == 0xE4B2D116L) | 7L), p_65));
+ return p_66;
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_14 g_735 g_101 g_1250 g_1251 g_94 g_95 g_534 g_679 g_1029 g_207 g_208 g_691 g_88 g_1463 g_813
+ * writes: g_14 g_534 g_1028 g_1452 g_101 g_1456 g_735 g_175
+ */
+static int32_t * func_69(int8_t p_70)
+{ /* block id: 646 */
+ uint8_t *l_1419[9] = {&g_177,&g_1098,&g_177,&g_177,&g_1098,&g_177,&g_177,&g_1098,&g_177};
+ int32_t l_1420 = 0x8112C32BL;
+ int32_t l_1421 = 0x5D192EC3L;
+ int32_t l_1422 = (-2L);
+ int32_t l_1423 = 3L;
+ int32_t l_1424[1][7][9] = {{{0xA557835BL,0x13D4A42FL,0x65F5FA38L,0x65F5FA38L,0x13D4A42FL,0xA557835BL,0x11973284L,(-3L),3L},{0L,(-3L),1L,(-1L),1L,0x2B1E312BL,0xA557835BL,0x65F5FA38L,0xD082371BL},{(-1L),1L,(-3L),0L,0x11973284L,(-10L),0x11973284L,0L,(-3L)},{0x65F5FA38L,0x65F5FA38L,0x13D4A42FL,0xA557835BL,0x11973284L,(-3L),3L,0xD082371BL,7L},{0xCC668815L,0x7AE882F6L,0xD082371BL,(-6L),1L,(-1L),0x2B1E312BL,0x11973284L,0x11973284L},{7L,0x5A5A6D7DL,0x13D4A42FL,1L,0x13D4A42FL,0x5A5A6D7DL,7L,(-1L),4L},{7L,0x2B1E312BL,(-3L),0x5A5A6D7DL,0L,1L,(-1L),(-10L),0xA557835BL}}};
+ int16_t ***** const l_1427 = &g_1102;
+ int16_t *****l_1428 = &g_1102;
+ int16_t ******l_1429 = &l_1428;
+ int16_t *l_1442 = &g_175;
+ int32_t l_1443 = 0xCFA03042L;
+ int8_t ***l_1450 = &g_1029;
+ int8_t ****l_1451[8][6][5] = {{{&g_1028,&l_1450,NULL,NULL,NULL},{&g_1028,&l_1450,&l_1450,&g_1028,&l_1450},{&g_1028,&g_1028,NULL,&l_1450,&g_1028},{&l_1450,&l_1450,&l_1450,&g_1028,&g_1028},{&g_1028,&g_1028,&g_1028,&g_1028,&g_1028},{&g_1028,&l_1450,&g_1028,&l_1450,&g_1028}},{{NULL,&g_1028,&l_1450,&g_1028,&l_1450},{NULL,&l_1450,&g_1028,&g_1028,&l_1450},{NULL,&g_1028,&l_1450,&l_1450,&l_1450},{&g_1028,&g_1028,&g_1028,&l_1450,&g_1028},{&g_1028,NULL,&l_1450,NULL,&l_1450},{&l_1450,NULL,&g_1028,&g_1028,&l_1450}},{{&g_1028,NULL,&g_1028,&l_1450,&l_1450},{&l_1450,&g_1028,&l_1450,&g_1028,&g_1028},{&g_1028,&g_1028,&l_1450,NULL,&g_1028},{&l_1450,&l_1450,&g_1028,&l_1450,&g_1028},{&g_1028,&g_1028,&l_1450,&l_1450,&g_1028},{&l_1450,&l_1450,&l_1450,&g_1028,&g_1028}},{{&g_1028,&g_1028,&g_1028,&g_1028,&g_1028},{&g_1028,&l_1450,&g_1028,&l_1450,&g_1028},{NULL,&g_1028,&l_1450,&g_1028,&l_1450},{NULL,&l_1450,&g_1028,&g_1028,&l_1450},{NULL,&g_1028,&l_1450,&l_1450,&l_1450},{&g_1028,&g_1028,&g_1028,&l_1450,&g_1028}},{{&g_1028,NULL,&l_1450,NULL,&l_1450},{&l_1450,NULL,&g_1028,&g_1028,&l_1450},{&g_1028,NULL,&g_1028,&l_1450,&l_1450},{&l_1450,&g_1028,&l_1450,&g_1028,&g_1028},{&g_1028,&g_1028,&l_1450,NULL,&g_1028},{&l_1450,&l_1450,&g_1028,&l_1450,&g_1028}},{{&g_1028,&g_1028,&l_1450,&l_1450,&g_1028},{&l_1450,&l_1450,&l_1450,&g_1028,&g_1028},{&g_1028,&g_1028,&g_1028,&g_1028,&g_1028},{&g_1028,&l_1450,&g_1028,&l_1450,&g_1028},{NULL,&g_1028,&l_1450,&g_1028,&l_1450},{NULL,&l_1450,&g_1028,&g_1028,&l_1450}},{{NULL,&g_1028,&l_1450,&l_1450,&l_1450},{&g_1028,&g_1028,&g_1028,&l_1450,&g_1028},{&g_1028,NULL,&l_1450,NULL,&l_1450},{&l_1450,NULL,&g_1028,&g_1028,&l_1450},{&g_1028,NULL,&g_1028,&l_1450,&g_1028},{&l_1450,&g_1028,&g_1028,&g_1028,&l_1450}},{{&g_1028,&l_1450,&g_1028,&g_1028,&g_1028},{&l_1450,&l_1450,&l_1450,&l_1450,&l_1450},{&g_1028,&g_1028,&g_1028,&l_1450,&g_1028},{&l_1450,&l_1450,&g_1028,&l_1450,&l_1450},{&l_1450,&g_1028,&g_1028,&g_1028,&g_1028},{&g_1028,&l_1450,&g_1028,&l_1450,&l_1450}}};
+ int32_t **l_1453 = &g_735;
+ uint8_t **l_1455[5][6][8];
+ uint8_t ***l_1454[4][4][6] = {{{&l_1455[0][4][6],&l_1455[0][4][6],&l_1455[4][5][0],NULL,&l_1455[0][1][4],&l_1455[1][2][1]},{&l_1455[4][5][0],&l_1455[3][2][5],&l_1455[4][5][0],&l_1455[4][5][0],&l_1455[4][5][0],&l_1455[4][5][0]},{NULL,&l_1455[4][5][0],&l_1455[4][5][0],NULL,&l_1455[0][4][6],&l_1455[1][2][1]},{&l_1455[3][0][2],NULL,&l_1455[4][5][0],&l_1455[4][5][6],&l_1455[4][5][0],&l_1455[4][5][6]}},{{&l_1455[4][5][6],&l_1455[4][5][0],&l_1455[4][5][6],&l_1455[4][5][0],NULL,&l_1455[3][0][2]},{&l_1455[1][2][1],&l_1455[0][4][6],NULL,&l_1455[4][5][0],&l_1455[4][5][0],NULL},{&l_1455[4][5][0],&l_1455[4][5][0],&l_1455[4][5][0],&l_1455[4][5][0],&l_1455[3][2][5],&l_1455[4][5][0]},{&l_1455[1][2][1],&l_1455[0][1][4],NULL,&l_1455[4][5][0],&l_1455[0][4][6],&l_1455[0][4][6]}},{{&l_1455[4][5][6],&l_1455[4][5][0],&l_1455[4][5][0],&l_1455[4][5][6],&l_1455[1][2][3],&l_1455[4][5][0]},{&l_1455[3][0][2],NULL,&l_1455[4][5][6],NULL,NULL,&l_1455[4][5][0]},{NULL,&l_1455[0][4][6],&l_1455[0][1][4],&l_1455[4][5][0],NULL,NULL},{&l_1455[4][5][0],NULL,&l_1455[2][0][1],NULL,&l_1455[1][2][3],&l_1455[4][5][0]}},{{&l_1455[0][4][6],&l_1455[4][5][0],&l_1455[4][5][0],&l_1455[4][5][0],&l_1455[0][4][6],&l_1455[4][5][0]},{&l_1455[4][5][0],&l_1455[0][1][4],NULL,&l_1455[4][5][6],&l_1455[3][2][5],&l_1455[4][5][0]},{&l_1455[4][5][0],&l_1455[4][5][0],&l_1455[4][5][6],&l_1455[0][1][4],&l_1455[4][5][0],&l_1455[4][5][0]},{NULL,&l_1455[0][4][6],NULL,&l_1455[2][0][1],NULL,&l_1455[4][5][0]}}};
+ int16_t l_1459 = 5L;
+ int i, j, k;
+ for (i = 0; i < 5; i++)
+ {
+ for (j = 0; j < 6; j++)
+ {
+ for (k = 0; k < 8; k++)
+ l_1455[i][j][k] = &l_1419[0];
+ }
+ }
+ l_1423 |= ((safe_add_func_int32_t_s_s(0L, ((**g_1250) = (safe_lshift_func_int8_t_s_u(((safe_div_func_uint8_t_u_u((g_14++), (((l_1427 == ((*l_1429) = l_1428)) ^ (-6L)) && p_70))) != (safe_rshift_func_uint8_t_u_u(((safe_rshift_func_int16_t_s_u((((l_1443 = (safe_div_func_uint32_t_u_u((safe_add_func_int32_t_s_s((*g_735), ((l_1424[0][5][3] <= ((safe_mod_func_uint16_t_u_u(p_70, ((l_1442 == NULL) , 0x8830L))) < p_70)) & p_70))), p_70))) && 0L) > l_1422), p_70)) ^ 0x24L), l_1420))), l_1421))))) == l_1420);
+ (*g_735) = ((*g_94) && (safe_rshift_func_int8_t_s_s((((((((safe_rshift_func_int16_t_s_s((p_70 == ((((*l_1429) != (*l_1429)) , ((l_1423 <= (((**g_1250) , (((safe_div_func_int16_t_s_s(((g_1452 = (g_1028 = l_1450)) != NULL), p_70)) , (*g_94)) || 0x2E08L)) >= l_1421)) && p_70)) , l_1420)), 7)) <= g_679[0][4]) == 0x8AD548DCL) || (**g_1029)) , l_1453) != NULL) && p_70), 1)));
+ if (((g_1456 = &l_1419[0]) != NULL))
+ { /* block id: 656 */
+ int32_t *l_1458[3][9][3] = {{{NULL,NULL,&l_1422},{&l_1421,&l_1420,&g_89},{NULL,&g_101[0][0][0],&g_10},{&l_1443,&l_1443,&l_1422},{NULL,&l_1443,&g_89},{NULL,&g_101[0][0][0],&l_1443},{&l_1422,&l_1420,&g_89},{&g_10,NULL,&l_1443},{&g_10,&g_89,&g_89}},{{&g_89,&l_1421,&l_1422},{&g_89,&l_1422,&g_10},{&g_10,NULL,&g_89},{&g_10,&l_1422,&l_1422},{&l_1422,NULL,NULL},{NULL,&l_1422,NULL},{NULL,&l_1421,NULL},{&l_1443,&g_89,NULL},{NULL,NULL,&l_1422}},{{&l_1421,&l_1420,&g_89},{NULL,&g_101[0][0][0],&l_1421},{&g_10,&g_10,&l_1420},{&g_89,&g_10,&l_1422},{&l_1423,&l_1443,&g_10},{&g_101[0][0][0],&l_1422,NULL},{&l_1421,&l_1423,&g_10},{&g_89,&l_1422,&l_1422},{&g_89,&g_10,&l_1420}}};
+ uint8_t l_1460[9][9][3] = {{{250UL,0UL,0UL},{250UL,250UL,0UL},{255UL,0UL,0UL},{0UL,255UL,0UL},{255UL,255UL,255UL},{250UL,0UL,0UL},{250UL,250UL,0UL},{255UL,0UL,0UL},{0UL,255UL,0UL}},{{255UL,255UL,255UL},{250UL,0UL,0UL},{250UL,250UL,0UL},{255UL,0UL,0UL},{0UL,255UL,0UL},{255UL,255UL,255UL},{250UL,0UL,0UL},{250UL,250UL,0UL},{255UL,0UL,0UL}},{{0UL,255UL,0UL},{255UL,255UL,255UL},{250UL,0UL,0UL},{250UL,250UL,0UL},{255UL,0UL,0UL},{0UL,255UL,0UL},{255UL,255UL,255UL},{250UL,0UL,0UL},{250UL,250UL,0UL}},{{255UL,0UL,0UL},{0UL,255UL,0UL},{255UL,255UL,255UL},{250UL,0UL,0UL},{250UL,250UL,0UL},{255UL,0UL,0UL},{0UL,255UL,0UL},{255UL,255UL,255UL},{250UL,0UL,0UL}},{{250UL,250UL,0UL},{255UL,0UL,0UL},{0UL,255UL,0UL},{255UL,255UL,255UL},{250UL,0UL,0UL},{250UL,250UL,0UL},{255UL,0UL,0UL},{0UL,255UL,0UL},{255UL,255UL,255UL}},{{250UL,0UL,0UL},{250UL,250UL,0UL},{255UL,0UL,0UL},{0UL,255UL,0UL},{255UL,255UL,255UL},{250UL,0UL,0UL},{250UL,250UL,0UL},{255UL,0UL,0UL},{0UL,255UL,0UL}},{{255UL,255UL,255UL},{250UL,0UL,0UL},{0UL,0UL,255UL},{0UL,255UL,255UL},{255UL,250UL,255UL},{0UL,250UL,0UL},{0UL,255UL,255UL},{0UL,0UL,255UL},{0UL,255UL,255UL}},{{255UL,250UL,255UL},{0UL,250UL,0UL},{0UL,255UL,255UL},{0UL,0UL,255UL},{0UL,255UL,255UL},{255UL,250UL,255UL},{0UL,250UL,0UL},{0UL,255UL,255UL},{0UL,0UL,255UL}},{{0UL,255UL,255UL},{255UL,250UL,255UL},{0UL,250UL,0UL},{0UL,255UL,255UL},{0UL,0UL,255UL},{0UL,255UL,255UL},{255UL,250UL,255UL},{0UL,250UL,0UL},{0UL,255UL,255UL}}};
+ int i, j, k;
+ (*l_1453) = l_1458[0][6][1];
+ --l_1460[3][2][1];
+ }
+ else
+ { /* block id: 659 */
+ (*g_88) = (((*g_691) = p_70) <= 65534UL);
+ }
+ return g_1463;
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_912
+ * writes: g_735 g_88
+ */
+static uint8_t func_76(uint8_t p_77, const int32_t * const p_78, int32_t * p_79)
+{ /* block id: 640 */
+ int32_t **l_1411 = &g_735;
+ int32_t **l_1412 = &g_88;
+ (*l_1412) = func_80(((*l_1411) = p_79));
+ (*l_1412) = p_79;
+ return g_912;
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads :
+ * writes:
+ */
+static int32_t * const func_80(int32_t * p_81)
+{ /* block id: 638 */
+ return p_81;
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads :
+ * writes:
+ */
+static int32_t * func_82(int32_t p_83, uint16_t p_84, int32_t * p_85)
+{ /* block id: 13 */
+ int32_t l_592[2];
+ const int32_t l_595[2][2][1] = {{{(-1L)},{(-1L)}},{{(-1L)},{(-1L)}}};
+ const int8_t l_598 = 0xC0L;
+ uint16_t *l_610 = &g_168;
+ int8_t l_655 = 1L;
+ int32_t l_656[8][1][1] = {{{4L}},{{4L}},{{0xD2B475C6L}},{{4L}},{{4L}},{{0xD2B475C6L}},{{4L}},{{4L}}};
+ uint32_t l_663 = 0UL;
+ int16_t l_678 = 0x00A6L;
+ int16_t l_680 = 0L;
+ int32_t ***l_715 = NULL;
+ int16_t * const *l_864[10];
+ uint32_t l_907[10] = {0x8FD9B42AL,0xCB637439L,0x8FD9B42AL,0x8FD9B42AL,0xCB637439L,0x8FD9B42AL,0x8FD9B42AL,0xCB637439L,0x8FD9B42AL,0x8FD9B42AL};
+ int8_t l_911 = (-9L);
+ int32_t l_964 = 0xA692B646L;
+ int32_t l_1012 = (-9L);
+ int32_t l_1093[4][3][8] = {{{2L,9L,(-3L),9L,2L,0L,0x9A570B86L,1L},{0L,0x56E35751L,2L,(-1L),0xB912FE8EL,0L,9L,9L},{0x9BC7F200L,0x19546F1DL,2L,2L,0x19546F1DL,0x9BC7F200L,0x9A570B86L,0xB912FE8EL}},{{0xB912FE8EL,0x68511652L,(-3L),1L,9L,(-1L),0x9BC7F200L,0L},{(-3L),0x67113F6AL,0L,1L,0L,0x67113F6AL,(-3L),0xB912FE8EL},{0x19546F1DL,0L,0x56E35751L,2L,(-1L),0xB912FE8EL,0L,9L}},{{1L,0xE0D73146L,0x33C53D7FL,(-1L),(-1L),0x33C53D7FL,0xE0D73146L,1L},{0x19546F1DL,1L,0x67113F6AL,9L,0L,0xE0D73146L,0x56E35751L,0x68511652L},{(-3L),0x9BC7F200L,4L,0xE0D73146L,9L,0xE0D73146L,4L,0x9BC7F200L}},{{0xB912FE8EL,1L,0x68511652L,0x9A570B86L,0x19546F1DL,0x33C53D7FL,0L,4L},{0x9BC7F200L,0xE0D73146L,(-1L),0L,0xB912FE8EL,0xB912FE8EL,0L,(-1L)},{0L,0L,0x68511652L,0x33C53D7FL,2L,0x67113F6AL,(-1L),1L}}};
+ int32_t l_1120 = 0x0B67F3DBL;
+ uint16_t l_1130 = 7UL;
+ uint8_t l_1193[7][9][3] = {{{0x19L,0x45L,251UL},{246UL,1UL,0x9BL},{255UL,0UL,0UL},{0x90L,255UL,0x37L},{0x96L,0x19L,255UL},{0x96L,0xE8L,253UL},{0x90L,0xC2L,250UL},{255UL,255UL,251UL},{246UL,0xB5L,0xABL}},{{0x19L,255UL,0x90L},{1UL,0xC2L,4UL},{255UL,0xE8L,0x42L},{8UL,0x19L,0x42L},{249UL,255UL,4UL},{0UL,0UL,0x90L},{8UL,1UL,0xABL},{0UL,0x45L,251UL},{8UL,0x73L,250UL}},{{0UL,246UL,253UL},{249UL,8UL,255UL},{8UL,8UL,0x37L},{255UL,246UL,0UL},{1UL,0x73L,0x9BL},{0x19L,0x45L,251UL},{246UL,1UL,0x9BL},{255UL,0UL,0UL},{0x90L,255UL,0x37L}},{{0x96L,0x19L,255UL},{0x96L,0xE8L,253UL},{0x90L,0xC2L,250UL},{255UL,255UL,251UL},{246UL,0xB5L,0xABL},{0x19L,255UL,0x90L},{1UL,0xC2L,4UL},{255UL,0xE8L,0x42L},{8UL,0x19L,0x42L}},{{249UL,255UL,4UL},{0UL,0UL,0x90L},{8UL,1UL,0xABL},{0UL,0x45L,251UL},{8UL,0x73L,250UL},{0UL,246UL,253UL},{249UL,8UL,255UL},{8UL,8UL,0x37L},{255UL,246UL,0UL}},{{1UL,0x73L,0x9BL},{0x19L,0x45L,251UL},{246UL,1UL,0x9BL},{255UL,0UL,0UL},{0x90L,255UL,0x37L},{0x96L,0x19L,255UL},{0x96L,0xE8L,253UL},{0x90L,0xC2L,250UL},{255UL,255UL,251UL}},{{246UL,0xB5L,0xABL},{0x19L,255UL,0x90L},{1UL,0xC2L,4UL},{255UL,0xE8L,0x42L},{8UL,0x19L,0x42L},{249UL,255UL,4UL},{0UL,0UL,0x90L},{8UL,1UL,0xABL},{0UL,0x45L,251UL}}};
+ uint32_t l_1214 = 0xA67816D7L;
+ int8_t **l_1230 = &g_207[2];
+ int32_t *l_1239 = &l_656[3][0][0];
+ int16_t ** const *l_1292 = &g_435;
+ int16_t ** const **l_1291 = &l_1292;
+ int32_t l_1329 = 0L;
+ int16_t ***l_1339 = &g_435;
+ uint32_t l_1340 = 0xE0FECC7EL;
+ const uint32_t ***l_1369 = NULL;
+ int i, j, k;
+ for (i = 0; i < 2; i++)
+ l_592[i] = 0x6EF68121L;
+ for (i = 0; i < 10; i++)
+ l_864[i] = NULL;
+ for (p_84 = 14; (p_84 == 60); p_84 = safe_add_func_int16_t_s_s(p_84, 4))
+ { /* block id: 16 */
+ int32_t *l_594[4];
+ int32_t **l_593 = &l_594[2];
+ int32_t l_616 = (-1L);
+ int32_t l_619 = 1L;
+ int16_t * const l_648[5] = {&g_175,&g_175,&g_175,&g_175,&g_175};
+ int32_t l_653[4][1];
+ uint32_t l_681 = 1UL;
+ int8_t **l_876 = NULL;
+ int8_t l_904 = 0x2AL;
+ uint32_t l_908 = 0xDB682572L;
+ int32_t l_910 = (-10L);
+ int16_t l_1180[6];
+ int8_t l_1233 = (-9L);
+ int16_t l_1234 = 1L;
+ int32_t l_1306 = 1L;
+ int32_t l_1323 = 1L;
+ uint8_t l_1400[3][9];
+ int i, j;
+ for (i = 0; i < 4; i++)
+ l_594[i] = &g_8[0];
+ for (i = 0; i < 4; i++)
+ {
+ for (j = 0; j < 1; j++)
+ l_653[i][j] = (-2L);
+ }
+ for (i = 0; i < 6; i++)
+ l_1180[i] = 0x47ABL;
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 9; j++)
+ l_1400[i][j] = 0x4EL;
+ }
+ }
+ return &g_10;
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_88 g_89
+ * writes:
+ */
+static int32_t func_92(const uint16_t * p_93)
+{ /* block id: 17 */
+ uint8_t l_96 = 0x79L;
+ uint8_t l_135 = 0xE2L;
+ int32_t l_145 = 0x9B5C0F6DL;
+ const int32_t *l_153 = NULL;
+ int32_t l_157 = 0xF2D310D2L;
+ int32_t *l_182[6] = {&g_8[2],NULL,&g_8[2],&g_8[2],NULL,&g_8[2]};
+ int32_t **l_181 = &l_182[3];
+ int32_t l_195 = 0x4882324AL;
+ uint8_t l_196[9] = {0x74L,0xD3L,0x74L,0xD3L,0x74L,0xD3L,0x74L,0xD3L,0x74L};
+ uint8_t l_241 = 0x45L;
+ int32_t *l_244 = &l_195;
+ uint16_t *l_266 = NULL;
+ int32_t ***l_312 = &l_181;
+ uint16_t l_333 = 65532UL;
+ uint16_t l_407 = 0UL;
+ uint8_t l_455 = 1UL;
+ int16_t **l_473 = NULL;
+ const int32_t *l_494 = &l_145;
+ int32_t l_513 = (-1L);
+ int16_t l_567 = 0x6F4BL;
+ int32_t *l_589 = &l_513;
+ int i;
+ return (*g_88);
+}
+
+
+
+
+/* ---------------------------------------- */
+int main (int argc, char* argv[])
+{
+ int i, j, k;
+ int print_hash_value = 0;
+ if (argc == 2 && strcmp(argv[1], "1") == 0) print_hash_value = 1;
+ platform_main_begin();
+ crc32_gentab();
+ func_1();
+ for (i = 0; i < 4; i++)
+ {
+ transparent_crc(g_8[i], "g_8[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ transparent_crc(g_10, "g_10", print_hash_value);
+ transparent_crc(g_14, "g_14", print_hash_value);
+ transparent_crc(g_68, "g_68", print_hash_value);
+ transparent_crc(g_89, "g_89", print_hash_value);
+ transparent_crc(g_95, "g_95", print_hash_value);
+ for (i = 0; i < 1; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ for (k = 0; k < 5; k++)
+ {
+ transparent_crc(g_101[i][j][k], "g_101[i][j][k]", print_hash_value);
+ if (print_hash_value) printf("index = [%d][%d][%d]\n", i, j, k);
+
+ }
+ }
+ }
+ transparent_crc(g_168, "g_168", print_hash_value);
+ transparent_crc(g_175, "g_175", print_hash_value);
+ transparent_crc(g_177, "g_177", print_hash_value);
+ transparent_crc(g_208, "g_208", print_hash_value);
+ transparent_crc(g_263, "g_263", print_hash_value);
+ for (i = 0; i < 4; i++)
+ {
+ for (j = 0; j < 1; j++)
+ {
+ for (k = 0; k < 5; k++)
+ {
+ transparent_crc(g_324[i][j][k], "g_324[i][j][k]", print_hash_value);
+ if (print_hash_value) printf("index = [%d][%d][%d]\n", i, j, k);
+
+ }
+ }
+ }
+ transparent_crc(g_369, "g_369", print_hash_value);
+ transparent_crc(g_490, "g_490", print_hash_value);
+ transparent_crc(g_532, "g_532", print_hash_value);
+ transparent_crc(g_534, "g_534", print_hash_value);
+ for (i = 0; i < 1; i++)
+ {
+ for (j = 0; j < 5; j++)
+ {
+ transparent_crc(g_679[i][j], "g_679[i][j]", print_hash_value);
+ if (print_hash_value) printf("index = [%d][%d]\n", i, j);
+
+ }
+ }
+ transparent_crc(g_813, "g_813", print_hash_value);
+ transparent_crc(g_906, "g_906", print_hash_value);
+ transparent_crc(g_912, "g_912", print_hash_value);
+ transparent_crc(g_1098, "g_1098", print_hash_value);
+ transparent_crc(g_1555, "g_1555", print_hash_value);
+ transparent_crc(g_1566, "g_1566", print_hash_value);
+ transparent_crc(g_1611, "g_1611", print_hash_value);
+ for (i = 0; i < 8; i++)
+ {
+ transparent_crc(g_1671[i], "g_1671[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ transparent_crc(g_1726, "g_1726", print_hash_value);
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ transparent_crc(g_1781[i][j], "g_1781[i][j]", print_hash_value);
+ if (print_hash_value) printf("index = [%d][%d]\n", i, j);
+
+ }
+ }
+ for (i = 0; i < 4; i++)
+ {
+ transparent_crc(g_1846[i], "g_1846[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ for (i = 0; i < 9; i++)
+ {
+ for (j = 0; j < 9; j++)
+ {
+ for (k = 0; k < 3; k++)
+ {
+ transparent_crc(g_1878[i][j][k], "g_1878[i][j][k]", print_hash_value);
+ if (print_hash_value) printf("index = [%d][%d][%d]\n", i, j, k);
+
+ }
+ }
+ }
+ transparent_crc(g_2002, "g_2002", print_hash_value);
+ platform_main_end(crc32_context ^ 0xFFFFFFFFUL, print_hash_value);
+ return 0;
+}
+
+/************************ statistics *************************
+XXX max struct depth: 0
+breakdown:
+ depth: 0, occurrence: 489
+XXX total union variables: 0
+
+XXX non-zero bitfields defined in structs: 0
+XXX zero bitfields defined in structs: 0
+XXX const bitfields defined in structs: 0
+XXX volatile bitfields defined in structs: 0
+XXX structs with bitfields in the program: 0
+breakdown:
+XXX full-bitfields structs in the program: 0
+breakdown:
+XXX times a bitfields struct's address is taken: 0
+XXX times a bitfields struct on LHS: 0
+XXX times a bitfields struct on RHS: 0
+XXX times a single bitfield on LHS: 0
+XXX times a single bitfield on RHS: 0
+
+XXX max expression depth: 60
+breakdown:
+ depth: 1, occurrence: 97
+ depth: 2, occurrence: 14
+ depth: 3, occurrence: 5
+ depth: 4, occurrence: 1
+ depth: 8, occurrence: 1
+ depth: 9, occurrence: 1
+ depth: 18, occurrence: 2
+ depth: 19, occurrence: 2
+ depth: 20, occurrence: 1
+ depth: 22, occurrence: 1
+ depth: 24, occurrence: 2
+ depth: 26, occurrence: 1
+ depth: 28, occurrence: 1
+ depth: 31, occurrence: 1
+ depth: 33, occurrence: 2
+ depth: 35, occurrence: 1
+ depth: 39, occurrence: 1
+ depth: 40, occurrence: 1
+ depth: 41, occurrence: 1
+ depth: 60, occurrence: 1
+
+XXX total number of pointers: 435
+
+XXX times a variable address is taken: 1134
+XXX times a pointer is dereferenced on RHS: 320
+breakdown:
+ depth: 1, occurrence: 285
+ depth: 2, occurrence: 27
+ depth: 3, occurrence: 8
+XXX times a pointer is dereferenced on LHS: 267
+breakdown:
+ depth: 1, occurrence: 244
+ depth: 2, occurrence: 16
+ depth: 3, occurrence: 6
+ depth: 4, occurrence: 1
+XXX times a pointer is compared with null: 45
+XXX times a pointer is compared with address of another variable: 4
+XXX times a pointer is compared with another pointer: 14
+XXX times a pointer is qualified to be dereferenced: 7978
+
+XXX max dereference level: 6
+breakdown:
+ level: 0, occurrence: 0
+ level: 1, occurrence: 1190
+ level: 2, occurrence: 134
+ level: 3, occurrence: 79
+ level: 4, occurrence: 27
+ level: 5, occurrence: 11
+ level: 6, occurrence: 13
+XXX number of pointers point to pointers: 171
+XXX number of pointers point to scalars: 264
+XXX number of pointers point to structs: 0
+XXX percent of pointers has null in alias set: 25.5
+XXX average alias set size: 1.48
+
+XXX times a non-volatile is read: 1625
+XXX times a non-volatile is write: 810
+XXX times a volatile is read: 0
+XXX times read thru a pointer: 0
+XXX times a volatile is write: 0
+XXX times written thru a pointer: 0
+XXX times a volatile is available for access: 0
+XXX percentage of non-volatile access: 100
+
+XXX forward jumps: 1
+XXX backward jumps: 5
+
+XXX stmts: 92
+XXX max block depth: 5
+breakdown:
+ depth: 0, occurrence: 28
+ depth: 1, occurrence: 11
+ depth: 2, occurrence: 6
+ depth: 3, occurrence: 9
+ depth: 4, occurrence: 16
+ depth: 5, occurrence: 22
+
+XXX percentage a fresh-made variable is used: 15.8
+XXX percentage an existing variable is used: 84.2
+********************* end of statistics **********************/
+
diff --git a/tests/fuzz/20.cpp.txt b/tests/fuzz/20.cpp.txt
new file mode 100644
index 00000000..3bff09b8
--- /dev/null
+++ b/tests/fuzz/20.cpp.txt
@@ -0,0 +1 @@
+checksum = D5BDABA9
diff --git a/tests/fuzz/21.c b/tests/fuzz/21.c
new file mode 100644
index 00000000..28720f01
--- /dev/null
+++ b/tests/fuzz/21.c
@@ -0,0 +1,2332 @@
+/*
+ * This is a RANDOMLY GENERATED PROGRAM.
+ *
+ * Generator: csmith 2.2.0
+ * Git version: bf42ffd
+ * Options: --no-volatiles --no-packed-struct
+ * Seed: 642934944
+ */
+
+#include "csmith.h"
+
+
+static long __undefined;
+
+/* --- Struct/Union Declarations --- */
+union U0 {
+ int8_t f0;
+ int8_t f1;
+ int16_t f2;
+ int8_t f3;
+};
+
+/* --- GLOBAL VARIABLES --- */
+static int32_t g_4[5] = {0x21DED680L,0x21DED680L,0x21DED680L,0x21DED680L,0x21DED680L};
+static int32_t g_20 = 0L;
+static int32_t g_67[7] = {2L,2L,2L,2L,2L,2L,2L};
+static int32_t g_75[3] = {2L,2L,2L};
+static uint16_t g_78 = 0x7081L;
+static int64_t g_91 = 0xAECDC9E869F92A77LL;
+static int64_t g_128[2][4][3] = {{{4L,(-7L),4L},{4L,0x14A00EA68498C81BLL,(-7L)},{0x14A00EA68498C81BLL,4L,4L},{(-7L),4L,0L}},{{(-1L),0x14A00EA68498C81BLL,1L},{(-7L),(-7L),1L},{0x14A00EA68498C81BLL,(-1L),0L},{4L,(-7L),4L}}};
+static int64_t *g_127 = &g_128[0][3][1];
+static uint8_t g_130 = 8UL;
+static uint64_t g_132 = 18446744073709551615UL;
+static uint64_t g_133 = 1UL;
+static int32_t g_135 = 1L;
+static int32_t g_146 = 0x0234A52FL;
+static uint32_t g_147 = 0x4143BCCAL;
+static uint32_t g_159 = 0x38252909L;
+static uint16_t g_177 = 1UL;
+static uint8_t g_183 = 0xB9L;
+static uint32_t g_204 = 6UL;
+static uint8_t g_206 = 0UL;
+static union U0 g_209 = {0xF0L};
+static int64_t g_253 = 0xFB460BE9092F00DDLL;
+static uint32_t g_254 = 0xA3D898C3L;
+static uint32_t g_258[8] = {18446744073709551615UL,0x8629A8D4L,18446744073709551615UL,0x8629A8D4L,18446744073709551615UL,0x8629A8D4L,18446744073709551615UL,0x8629A8D4L};
+static const int32_t *g_268 = &g_4[3];
+static const int32_t **g_267 = &g_268;
+static const uint16_t g_274 = 0xF497L;
+static int64_t **g_277[1] = {&g_127};
+static int64_t ***g_276 = &g_277[0];
+static uint64_t *g_333[8][2] = {{&g_133,&g_132},{&g_133,&g_132},{&g_133,&g_133},{(void*)0,(void*)0},{(void*)0,&g_133},{&g_133,&g_132},{&g_133,&g_132},{&g_133,&g_133}};
+static uint16_t g_380 = 0x0529L;
+static int16_t g_383 = 1L;
+static int16_t g_384 = 0xD1D2L;
+static int16_t g_408 = 0x2866L;
+static uint16_t g_409[1][4] = {{0xA1F1L,0xA1F1L,0xA1F1L,0xA1F1L}};
+static uint8_t *g_442 = (void*)0;
+static uint8_t **g_441 = &g_442;
+static union U0 g_458 = {0x3BL};
+static union U0 *g_457 = &g_458;
+static int32_t g_471 = 0L;
+static uint16_t g_578 = 0UL;
+static uint64_t g_629 = 0UL;
+static uint16_t *g_643 = &g_177;
+static uint16_t **g_642 = &g_643;
+static uint32_t *g_648 = &g_258[5];
+static uint32_t **g_647[9][8] = {{(void*)0,(void*)0,&g_648,(void*)0,(void*)0,&g_648,&g_648,&g_648},{(void*)0,&g_648,(void*)0,&g_648,&g_648,(void*)0,&g_648,(void*)0},{&g_648,&g_648,(void*)0,&g_648,&g_648,(void*)0,&g_648,&g_648},{&g_648,&g_648,&g_648,&g_648,&g_648,(void*)0,(void*)0,(void*)0},{(void*)0,&g_648,&g_648,&g_648,&g_648,(void*)0,&g_648,&g_648},{(void*)0,&g_648,(void*)0,&g_648,&g_648,&g_648,(void*)0,&g_648},{&g_648,(void*)0,(void*)0,&g_648,&g_648,&g_648,&g_648,&g_648},{&g_648,&g_648,&g_648,&g_648,&g_648,&g_648,&g_648,(void*)0},{(void*)0,&g_648,(void*)0,&g_648,(void*)0,&g_648,(void*)0,&g_648}};
+static int8_t g_708 = (-6L);
+static int64_t g_746 = 0xB223B77F3AA8293ALL;
+static int64_t g_778 = 0x798751D9133BB1D3LL;
+static uint64_t ** const g_856 = &g_333[7][0];
+static uint64_t ** const *g_855 = &g_856;
+static uint16_t g_888 = 0x8340L;
+static uint8_t *g_983 = &g_130;
+static int32_t *g_1000 = &g_20;
+static int32_t **g_999 = &g_1000;
+static int64_t g_1086 = 8L;
+static int32_t ***g_1175 = &g_999;
+static const union U0 ***g_1185 = (void*)0;
+static int8_t g_1326 = 0x8EL;
+static int64_t **g_1334 = (void*)0;
+static const int64_t g_1337 = 0L;
+static int8_t g_1413 = (-3L);
+static uint64_t **g_1569[9] = {(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0};
+static uint64_t ***g_1568[5][3] = {{&g_1569[6],&g_1569[6],&g_1569[5]},{&g_1569[5],&g_1569[2],&g_1569[6]},{&g_1569[1],&g_1569[6],&g_1569[1]},{&g_1569[1],&g_1569[5],&g_1569[6]},{&g_1569[5],&g_1569[1],&g_1569[1]}};
+static uint64_t ****g_1567 = &g_1568[4][0];
+static uint16_t * const *g_1574 = &g_643;
+static uint16_t * const **g_1573[3] = {&g_1574,&g_1574,&g_1574};
+static uint64_t g_1585 = 0x597575CF89740C88LL;
+static const int8_t g_1622 = 8L;
+static int32_t g_1679 = (-2L);
+static uint32_t *g_1701 = &g_254;
+static uint32_t **g_1700 = &g_1701;
+static int32_t *g_1707 = (void*)0;
+static const int16_t *g_1739 = &g_384;
+static const int16_t ** const g_1738[3][1][7] = {{{&g_1739,&g_1739,&g_1739,&g_1739,(void*)0,&g_1739,&g_1739}},{{&g_1739,&g_1739,&g_1739,&g_1739,&g_1739,&g_1739,&g_1739}},{{&g_1739,&g_1739,(void*)0,&g_1739,&g_1739,&g_1739,&g_1739}}};
+static const int16_t **g_1744 = &g_1739;
+static uint32_t g_1860 = 0x5534D26BL;
+static uint32_t ***g_1926[3] = {(void*)0,(void*)0,(void*)0};
+static int32_t g_1962 = (-2L);
+static int32_t g_2033[10] = {0x3E7186E9L,0x3E7186E9L,0x3E7186E9L,0x3E7186E9L,0x3E7186E9L,0x3E7186E9L,0x3E7186E9L,0x3E7186E9L,0x3E7186E9L,0x3E7186E9L};
+static uint32_t ** const ***g_2089 = (void*)0;
+static union U0 g_2193 = {0xBDL};
+static int16_t **g_2230 = (void*)0;
+static int64_t g_2307 = 0L;
+static uint32_t g_2497 = 0xD94C2BE8L;
+static int32_t g_2508 = 0xB8F83451L;
+static int32_t * const *g_2622 = &g_1000;
+static int32_t * const **g_2621 = &g_2622;
+static int32_t * const ***g_2620 = &g_2621;
+static const uint16_t *g_2632 = &g_380;
+static const uint16_t **g_2631 = &g_2632;
+static const uint16_t ***g_2630[9] = {&g_2631,&g_2631,&g_2631,&g_2631,&g_2631,&g_2631,&g_2631,&g_2631,&g_2631};
+static uint32_t g_2648 = 0x9D64EF08L;
+static int32_t g_2767 = 0x9B96E27FL;
+static uint64_t g_2797 = 18446744073709551615UL;
+static uint64_t g_2866 = 0x116C815868EB1DEBLL;
+static uint32_t g_2895 = 8UL;
+static int32_t ****g_2978 = &g_1175;
+static uint16_t *** const *g_2981 = (void*)0;
+static uint16_t *** const ** const g_2980 = &g_2981;
+static uint16_t **g_3116 = &g_643;
+static uint8_t g_3176[4] = {251UL,251UL,251UL,251UL};
+static int8_t g_3254 = 0xDDL;
+static int64_t g_3261 = 8L;
+static uint32_t ***g_3310 = &g_647[5][0];
+static uint32_t ***g_3311 = &g_647[5][0];
+static uint32_t g_3322[7] = {0x55EF5714L,0x55EF5714L,0x55EF5714L,0x55EF5714L,0x55EF5714L,0x55EF5714L,0x55EF5714L};
+static int8_t *g_3328 = (void*)0;
+static uint16_t g_3340 = 0x2720L;
+static const uint16_t **** const g_3349 = &g_2630[4];
+static const uint16_t **** const *g_3348 = &g_3349;
+static int32_t g_3407 = 0xDAD5159FL;
+static uint32_t g_3485 = 0xEE071645L;
+static int32_t g_3515 = 0xC406C7B2L;
+static int32_t g_3578 = 8L;
+static int16_t **** const g_3593 = (void*)0;
+static uint32_t ****g_3601 = &g_1926[2];
+static uint32_t *****g_3600[7][3][8] = {{{&g_3601,&g_3601,(void*)0,&g_3601,&g_3601,&g_3601,&g_3601,&g_3601},{&g_3601,(void*)0,&g_3601,&g_3601,&g_3601,&g_3601,(void*)0,(void*)0},{&g_3601,(void*)0,&g_3601,(void*)0,&g_3601,(void*)0,(void*)0,&g_3601}},{{&g_3601,&g_3601,&g_3601,&g_3601,&g_3601,&g_3601,&g_3601,&g_3601},{&g_3601,&g_3601,&g_3601,(void*)0,&g_3601,&g_3601,&g_3601,(void*)0},{(void*)0,&g_3601,(void*)0,&g_3601,(void*)0,&g_3601,&g_3601,&g_3601}},{{&g_3601,&g_3601,&g_3601,&g_3601,&g_3601,(void*)0,&g_3601,&g_3601},{&g_3601,(void*)0,&g_3601,&g_3601,(void*)0,(void*)0,&g_3601,&g_3601},{(void*)0,&g_3601,(void*)0,(void*)0,&g_3601,&g_3601,&g_3601,(void*)0}},{{(void*)0,(void*)0,(void*)0,&g_3601,&g_3601,&g_3601,&g_3601,&g_3601},{&g_3601,&g_3601,&g_3601,&g_3601,&g_3601,&g_3601,&g_3601,&g_3601},{&g_3601,&g_3601,&g_3601,&g_3601,(void*)0,(void*)0,&g_3601,&g_3601}},{{&g_3601,&g_3601,(void*)0,&g_3601,(void*)0,&g_3601,(void*)0,&g_3601},{&g_3601,&g_3601,&g_3601,(void*)0,&g_3601,(void*)0,&g_3601,&g_3601},{&g_3601,&g_3601,&g_3601,(void*)0,&g_3601,&g_3601,&g_3601,&g_3601}},{{(void*)0,(void*)0,&g_3601,(void*)0,&g_3601,&g_3601,(void*)0,&g_3601},{&g_3601,&g_3601,(void*)0,&g_3601,&g_3601,(void*)0,&g_3601,&g_3601},{&g_3601,&g_3601,&g_3601,&g_3601,&g_3601,&g_3601,&g_3601,&g_3601}},{{&g_3601,&g_3601,&g_3601,&g_3601,&g_3601,(void*)0,&g_3601,&g_3601},{&g_3601,&g_3601,(void*)0,&g_3601,&g_3601,&g_3601,&g_3601,&g_3601},{&g_3601,&g_3601,(void*)0,&g_3601,&g_3601,&g_3601,&g_3601,&g_3601}}};
+static int16_t *g_3706 = (void*)0;
+static int16_t **g_3705 = &g_3706;
+static const uint32_t *g_3714 = &g_1860;
+static const uint32_t **g_3713[3] = {&g_3714,&g_3714,&g_3714};
+static uint64_t *****g_3772 = &g_1567;
+static uint64_t ******g_3771 = &g_3772;
+static uint32_t g_3815 = 18446744073709551615UL;
+static const uint32_t g_3847 = 4294967293UL;
+static int16_t g_3879 = 0x5935L;
+static int32_t g_3880 = 0x2FDB7342L;
+static int64_t * const g_3913 = &g_253;
+
+
+/* --- FORWARD DECLARATIONS --- */
+static int16_t func_1(void);
+static int32_t * func_13(uint8_t p_14);
+static uint64_t func_34(int32_t p_35, uint64_t p_36, int8_t p_37, int32_t * p_38);
+static union U0 func_48(int32_t * p_49, int32_t p_50);
+static int32_t * func_51(int8_t p_52, uint16_t p_53, uint16_t p_54, int32_t * p_55, int32_t * p_56);
+static int32_t * func_57(int32_t * p_58, const int32_t * p_59, int32_t * p_60, int32_t p_61, int32_t * p_62);
+static int32_t * func_63(uint32_t p_64, int32_t * p_65);
+static int32_t func_68(int32_t p_69, uint32_t p_70, int8_t p_71, int16_t p_72, int64_t p_73);
+static union U0 func_97(const int32_t * p_98);
+static const int32_t * func_99(uint16_t p_100, int16_t p_101, union U0 p_102, int64_t * const p_103, int64_t * p_104);
+
+
+/* --- FUNCTIONS --- */
+/* ------------------------------------------ */
+/*
+ * reads : g_4 g_999 g_1000 g_1175 g_983 g_130 g_457 g_458 g_642 g_1744 g_1739 g_384 g_578 g_2621 g_2622 g_20 g_276 g_277 g_2620 g_2797 g_1700 g_1701 g_254 g_253 g_127 g_128 g_2497 g_1574 g_643 g_177 g_146 g_2631 g_2632 g_380 g_648 g_258 g_274 g_268 g_209.f1 g_133 g_458.f1 g_3261 g_629 g_458.f3 g_2033 g_3322 g_132 g_3340 g_2895 g_3348 g_888 g_2193.f1 g_441 g_442 g_267 g_746 g_3116 g_408 g_471 g_209 g_3485 g_75 g_2978 g_2980 g_2981 g_3349 g_1738 g_147 g_78 g_458.f2 g_1679 g_91 g_159 g_135 g_67 g_183 g_206 g_204 g_209.f0 g_209.f3 g_856 g_333 g_458.f0 g_3593 g_778 g_3176 g_3578 g_1337 g_2630 g_409 g_1086 g_3713 g_3771 g_3714 g_1860 g_1567 g_1568 g_1185 g_3515 g_3815 g_3847 g_3310 g_647 g_3879 g_3772 g_3913 g_3407
+ * writes: g_4 g_20 g_1000 g_643 g_277 g_2797 g_3176 g_146 g_254 g_177 g_128 g_2193.f1 g_209.f1 g_130 g_133 g_629 g_458.f3 g_441 g_3328 g_132 g_3340 g_2895 g_3348 g_888 g_268 g_457 g_75 g_408 g_3485 g_1744 g_458.f2 g_1567 g_1679 g_127 g_147 g_159 g_183 g_135 g_204 g_206 g_258 g_267 g_333 g_3515 g_3600 g_209 g_3578 g_384 g_1086 g_3705 g_3713 g_1568 g_91 g_3879 g_3407 g_3254 g_458
+ */
+static int16_t func_1(void)
+{ /* block id: 0 */
+ uint32_t l_2 = 4294967295UL;
+ int32_t l_5 = 0x8A527335L;
+ int32_t l_6 = 0x11BC383CL;
+ int32_t l_7 = 0x79041289L;
+ uint16_t ** const *l_3150 = &g_642;
+ int8_t *l_3158 = &g_2193.f1;
+ union U0 *l_3298 = &g_209;
+ uint32_t ***l_3308 = &g_647[7][6];
+ uint32_t **l_3346[6][8] = {{&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701},{&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701},{&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701},{&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701},{&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701},{&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701}};
+ int32_t l_3362 = 0x16A6D5DAL;
+ int32_t l_3363 = 0L;
+ int32_t l_3368 = 1L;
+ int32_t l_3369 = (-1L);
+ int32_t l_3370 = 0x7D45392EL;
+ int32_t l_3371 = (-10L);
+ int64_t l_3374 = 0L;
+ uint64_t l_3375 = 0x3D38361B79A4DC58LL;
+ uint64_t *****l_3385 = &g_1567;
+ uint16_t l_3419[4];
+ int8_t l_3446[6] = {2L,2L,2L,2L,2L,2L};
+ uint32_t l_3495 = 18446744073709551615UL;
+ const union U0 *l_3532 = &g_458;
+ const union U0 **l_3531 = &l_3532;
+ const union U0 ***l_3530 = &l_3531;
+ int8_t l_3544 = 0L;
+ uint8_t l_3580 = 255UL;
+ int16_t * const l_3597 = &g_384;
+ int16_t * const *l_3596 = &l_3597;
+ int16_t * const **l_3595 = &l_3596;
+ uint64_t l_3656 = 0x5FE4D132F8BD5F31LL;
+ int16_t l_3664 = 0xE475L;
+ int16_t *l_3704 = &g_384;
+ int16_t **l_3703 = &l_3704;
+ int32_t l_3735 = 0x57B5ED23L;
+ int32_t l_3736 = 0xEE9E89C4L;
+ const uint32_t ***l_3825[2][1];
+ uint8_t l_3908 = 5UL;
+ uint64_t **** const *l_3909[6];
+ int32_t l_3912[4];
+ int32_t l_3944 = 0x194E005FL;
+ uint32_t l_3950 = 0UL;
+ uint32_t ******l_3989 = &g_3600[3][1][4];
+ uint16_t l_4017 = 0x3BADL;
+ int i, j;
+ for (i = 0; i < 4; i++)
+ l_3419[i] = 0x9737L;
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 1; j++)
+ l_3825[i][j] = &g_3713[1];
+ }
+ for (i = 0; i < 6; i++)
+ l_3909[i] = &g_1567;
+ for (i = 0; i < 4; i++)
+ l_3912[i] = (-2L);
+ if ((l_2 & 0x3E90A624CDB8FAAALL))
+ { /* block id: 1 */
+ int32_t *l_3[8][10][2];
+ uint16_t l_8[9] = {0x26AFL,0x26AFL,0x26AFL,0x26AFL,0x26AFL,0x26AFL,0x26AFL,0x26AFL,0x26AFL};
+ uint32_t ** const *l_3144[9][2][5] = {{{&g_1700,&g_1700,&g_1700,&g_1700,&g_1700},{&g_1700,&g_1700,&g_1700,&g_1700,&g_1700}},{{&g_1700,&g_1700,&g_1700,&g_1700,&g_1700},{&g_1700,&g_1700,&g_1700,&g_1700,(void*)0}},{{&g_1700,(void*)0,&g_1700,&g_1700,&g_1700},{&g_1700,(void*)0,&g_1700,&g_1700,&g_1700}},{{&g_1700,(void*)0,&g_1700,(void*)0,(void*)0},{&g_1700,(void*)0,&g_1700,&g_1700,&g_1700}},{{&g_1700,&g_1700,&g_1700,&g_1700,(void*)0},{&g_1700,&g_1700,&g_1700,&g_1700,&g_1700}},{{&g_1700,&g_1700,&g_1700,(void*)0,&g_1700},{&g_1700,&g_1700,&g_1700,(void*)0,(void*)0}},{{&g_1700,&g_1700,&g_1700,(void*)0,&g_1700},{&g_1700,&g_1700,&g_1700,(void*)0,&g_1700}},{{&g_1700,(void*)0,&g_1700,(void*)0,&g_1700},{&g_1700,&g_1700,&g_1700,(void*)0,&g_1700}},{{&g_1700,&g_1700,&g_1700,&g_1700,&g_1700},{&g_1700,&g_1700,&g_1700,&g_1700,&g_1700}}};
+ uint32_t ** const **l_3143 = &l_3144[0][0][3];
+ uint32_t ** const ***l_3142 = &l_3143;
+ union U0 l_3228 = {0x13L};
+ uint64_t *l_3240 = &g_133;
+ uint32_t * const *l_3315 = &g_648;
+ uint32_t * const * const *l_3314 = &l_3315;
+ int32_t l_3388 = 1L;
+ uint64_t *****l_3389 = &g_1567;
+ uint8_t *l_3426 = (void*)0;
+ union U0 *l_3438 = &l_3228;
+ uint64_t l_3523 = 0x5F8208EF81CF263DLL;
+ union U0 **l_3534[7] = {&g_457,&g_457,&g_457,&g_457,&g_457,&g_457,&g_457};
+ union U0 ***l_3533 = &l_3534[5];
+ int16_t *l_3542[5];
+ int16_t l_3554 = 3L;
+ int8_t l_3590[9] = {(-8L),(-8L),(-8L),(-8L),(-8L),(-8L),(-8L),(-8L),(-8L)};
+ uint32_t *****l_3598 = (void*)0;
+ int64_t l_3625 = 9L;
+ uint16_t l_3626 = 65535UL;
+ uint32_t *l_3659 = &g_258[6];
+ int32_t l_3790[2][8] = {{0xFAB70EA6L,0L,0x05281176L,0L,0xFAB70EA6L,0xFAB70EA6L,0L,0x05281176L},{0xFAB70EA6L,0xFAB70EA6L,0L,0x05281176L,0L,0xFAB70EA6L,0xFAB70EA6L,0L}};
+ uint64_t l_3812 = 3UL;
+ uint64_t l_3814 = 18446744073709551608UL;
+ uint16_t **l_3827[3];
+ uint64_t l_3829 = 18446744073709551615UL;
+ uint32_t l_3846 = 1UL;
+ uint16_t *****l_3857 = (void*)0;
+ const uint16_t ****l_3859 = &g_2630[5];
+ const uint16_t *****l_3858 = &l_3859;
+ int i, j, k;
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 10; j++)
+ {
+ for (k = 0; k < 2; k++)
+ l_3[i][j][k] = &g_4[3];
+ }
+ }
+ for (i = 0; i < 5; i++)
+ l_3542[i] = &g_383;
+ for (i = 0; i < 3; i++)
+ l_3827[i] = &g_643;
+lbl_3151:
+ l_8[1]++;
+ for (l_6 = (-2); (l_6 > 15); l_6 = safe_add_func_uint8_t_u_u(l_6, 6))
+ { /* block id: 5 */
+ uint64_t l_3138 = 0x57C7955DEB977126LL;
+ union U0 **l_3154 = &g_457;
+ const int64_t *l_3156 = &g_128[1][0][1];
+ const int64_t **l_3155[2][2][6] = {{{&l_3156,&l_3156,&l_3156,&l_3156,&l_3156,&l_3156},{&l_3156,&l_3156,&l_3156,&l_3156,&l_3156,&l_3156}},{{&l_3156,&l_3156,&l_3156,&l_3156,&l_3156,&l_3156},{&l_3156,&l_3156,&l_3156,&l_3156,&l_3156,&l_3156}}};
+ const int64_t ***l_3157 = &l_3155[0][1][3];
+ uint16_t l_3165[8] = {1UL,1UL,1UL,1UL,1UL,1UL,1UL,1UL};
+ int i, j, k;
+ for (l_7 = 8; (l_7 >= 1); l_7 -= 1)
+ { /* block id: 8 */
+ uint32_t l_3141 = 18446744073709551615UL;
+ uint32_t * const ***l_3146 = (void*)0;
+ uint32_t * const *** const *l_3145 = &l_3146;
+ union U0 **l_3147 = &g_457;
+ int i;
+ g_4[3] |= l_8[l_7];
+ (**g_1175) = func_13(g_4[2]);
+ if (l_8[l_7])
+ { /* block id: 1459 */
+ uint16_t *l_3133 = &l_8[8];
+ uint16_t *l_3139 = &l_8[l_7];
+ int32_t l_3140 = 0xF695A281L;
+ uint16_t ***l_3149 = &g_3116;
+ uint16_t ****l_3148 = &l_3149;
+ (***g_2621) &= (safe_mod_func_uint8_t_u_u((((*l_3148) = ((((((safe_mod_func_int16_t_s_s((((safe_rshift_func_int8_t_s_u((((((safe_lshift_func_uint8_t_u_u((*g_983), (safe_rshift_func_uint16_t_u_u(l_8[l_7], (((*g_457) , ((((safe_rshift_func_int8_t_s_u(((((*g_642) = l_3133) != (((safe_mul_func_uint8_t_u_u(0x6AL, 0xD8L)) || (safe_rshift_func_uint16_t_u_s(l_3138, (**g_1744)))) , l_3139)) < 0xC0D6B72D1B8F337DLL), 1)) , l_3140) > 0L) & g_578)) >= l_3138))))) ^ l_3141) < (*g_983)) , l_3142) != l_3145), (*g_983))) > l_6) , (**g_1744)), l_6)) ^ l_3140) , (**g_1744)) , l_3147) != (void*)0) , &g_3116)) == l_3150), 0x4FL));
+ }
+ else
+ { /* block id: 1463 */
+ (**g_999) ^= l_7;
+ if (l_7)
+ goto lbl_3151;
+ }
+ }
+ (****g_2620) = (safe_rshift_func_int16_t_s_s((((((void*)0 != l_3154) , ((*g_276) = (*g_276))) == ((*l_3157) = l_3155[0][1][3])) < (l_3158 == (void*)0)), 0));
+ for (g_2797 = 0; (g_2797 >= 54); ++g_2797)
+ { /* block id: 1473 */
+ int32_t l_3166[8][8][3] = {{{0x36A42BD7L,0x08DAE5F5L,0L},{0x3FB3DE0AL,0xDD914932L,(-5L)},{7L,7L,0xD3200B0DL},{1L,(-5L),0xB59C95F6L},{9L,7L,(-5L)},{0xDD914932L,0xC624916FL,0x3FB3DE0AL},{0x36A42BD7L,9L,(-5L)},{0x97CD9E59L,0xB59C95F6L,0xB59C95F6L}},{{0L,(-1L),0x08DAE5F5L},{0L,0x08DAE5F5L,0x36A42BD7L},{0x97CD9E59L,1L,0x7D66C06FL},{0x36A42BD7L,0xDD914932L,7L},{0xDD914932L,1L,0x63FDB9F2L},{9L,0x08DAE5F5L,9L},{1L,(-1L),9L},{(-5L),0xB59C95F6L,0x63FDB9F2L}},{{0x63FDB9F2L,9L,7L},{(-1L),0xC624916FL,0x7D66C06FL},{0x63FDB9F2L,7L,0x36A42BD7L},{(-5L),(-5L),0x08DAE5F5L},{1L,(-5L),0xB59C95F6L},{9L,7L,(-5L)},{0xDD914932L,0xC624916FL,0x3FB3DE0AL},{0x36A42BD7L,9L,(-5L)}},{{0x97CD9E59L,0xB59C95F6L,0xB59C95F6L},{0L,(-1L),0x08DAE5F5L},{0L,0x08DAE5F5L,0x36A42BD7L},{0x97CD9E59L,1L,0x7D66C06FL},{0x36A42BD7L,0xDD914932L,7L},{0xDD914932L,1L,0x63FDB9F2L},{9L,0x08DAE5F5L,9L},{1L,(-1L),9L}},{{(-5L),0xB59C95F6L,0x63FDB9F2L},{0x63FDB9F2L,9L,7L},{(-1L),0xC624916FL,0x7D66C06FL},{0x63FDB9F2L,7L,0x36A42BD7L},{(-5L),(-5L),0x08DAE5F5L},{1L,(-5L),0xB59C95F6L},{9L,7L,(-5L)},{0xDD914932L,0xC624916FL,0x3FB3DE0AL}},{{0x36A42BD7L,9L,(-5L)},{0x97CD9E59L,0xB59C95F6L,0xB59C95F6L},{0L,(-1L),0x08DAE5F5L},{0L,0x08DAE5F5L,0x36A42BD7L},{0x97CD9E59L,1L,0x7D66C06FL},{0x36A42BD7L,0xDD914932L,7L},{0xDD914932L,1L,0x63FDB9F2L},{9L,0x08DAE5F5L,9L}},{{1L,(-1L),9L},{(-5L),0xB59C95F6L,0x63FDB9F2L},{0x63FDB9F2L,9L,7L},{(-1L),0xC624916FL,0x7D66C06FL},{0x63FDB9F2L,7L,0x36A42BD7L},{(-5L),(-5L),0x08DAE5F5L},{1L,(-5L),0xB59C95F6L},{9L,7L,(-5L)}},{{0xDD914932L,0xC624916FL,0x3FB3DE0AL},{0x36A42BD7L,9L,(-5L)},{0x97CD9E59L,0xB59C95F6L,0xB59C95F6L},{0L,(-1L),0x08DAE5F5L},{0L,0x08DAE5F5L,0x36A42BD7L},{0x97CD9E59L,1L,0x7D66C06FL},{0x36A42BD7L,0xDD914932L,7L},{0xDD914932L,1L,0x63FDB9F2L}}};
+ union U0 *l_3167 = (void*)0;
+ uint32_t l_3175[10];
+ int i, j, k;
+ for (i = 0; i < 10; i++)
+ l_3175[i] = 0UL;
+ g_3176[0] = (((safe_div_func_int32_t_s_s(l_2, ((**g_999) , (safe_mul_func_int8_t_s_s((l_3165[1] != (l_3166[1][2][2] < (((l_3165[5] , (void*)0) != l_3167) >= ((safe_mod_func_uint16_t_u_u((safe_unary_minus_func_int32_t_s(((*g_983) , ((***g_2621) |= (safe_div_func_int32_t_s_s(((safe_add_func_uint32_t_u_u(((*g_983) > 0UL), (**g_1700))) >= 4UL), 1UL)))))), l_3165[1])) && 0x27EDL)))), g_253))))) , 0xCDD9L) && l_3175[6]);
+ }
+ }
+ if ((***g_2621))
+ { /* block id: 1478 */
+ uint32_t **l_3185 = &g_1701;
+ int32_t l_3186 = 0xDDB13C5AL;
+ uint64_t *****l_3198 = &g_1567;
+ uint64_t ******l_3197 = &l_3198;
+ int32_t l_3229 = 0xCC934D37L;
+ uint32_t **l_3282 = &g_648;
+ uint64_t l_3352 = 18446744073709551615UL;
+ int32_t l_3408 = 1L;
+ int32_t l_3409 = 8L;
+ uint32_t l_3410 = 0UL;
+ int32_t l_3413 = 0x1B38E9A0L;
+ int64_t l_3414 = 1L;
+ int32_t l_3415 = 0L;
+ int32_t l_3416 = (-10L);
+ int32_t l_3417 = 0x826CAA3AL;
+ int32_t l_3418 = (-10L);
+ if (((((safe_add_func_uint8_t_u_u((safe_rshift_func_int8_t_s_s((((*g_457) , (***g_276)) ^ 0x90099C64A4CC214BLL), 4)), g_2497)) , l_3186) & 0xD30FF6655B03D0F7LL) < (**g_1574)))
+ { /* block id: 1480 */
+ uint32_t l_3187[3][8] = {{0x13CA3311L,5UL,0x6BA18EA5L,5UL,0x13CA3311L,0x13CA3311L,5UL,0x6BA18EA5L},{5UL,5UL,18446744073709551615UL,18446744073709551615UL,18446744073709551615UL,5UL,5UL,18446744073709551615UL},{0x6BA18EA5L,18446744073709551615UL,18446744073709551615UL,0x6BA18EA5L,0x13CA3311L,0x6BA18EA5L,18446744073709551615UL,18446744073709551615UL}};
+ int8_t l_3205 = 0x03L;
+ int16_t *l_3217 = &g_408;
+ int16_t * const l_3219 = (void*)0;
+ int32_t l_3230[4] = {(-8L),(-8L),(-8L),(-8L)};
+ uint8_t l_3231 = 0x75L;
+ int8_t l_3257[10][5][5] = {{{0L,0x77L,(-7L),0xFBL,0xFBL},{0L,3L,0L,(-4L),(-2L)},{0L,(-7L),1L,0x4AL,1L},{(-10L),0xB6L,(-4L),0x50L,(-1L)},{(-1L),0x33L,1L,1L,0xD2L}},{{0x0CL,0x18L,0L,(-1L),(-7L)},{(-1L),(-1L),(-7L),0x8FL,7L},{5L,0x0CL,0x2DL,5L,0x6AL},{1L,7L,0x56L,0x79L,0x1DL},{0x15L,0x9DL,(-1L),0x42L,0xE5L}},{{0xEDL,(-1L),0L,(-8L),1L},{0L,0x8CL,(-2L),(-2L),0x8CL},{0L,0L,0x05L,0x77L,0x3EL},{0L,(-1L),0L,0x2DL,(-4L)},{0xFBL,0x08L,0xE9L,6L,(-5L)}},{{0L,(-10L),0L,8L,0x81L},{0L,(-9L),0xEDL,0x3EL,(-1L)},{0L,0x93L,1L,0xB6L,5L},{0xEDL,0xEDL,0xF1L,0xD6L,(-9L)},{0x15L,(-1L),(-1L),0x8CL,3L}},{{1L,0x66L,0x24L,0x10L,0x56L},{5L,0x34L,0L,0xB1L,8L},{(-1L),(-5L),(-5L),(-1L),(-6L)},{0x0CL,0x50L,8L,0L,5L},{(-1L),6L,0x10L,1L,(-1L)}},{{(-10L),0x67L,0xE5L,0L,0x0FL},{0L,0x4AL,0xE8L,(-1L),(-1L)},{0L,(-1L),(-7L),0xB1L,0L},{0L,(-1L),1L,0x10L,0x8FL},{0xE5L,0x2DL,(-1L),0x8CL,0x67L}},{{(-8L),(-1L),0x33L,0xD6L,0L},{0x50L,0x6AL,0L,0xB6L,0x9DL},{(-1L),1L,0x66L,0x3EL,0x66L},{1L,1L,(-10L),8L,4L},{(-9L),(-7L),(-6L),(-9L),(-1L)}},{{0x93L,0x33L,0x12L,(-1L),1L},{(-1L),(-7L),0xEDL,1L,0x77L},{4L,0x0FL,0x50L,0x93L,0x0CL},{0xE9L,0x10L,0xD8L,0xF1L,0x8FL},{(-2L),(-1L),(-10L),0L,0L}},{{(-7L),1L,0x42L,7L,(-6L)},{(-10L),(-1L),0x13L,(-4L),0x67L},{0x04L,0xEDL,0x3EL,(-6L),7L},{0L,0x15L,0L,0x15L,0L},{0xD2L,(-6L),0xF1L,(-1L),0x3EL}},{{8L,0L,5L,(-7L),(-2L)},{0x77L,(-9L),(-1L),(-6L),0x3EL},{(-1L),(-7L),0L,(-1L),0L},{0x3EL,0x06L,0x77L,(-1L),7L},{(-1L),0x12L,(-1L),0x50L,0x67L}}};
+ const int64_t **l_3264 = (void*)0;
+ uint32_t **l_3281 = &g_648;
+ int i, j, k;
+ for (g_146 = 0; (g_146 <= 1); g_146 += 1)
+ { /* block id: 1483 */
+ uint32_t l_3192 = 1UL;
+ union U0 *l_3214[3];
+ int32_t l_3255 = (-1L);
+ int i;
+ for (i = 0; i < 3; i++)
+ l_3214[i] = &g_458;
+ ++l_3187[2][6];
+ if ((safe_sub_func_int64_t_s_s(((*g_127) = (!(l_3192 < ((((--(**g_1700)) | ((safe_div_func_int16_t_s_s((((void*)0 != l_3197) > (l_3186 & l_3186)), ((**g_642) = (safe_mul_func_int8_t_s_s((safe_sub_func_uint16_t_u_u(((**g_2631) , l_2), ((safe_mod_func_uint16_t_u_u(((*g_648) , 4UL), (**g_2631))) >= g_274))), 1UL))))) > 0x8E3D84382D7D5000LL)) ^ 0x34L) >= 0UL)))), l_3205)))
+ { /* block id: 1488 */
+ int8_t l_3213 = 0xEEL;
+ int16_t **l_3218 = &l_3217;
+ int32_t l_3232 = (-1L);
+ int32_t l_3233 = 1L;
+ if (l_3192)
+ break;
+ l_3232 &= ((safe_add_func_uint8_t_u_u((safe_div_func_int8_t_s_s((safe_rshift_func_uint16_t_u_s(((safe_unary_minus_func_uint16_t_u(((g_254 & l_3213) > ((void*)0 == l_3214[1])))) > (safe_mul_func_int8_t_s_s((((*l_3218) = l_3217) == l_3219), (safe_rshift_func_int8_t_s_s(((*l_3158) = ((safe_div_func_uint32_t_u_u(((safe_mod_func_int16_t_s_s(((l_3230[2] = ((safe_rshift_func_uint8_t_u_u((((l_3187[2][6] & (((l_3228 , (*g_457)) , 253UL) || l_3192)) != l_3229) & l_3192), 1)) != (***g_2621))) > l_3192), (**g_1744))) == (*g_268)), 0xFC91D86FL)) != l_3231)), l_7))))), (*g_1739))), 248UL)), 250UL)) < 255UL);
+ return l_3233;
+ }
+ else
+ { /* block id: 1495 */
+ (*g_999) = (**g_1175);
+ }
+ if (l_2)
+ continue;
+ for (g_209.f1 = 0; (g_209.f1 <= 1); g_209.f1 += 1)
+ { /* block id: 1501 */
+ uint8_t *l_3241[9][8][3] = {{{&l_3231,&l_3231,&l_3231},{&g_3176[3],(void*)0,&g_183},{&l_3231,(void*)0,&l_3231},{&g_183,&g_3176[3],&g_3176[3]},{&g_206,(void*)0,(void*)0},{&g_183,&g_183,&g_206},{&l_3231,&g_3176[0],&g_206},{&g_3176[3],&g_183,&g_3176[3]}},{{&l_3231,(void*)0,&g_3176[0]},{(void*)0,&g_3176[3],&g_3176[3]},{&g_3176[0],(void*)0,&g_206},{&g_183,(void*)0,&g_206},{&g_3176[0],&l_3231,(void*)0},{(void*)0,&g_183,&g_3176[3]},{&l_3231,&l_3231,&l_3231},{&g_3176[3],(void*)0,&g_183}},{{&l_3231,(void*)0,&l_3231},{&g_183,&g_3176[3],&g_3176[3]},{&g_206,(void*)0,(void*)0},{&g_183,&g_183,&g_206},{&l_3231,&g_3176[0],&g_206},{&g_3176[3],&g_183,&g_3176[3]},{&l_3231,(void*)0,&g_3176[0]},{(void*)0,&g_3176[3],&g_3176[3]}},{{&g_3176[0],(void*)0,&g_206},{&g_183,(void*)0,&g_206},{&g_3176[0],&l_3231,(void*)0},{(void*)0,&g_183,&g_3176[3]},{&l_3231,&l_3231,&l_3231},{&g_3176[3],(void*)0,&g_183},{&l_3231,(void*)0,&l_3231},{&g_183,&g_3176[3],&g_3176[3]}},{{&g_206,(void*)0,(void*)0},{&g_183,&g_183,&g_206},{&l_3231,&g_3176[0],&g_206},{&g_3176[3],&g_183,&g_3176[3]},{&l_3231,(void*)0,&g_3176[0]},{&g_3176[3],&g_183,&g_183},{&g_183,&g_3176[0],(void*)0},{&g_3176[3],&g_3176[3],&g_183}},{{&g_183,(void*)0,&g_3176[0]},{&g_3176[3],&g_3176[3],&g_206},{&g_206,(void*)0,&g_206},{&g_183,&g_3176[3],&g_206},{&l_3231,&g_3176[0],&g_206},{&g_206,&g_183,&g_206},{&g_206,(void*)0,&g_3176[0]},{&g_206,&g_206,&g_183}},{{&l_3231,(void*)0,(void*)0},{&g_183,&g_206,&g_183},{&g_206,(void*)0,&g_183},{&g_3176[3],&g_183,&g_183},{&g_183,&g_3176[0],(void*)0},{&g_3176[3],&g_3176[3],&g_183},{&g_183,(void*)0,&g_3176[0]},{&g_3176[3],&g_3176[3],&g_206}},{{&g_206,(void*)0,&g_206},{&g_183,&g_3176[3],&g_206},{&l_3231,&g_3176[0],&g_206},{&g_206,&g_183,&g_206},{&g_206,(void*)0,&g_3176[0]},{&g_206,&g_206,&g_183},{&l_3231,(void*)0,(void*)0},{&g_183,&g_206,&g_183}},{{&g_206,(void*)0,&g_183},{&g_3176[3],&g_183,&g_183},{&g_183,&g_3176[0],(void*)0},{&g_3176[3],&g_3176[3],&g_183},{&g_183,(void*)0,&g_3176[0]},{&g_3176[3],&g_3176[3],&g_206},{&g_206,(void*)0,&g_206},{&g_183,&g_3176[3],&g_206}}};
+ uint64_t l_3242[8] = {0xB6412F7D8489259FLL,1UL,1UL,0xB6412F7D8489259FLL,1UL,1UL,0xB6412F7D8489259FLL,1UL};
+ uint64_t l_3253 = 18446744073709551606UL;
+ int32_t l_3256 = 0x6AE19F0EL;
+ uint32_t l_3258 = 4294967295UL;
+ int i, j, k;
+ l_6 = (safe_mod_func_uint16_t_u_u((l_3230[2] , (safe_mul_func_int8_t_s_s(((safe_add_func_int8_t_s_s(((((*l_3240) |= (((0x9CL ^ ((void*)0 != l_3240)) >= (l_3242[0] = ((*g_983) &= l_3187[2][6]))) <= l_6)) > (((safe_rshift_func_int8_t_s_u((safe_rshift_func_uint8_t_u_s((((*g_127) = (safe_rshift_func_uint8_t_u_s(g_177, ((1L <= ((safe_mul_func_uint16_t_u_u((safe_add_func_uint32_t_u_u((**g_1700), (**g_1700))), (-5L))) & l_3192)) != l_7)))) == 0x94128C946CC5AD13LL), g_458.f1)), l_3186)) < 0xBBL) , (-1L))) >= 250UL), l_3253)) >= 1UL), l_3187[0][2]))), 65535UL));
+ l_3258++;
+ if (g_3261)
+ continue;
+ }
+ }
+ l_3[7][8][1] = ((*g_999) = &l_3230[0]);
+ for (g_629 = 0; (g_629 < 23); ++g_629)
+ { /* block id: 1515 */
+ uint32_t l_3271 = 1UL;
+ int32_t l_3274 = (-8L);
+ uint8_t l_3294[4][3][2] = {{{0x30L,0x30L},{0xECL,253UL},{0x6AL,9UL}},{{0UL,0xECL},{255UL,0UL},{5UL,0UL}},{{5UL,0UL},{255UL,0xECL},{0UL,9UL}},{{0x6AL,253UL},{0xECL,0x30L},{0x30L,0x30L}}};
+ uint32_t ****l_3309[2][8];
+ int i, j, k;
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 8; j++)
+ l_3309[i][j] = (void*)0;
+ }
+ }
+ }
+ else
+ { /* block id: 1537 */
+ uint64_t l_3321 = 0xDDE7A297B90E42B9LL;
+ int32_t l_3323 = 0L;
+ int8_t *l_3329 = (void*)0;
+ uint32_t l_3330[6][7][6] = {{{18446744073709551615UL,1UL,0xB6573154L,18446744073709551615UL,0xAB8E7E60L,0xD5EF4BC4L},{18446744073709551615UL,0xAB8E7E60L,0xD5EF4BC4L,1UL,1UL,0xD5EF4BC4L},{18446744073709551614UL,18446744073709551614UL,0xB6573154L,1UL,1UL,0x8128DDD9L},{1UL,0xAB8E7E60L,0x812AD54AL,1UL,0xAB8E7E60L,0xB6573154L},{18446744073709551614UL,1UL,0x812AD54AL,1UL,18446744073709551614UL,0x8128DDD9L},{18446744073709551615UL,1UL,0xB6573154L,18446744073709551615UL,0xAB8E7E60L,0xD5EF4BC4L},{18446744073709551615UL,0xAB8E7E60L,0xD5EF4BC4L,1UL,1UL,0xD5EF4BC4L}},{{18446744073709551614UL,18446744073709551614UL,0xB6573154L,1UL,1UL,0x8128DDD9L},{1UL,0xAB8E7E60L,0x812AD54AL,1UL,0xAB8E7E60L,0xB6573154L},{0xCE918E94L,0x8BF1BB38L,0xAB8E7E60L,0x8BF1BB38L,0xCE918E94L,1UL},{0UL,0x8BF1BB38L,18446744073709551615UL,0UL,0x269CFCD7L,1UL},{0UL,0x269CFCD7L,1UL,0x8BF1BB38L,0x8BF1BB38L,1UL},{0xCE918E94L,0xCE918E94L,18446744073709551615UL,0x991B26EDL,0x8BF1BB38L,1UL},{0x8BF1BB38L,0x269CFCD7L,0xAB8E7E60L,0x991B26EDL,0x269CFCD7L,18446744073709551615UL}},{{0xCE918E94L,0x8BF1BB38L,0xAB8E7E60L,0x8BF1BB38L,0xCE918E94L,1UL},{0UL,0x8BF1BB38L,18446744073709551615UL,0UL,0x269CFCD7L,1UL},{0UL,0x269CFCD7L,1UL,0x8BF1BB38L,0x8BF1BB38L,1UL},{0xCE918E94L,0xCE918E94L,18446744073709551615UL,0x991B26EDL,0x8BF1BB38L,1UL},{0x8BF1BB38L,0x269CFCD7L,0xAB8E7E60L,0x991B26EDL,0x269CFCD7L,18446744073709551615UL},{0xCE918E94L,0x8BF1BB38L,0xAB8E7E60L,0x8BF1BB38L,0xCE918E94L,1UL},{0UL,0x8BF1BB38L,18446744073709551615UL,0UL,0x269CFCD7L,1UL}},{{0UL,0x269CFCD7L,1UL,0x8BF1BB38L,0x8BF1BB38L,1UL},{0xCE918E94L,0xCE918E94L,18446744073709551615UL,0x991B26EDL,0x8BF1BB38L,1UL},{0x8BF1BB38L,0x269CFCD7L,0xAB8E7E60L,0x991B26EDL,0x269CFCD7L,18446744073709551615UL},{0xCE918E94L,0x8BF1BB38L,0xAB8E7E60L,0x8BF1BB38L,0xCE918E94L,1UL},{0UL,0x8BF1BB38L,18446744073709551615UL,0UL,0x269CFCD7L,1UL},{0UL,0x269CFCD7L,1UL,0x8BF1BB38L,0x8BF1BB38L,1UL},{0xCE918E94L,0xCE918E94L,18446744073709551615UL,0x991B26EDL,0x8BF1BB38L,1UL}},{{0x8BF1BB38L,0x269CFCD7L,0xAB8E7E60L,0x991B26EDL,0x269CFCD7L,18446744073709551615UL},{0xCE918E94L,0x8BF1BB38L,0xAB8E7E60L,0x8BF1BB38L,0xCE918E94L,1UL},{0UL,0x8BF1BB38L,18446744073709551615UL,0UL,0x269CFCD7L,1UL},{0UL,0x269CFCD7L,1UL,0x8BF1BB38L,0x8BF1BB38L,1UL},{0xCE918E94L,0xCE918E94L,18446744073709551615UL,0x991B26EDL,0x8BF1BB38L,1UL},{0x8BF1BB38L,0x269CFCD7L,0xAB8E7E60L,0x991B26EDL,0x269CFCD7L,18446744073709551615UL},{0xCE918E94L,0x8BF1BB38L,0xAB8E7E60L,0x8BF1BB38L,0xCE918E94L,1UL}},{{0UL,0x8BF1BB38L,18446744073709551615UL,0UL,0x269CFCD7L,1UL},{0UL,0x269CFCD7L,1UL,0x8BF1BB38L,0x8BF1BB38L,1UL},{0xCE918E94L,0xCE918E94L,18446744073709551615UL,0x991B26EDL,0x8BF1BB38L,1UL},{0x8BF1BB38L,0x269CFCD7L,0xAB8E7E60L,0x991B26EDL,0x269CFCD7L,18446744073709551615UL},{0xCE918E94L,0x8BF1BB38L,0xAB8E7E60L,0x8BF1BB38L,0xCE918E94L,1UL},{0UL,0x8BF1BB38L,18446744073709551615UL,0UL,0x269CFCD7L,0x991B26EDL},{0xE15135D8L,0xB6573154L,0x991B26EDL,0x812AD54AL,0x812AD54AL,0x991B26EDL}}};
+ int32_t l_3333[3];
+ uint32_t l_3335[8][1][9] = {{{0x30091A38L,0UL,0x30B5CAEFL,0xE11A6A21L,0xE11A6A21L,0x30B5CAEFL,0UL,0x30091A38L,0x30B5CAEFL}},{{0x30091A38L,0UL,0x30B5CAEFL,0xE11A6A21L,0xE11A6A21L,0x30B5CAEFL,0UL,0x30091A38L,0x30B5CAEFL}},{{0x30091A38L,0UL,0x30B5CAEFL,0xE11A6A21L,0xE11A6A21L,0x30B5CAEFL,0UL,0x30091A38L,0x30B5CAEFL}},{{0x30091A38L,0UL,0x30B5CAEFL,0xE11A6A21L,0xE11A6A21L,0x30B5CAEFL,0UL,0x30091A38L,0x30B5CAEFL}},{{0x30091A38L,0UL,0x30B5CAEFL,0xE11A6A21L,0xE11A6A21L,0x30B5CAEFL,0UL,0x30091A38L,0x30B5CAEFL}},{{0x30091A38L,0UL,0x30B5CAEFL,0xE11A6A21L,0xE11A6A21L,0x30B5CAEFL,0UL,0x30091A38L,0x30B5CAEFL}},{{0x30091A38L,0UL,0x30B5CAEFL,0xE11A6A21L,0xE11A6A21L,0x30B5CAEFL,0UL,0x30091A38L,0x30B5CAEFL}},{{0x30091A38L,0UL,0x30B5CAEFL,0xE11A6A21L,0xE11A6A21L,0x30B5CAEFL,0UL,0x30091A38L,0x30B5CAEFL}}};
+ int i, j, k;
+ for (i = 0; i < 3; i++)
+ l_3333[i] = 3L;
+lbl_3355:
+ for (g_458.f3 = 0; (g_458.f3 <= 9); g_458.f3 += 1)
+ { /* block id: 1540 */
+ uint8_t ***l_3320 = &g_441;
+ int i;
+ (*g_1000) |= (l_3323 = (safe_add_func_int8_t_s_s(g_2033[g_458.f3], ((((l_3229 ^= (safe_mod_func_int64_t_s_s((((*g_643) = ((*g_457) , (0x159FL != (((((*g_457) , (void*)0) == ((*l_3320) = &g_442)) <= (l_3321 < g_3322[2])) || g_2033[g_458.f3])))) <= l_5), l_7))) >= (-1L)) > l_3321) ^ l_2))));
+ return g_2033[g_458.f3];
+ }
+ if ((safe_lshift_func_uint16_t_u_s(((safe_rshift_func_uint8_t_u_u((((*g_983) = (*g_983)) < 0xDCL), g_629)) && ((g_3328 = &g_3254) == l_3329)), 4)))
+ { /* block id: 1550 */
+ int8_t l_3339 = 7L;
+ for (g_132 = 0; (g_132 <= 7); g_132 += 1)
+ { /* block id: 1553 */
+ int16_t l_3334 = (-2L);
+ int32_t l_3338[7] = {(-9L),(-9L),0xA9A03672L,(-9L),(-9L),0xA9A03672L,(-9L)};
+ int i;
+ l_3330[3][1][3]++;
+ l_3335[2][0][3]--;
+ g_3340++;
+ if (g_258[g_132])
+ break;
+ }
+ }
+ else
+ { /* block id: 1559 */
+ uint32_t **l_3345 = &g_1701;
+ for (g_2895 = 0; (g_2895 <= 9); g_2895 += 1)
+ { /* block id: 1562 */
+ uint32_t ***l_3347 = &l_3346[3][0];
+ const uint16_t **** const **l_3350 = &g_3348;
+ int32_t l_3351 = 3L;
+ int i;
+ (**g_2622) ^= (safe_mul_func_int8_t_s_s((((l_3345 == ((*l_3347) = (g_2033[g_2895] , l_3346[2][3]))) , ((*l_3350) = g_3348)) == &g_2981), g_2033[g_2895]));
+ l_3352--;
+ if (g_458.f3)
+ goto lbl_3355;
+ }
+ return l_3352;
+ }
+ }
+ for (l_3228.f0 = 26; (l_3228.f0 > (-21)); l_3228.f0--)
+ { /* block id: 1574 */
+ int64_t l_3358[10] = {0L,0L,0L,0L,0L,0L,0L,0L,0L,0L};
+ int32_t l_3359 = (-5L);
+ int32_t l_3360 = 1L;
+ int32_t l_3364 = (-1L);
+ int32_t l_3367 = 0xBCDBA61AL;
+ int32_t l_3372 = (-1L);
+ int32_t l_3373 = 0x8C5B084EL;
+ int i;
+ l_3358[7] = l_6;
+ for (g_146 = 2; (g_146 >= 0); g_146 -= 1)
+ { /* block id: 1578 */
+ int64_t l_3361 = 0x9285272348967190LL;
+ int16_t l_3365 = 0xD941L;
+ int32_t l_3366 = 1L;
+ uint32_t l_3382[4][5][9] = {{{1UL,18446744073709551614UL,1UL,18446744073709551615UL,18446744073709551613UL,0x2E5E3E5AL,18446744073709551607UL,0x71493D5FL,4UL},{18446744073709551611UL,0xE6880DAFL,2UL,0xDDD702C7L,0xA6C66844L,0xC0E85E58L,0xA6C66844L,0xDDD702C7L,2UL},{4UL,4UL,18446744073709551614UL,18446744073709551615UL,0x204CB92DL,1UL,2UL,1UL,6UL},{1UL,1UL,0xC0E85E58L,18446744073709551615UL,18446744073709551606UL,18446744073709551606UL,18446744073709551615UL,0xC0E85E58L,1UL},{18446744073709551615UL,18446744073709551606UL,18446744073709551614UL,0x57A19FA0L,0UL,18446744073709551615UL,4UL,2UL,18446744073709551613UL}},{{0xDDD702C7L,1UL,2UL,1UL,18446744073709551615UL,1UL,2UL,1UL,0xDDD702C7L},{0UL,18446744073709551606UL,1UL,0xD37B812EL,4UL,18446744073709551607UL,6UL,18446744073709551614UL,0x2E5E3E5AL},{0x17F27A6EL,1UL,0x5030D5BFL,0xC0E85E58L,0xC0E85E58L,0x5030D5BFL,1UL,0x17F27A6EL,0xC51F3F36L},{0UL,4UL,6UL,0x204CB92DL,0x71493D5FL,18446744073709551615UL,18446744073709551613UL,0xD37B812EL,0xD37B812EL},{0xDDD702C7L,0xE6880DAFL,18446744073709551615UL,0x17F27A6EL,18446744073709551615UL,0xE6880DAFL,0xDDD702C7L,18446744073709551606UL,0xC51F3F36L}},{{18446744073709551615UL,18446744073709551614UL,1UL,18446744073709551606UL,4UL,0x204CB92DL,0xD37B812EL,1UL,0xD37B812EL},{18446744073709551615UL,0xA6C66844L,0xE6880DAFL,0xE6880DAFL,0xA6C66844L,18446744073709551615UL,18446744073709551606UL,0x5030D5BFL,0x17F27A6EL},{1UL,2UL,1UL,0x204CB92DL,18446744073709551615UL,18446744073709551614UL,4UL,4UL,18446744073709551614UL},{0xE6880DAFL,18446744073709551615UL,0x17F27A6EL,18446744073709551615UL,0xE6880DAFL,0xDDD702C7L,18446744073709551606UL,0xC51F3F36L,1UL},{18446744073709551613UL,4UL,1UL,0x2E5E3E5AL,2UL,18446744073709551607UL,0xD37B812EL,18446744073709551607UL,2UL}},{{18446744073709551606UL,2UL,2UL,18446744073709551606UL,0x4809426DL,0xDDD702C7L,0x17F27A6EL,18446744073709551615UL,0xC0E85E58L},{18446744073709551615UL,6UL,0UL,1UL,0x71493D5FL,18446744073709551614UL,18446744073709551614UL,0x71493D5FL,1UL},{0x616EDC88L,1UL,0x616EDC88L,0x3258CFFDL,0x4809426DL,18446744073709551615UL,1UL,18446744073709551611UL,0xDDD702C7L},{1UL,18446744073709551613UL,0x71493D5FL,18446744073709551606UL,2UL,0x204CB92DL,2UL,18446744073709551606UL,0x71493D5FL},{0xDDD702C7L,0xDDD702C7L,1UL,0x3258CFFDL,0xE6880DAFL,0x616EDC88L,0xC0E85E58L,0x17F27A6EL,2UL}}};
+ int i, j, k;
+ l_3375++;
+ if ((*g_268))
+ continue;
+ l_3229 = (l_3361 != (~((safe_rshift_func_int16_t_s_s(((safe_mod_func_uint32_t_u_u(((l_6 , &g_3348) != &g_2980), (~(!l_3382[3][3][1])))) , (safe_sub_func_int64_t_s_s((((*l_3197) = l_3385) == (l_3370 , (((((safe_lshift_func_uint8_t_u_u(l_3374, (l_3360 != l_3382[2][2][5]))) , 1L) , l_3388) != l_3365) , l_3389))), l_2))), 2)) || l_3352)));
+ for (g_888 = 0; (g_888 <= 2); g_888 += 1)
+ { /* block id: 1585 */
+ uint64_t *l_3398 = &g_629;
+ uint32_t l_3405 = 0x14A9940BL;
+ int32_t l_3406[9] = {1L,1L,1L,1L,1L,1L,1L,1L,1L};
+ int i, j;
+ l_3406[8] ^= ((((safe_add_func_uint64_t_u_u(((*l_3240)--), ((((safe_add_func_int16_t_s_s((((safe_lshift_func_uint16_t_u_u((((((*l_3398) = 0x4D91C8663151B76CLL) != 0x073A0058EBEA58B1LL) | l_3374) >= (safe_mul_func_int8_t_s_s((safe_sub_func_uint32_t_u_u(((*l_3185) == (void*)0), (safe_div_func_uint8_t_u_u((((*l_3158) |= l_3369) < 6UL), (l_3366 | (l_5 > 9UL)))))), l_3358[5]))), 9)) , &g_1567) == &g_1567), 0x1CACL)) == (*g_268)) < 0x93C5L) , l_3405))) >= l_3367) == (**g_1700)) ^ (*g_127));
+ if (l_3382[0][0][4])
+ continue;
+ }
+ }
+ if (l_3373)
+ continue;
+ l_3410--;
+ }
+ l_3419[2]--;
+ }
+ else
+ { /* block id: 1597 */
+ int32_t *l_3429 = &g_75[0];
+ uint16_t ***l_3481 = &g_642;
+ uint16_t ****l_3480[8] = {(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0};
+ int64_t l_3488[4][1][5] = {{{7L,6L,7L,6L,7L}},{{0L,0L,1L,1L,0L}},{{(-1L),6L,(-1L),6L,(-1L)}},{{0L,1L,1L,0L,0L}}};
+ union U0 l_3502 = {0x32L};
+ int16_t *l_3543 = &g_408;
+ int64_t l_3545 = 0xCC9D81739EE3B76CLL;
+ int32_t l_3548 = 0xFEF003C0L;
+ int32_t l_3551 = 2L;
+ int32_t l_3553[10] = {(-7L),(-7L),(-7L),(-7L),(-7L),(-7L),(-7L),(-7L),(-7L),(-7L)};
+ uint8_t l_3555 = 1UL;
+ int8_t l_3624 = (-4L);
+ int16_t l_3665 = 0L;
+ int32_t l_3689 = 0x13D17FE3L;
+ uint64_t l_3693 = 1UL;
+ uint32_t **l_3716 = (void*)0;
+ uint32_t l_3753 = 0xBFB92AF7L;
+ uint8_t l_3758 = 0xDAL;
+ int64_t l_3759[1];
+ int8_t l_3828 = 0xBFL;
+ int32_t ** const ****l_3840 = (void*)0;
+ int32_t l_3856 = (-8L);
+ const uint32_t l_3872 = 3UL;
+ uint32_t *****l_3934 = &g_3601;
+ int i, j, k;
+ for (i = 0; i < 1; i++)
+ l_3759[i] = 0x4C49DDF402E1B26ALL;
+ if (((-4L) > (((l_3368 = 0L) > (safe_sub_func_uint16_t_u_u(((*g_441) != l_3426), (safe_lshift_func_uint8_t_u_u(1UL, 3))))) > ((**g_1175) == l_3429))))
+ { /* block id: 1599 */
+ (*g_267) = &l_3388;
+ return l_3369;
+ }
+ else
+ { /* block id: 1602 */
+ int16_t l_3436[5] = {0x12A2L,0x12A2L,0x12A2L,0x12A2L,0x12A2L};
+ uint32_t ****l_3437 = &l_3308;
+ int32_t l_3482 = 1L;
+ int32_t l_3483 = 0xF7B6D19CL;
+ int32_t l_3489 = 0x50343D68L;
+ int32_t l_3494[2][7] = {{0xB2700B47L,(-2L),0x382AAF93L,0x34F800FAL,0x34F800FAL,0x382AAF93L,(-2L)},{0xB2700B47L,(-2L),0x382AAF93L,0x34F800FAL,0x34F800FAL,0x382AAF93L,(-2L)}};
+ const uint64_t *l_3516[4][3] = {{&g_132,&l_3375,&g_132},{&g_132,&l_3375,&g_132},{&g_132,&l_3375,&g_132},{&g_132,&l_3375,&g_132}};
+ uint64_t ***** const *l_3537 = &l_3385;
+ int64_t l_3538 = 0xB72394C9ED776906LL;
+ int8_t l_3552 = 0xE5L;
+ uint16_t *****l_3635[9] = {&l_3480[2],&l_3480[2],&l_3480[2],&l_3480[2],&l_3480[2],&l_3480[2],&l_3480[2],&l_3480[2],&l_3480[2]};
+ uint16_t ******l_3634 = &l_3635[2];
+ int8_t *l_3654 = &l_3590[8];
+ int8_t *l_3655 = &l_3544;
+ int i, j;
+lbl_3541:
+ if ((0xC5581AAEL > (((&g_647[5][0] == ((*l_3437) = (((safe_sub_func_int64_t_s_s(((***g_276) = ((((safe_rshift_func_int16_t_s_s((((safe_mul_func_int8_t_s_s(((****g_2620) == ((((void*)0 != &l_3298) || 6L) ^ ((*g_1701) , 0x42C35DDFL))), 0x63L)) >= 0x1412F895L) < 0x6480L), 3)) , l_3436[4]) <= 0x67879153L) || 0x1F4B0C28L)), 18446744073709551615UL)) == 1UL) , l_3308))) != l_3436[4]) || g_746)))
+ { /* block id: 1605 */
+ union U0 **l_3439 = (void*)0;
+ int32_t l_3453[4][8][4] = {{{0xA9A0789AL,0x9149705AL,0x36D971D7L,0xD6172A53L},{0x36D971D7L,0xD6172A53L,0x252D9B84L,0xD6172A53L},{1L,0x9149705AL,1L,0x36D971D7L},{0x90B9288CL,0x2C266790L,0xD6172A53L,(-1L)},{1L,1L,1L,1L},{0xD6172A53L,0xD6172A53L,0xA9A0789AL,0x2C266790L},{0x36D971D7L,1L,0xD6172A53L,0x9149705AL},{(-1L),(-4L),0x90B9288CL,0xD6172A53L}},{{0x5A1350BCL,(-4L),0x5A1350BCL,0x9149705AL},{(-4L),1L,0x252D9B84L,0x2C266790L},{0x2C266790L,0xD6172A53L,(-1L),1L},{1L,(-1L),(-1L),1L},{0x2C266790L,0x9149705AL,0x252D9B84L,0x5A1350BCL},{(-4L),(-4L),0x5A1350BCL,0xA9A0789AL},{0x5A1350BCL,0xA9A0789AL,0x90B9288CL,0xA9A0789AL},{(-1L),(-4L),0xD6172A53L,0x5A1350BCL}},{{0x36D971D7L,0x9149705AL,0xA9A0789AL,1L},{0xD6172A53L,(-1L),1L,1L},{0xD6172A53L,0xD6172A53L,0xA9A0789AL,0x2C266790L},{0x36D971D7L,1L,0xD6172A53L,0x9149705AL},{(-1L),(-4L),0x90B9288CL,0xD6172A53L},{0x5A1350BCL,(-4L),0x5A1350BCL,0x9149705AL},{(-4L),1L,0x252D9B84L,0x2C266790L},{0x2C266790L,0xD6172A53L,(-1L),1L}},{{1L,(-1L),(-1L),1L},{0x2C266790L,0x9149705AL,0x252D9B84L,0x5A1350BCL},{(-4L),(-4L),0x5A1350BCL,0xA9A0789AL},{0x5A1350BCL,0xA9A0789AL,0x90B9288CL,0xA9A0789AL},{(-1L),(-4L),0xD6172A53L,0x5A1350BCL},{0x36D971D7L,0x9149705AL,0xA9A0789AL,1L},{0xD6172A53L,(-1L),1L,1L},{0xD6172A53L,0xD6172A53L,0xA9A0789AL,0x2C266790L}}};
+ uint16_t ***l_3479 = &g_3116;
+ uint16_t ****l_3478 = &l_3479;
+ int i, j, k;
+ g_457 = l_3438;
+ (***g_2621) |= (((*l_3429) = (l_3453[2][7][1] = ((*g_983) == (safe_div_func_int16_t_s_s((safe_mul_func_int8_t_s_s((((void*)0 == &g_3349) != (safe_add_func_uint8_t_u_u(l_3446[0], ((((*g_457) = (*g_457)) , ((safe_rshift_func_uint8_t_u_u(0x6FL, 0)) && (**g_642))) ^ ((safe_mod_func_int64_t_s_s((safe_sub_func_uint64_t_u_u(18446744073709551607UL, l_3453[2][7][1])), (***g_276))) <= l_3436[0]))))), l_3419[2])), l_3436[4]))))) < l_3436[4]);
+ if (l_3446[2])
+ { /* block id: 1611 */
+ int16_t *l_3472 = &g_408;
+ int32_t l_3474 = 0L;
+ int32_t l_3477 = (-1L);
+ int64_t l_3484 = (-1L);
+ int16_t l_3490 = 8L;
+ uint32_t l_3491 = 0UL;
+ (***g_2621) = (l_3436[4] ^ ((((((safe_div_func_uint32_t_u_u((0L | (safe_div_func_int32_t_s_s(((l_3453[2][7][1] ^ ((++(**g_3116)) , (safe_add_func_int64_t_s_s((+((((safe_lshift_func_uint8_t_u_s(((+(safe_add_func_uint32_t_u_u((safe_lshift_func_int16_t_s_s(((((*l_3438) , (safe_add_func_uint64_t_u_u((safe_div_func_int64_t_s_s(((((*l_3472) &= 0x0CC3L) > (*g_1739)) || (safe_unary_minus_func_uint32_t_u((l_3474 = (*g_1701))))), (safe_rshift_func_int8_t_s_s(((0x2FF5L | ((**g_1574) ^= ((*g_127) | 18446744073709551615UL))) | 0x1D00L), l_3477)))), (-6L)))) | g_471) , l_3436[4]), l_3477)), l_3477))) < 0L), l_3375)) >= l_3375) , l_3478) == l_3480[2])), 18446744073709551615UL)))) & l_5), (**g_1700)))), (*g_1701))) , (*l_3298)) , l_3436[4]) || l_3477) && l_3477) ^ l_3453[2][7][1]));
+ g_3485--;
+ --l_3491;
+ }
+ else
+ { /* block id: 1619 */
+ uint32_t *l_3498 = &g_3322[2];
+ l_3495--;
+ (***g_1175) = (func_97((((*l_3429) && (l_3498 != (void*)0)) , func_57(func_57((***g_2978), func_13((safe_add_func_uint64_t_u_u((*l_3429), ((*g_2980) == (*g_3348))))), (***g_2978), l_3453[2][7][1], (*g_999)), (***g_2978), l_3429, (*g_268), &l_3453[1][3][0]))) , l_3489);
+ (****g_2620) = 7L;
+ return (*g_1739);
+ }
+ }
+ else
+ { /* block id: 1625 */
+ const int32_t *l_3501 = &g_75[0];
+ int64_t *l_3514[1];
+ int i;
+ for (i = 0; i < 1; i++)
+ l_3514[i] = &l_3374;
+ (****g_2620) = ((((((l_3502 , (-1L)) == 0x94D1ECE486E951AELL) , (*l_3501)) , (**g_267)) < l_3494[1][1]) & (**g_267));
+ l_3370 &= ((safe_rshift_func_uint8_t_u_s(((((safe_mod_func_uint32_t_u_u(((safe_sub_func_uint8_t_u_u((l_3483 ^= (l_6 , ((safe_rshift_func_int16_t_s_u((safe_unary_minus_func_int16_t_s((((*g_127) == ((*l_3429) > (*l_3429))) & (((*g_856) = (*g_856)) == ((l_3363 &= (g_3515 = l_5)) , l_3516[0][0]))))), (((safe_add_func_uint32_t_u_u(((safe_div_func_int8_t_s_s((safe_lshift_func_uint8_t_u_s((*g_983), (((*g_1000) = ((*l_3429) || l_3523)) < (*g_1701)))), g_458.f0)) > (*g_268)), 0xE7B98EBDL)) ^ l_3446[0]) <= (*g_127)))) | l_3482))), (*l_3501))) ^ 1L), l_3489)) ^ (***g_276)) ^ 0x6712AC90L) & (*l_3429)), 4)) ^ (*g_127));
+ }
+ if (((safe_rshift_func_int8_t_s_u((*l_3429), 4)) & (((l_3369 &= l_3375) | (((**g_1700) = (((l_3419[2] , (safe_rshift_func_uint8_t_u_s((+(safe_lshift_func_uint16_t_u_s(((g_458.f1 , l_3530) != l_3533), 3))), 5))) && (l_3502 , l_3538)) >= 5L)) && 0x5B78E17CL)) || (*g_127))))
+ { /* block id: 1636 */
+ int32_t l_3546 = (-2L);
+ int32_t l_3547 = 0x4E086909L;
+ int64_t l_3549 = (-3L);
+ int32_t l_3550 = 0L;
+ int8_t l_3574 = 0x5FL;
+ uint32_t *l_3575[4][4][2] = {{{&g_1860,&g_204},{&g_1860,&g_3322[2]},{&g_204,&g_3322[2]},{&g_1860,&g_204}},{{&g_1860,&g_3322[2]},{&g_204,&g_3322[2]},{&g_1860,&g_204},{&g_1860,&g_3322[2]}},{{&g_204,&g_3322[2]},{&g_1860,&g_204},{&g_1860,&g_3322[2]},{&g_204,&g_3322[2]}},{{&g_1860,&g_204},{&g_1860,&g_3322[2]},{&g_204,&g_3322[2]},{&g_1860,&g_204}}};
+ int8_t l_3579 = 0L;
+ int16_t ***l_3594[6][5][1];
+ int i, j, k;
+ for (i = 0; i < 6; i++)
+ {
+ for (j = 0; j < 5; j++)
+ {
+ for (k = 0; k < 1; k++)
+ l_3594[i][j][k] = &g_2230;
+ }
+ }
+ for (l_3495 = 13; (l_3495 > 19); ++l_3495)
+ { /* block id: 1639 */
+ if (l_3228.f0)
+ goto lbl_3541;
+ (***g_2621) = (l_3542[2] != l_3543);
+ (****g_2620) = 0xA5091839L;
+ }
+ --l_3555;
+ l_3547 ^= ((((***g_1175) | (safe_mod_func_int8_t_s_s((safe_rshift_func_int16_t_s_s((safe_add_func_uint64_t_u_u((safe_sub_func_int64_t_s_s((l_3426 != (void*)0), l_3482)), (***g_276))), 5)), (safe_add_func_int32_t_s_s((safe_lshift_func_int16_t_s_s(((((*l_3429) = (*g_1000)) >= l_3550) || (safe_add_func_uint32_t_u_u((safe_sub_func_uint64_t_u_u(((*g_1700) != ((l_3574 = (l_3436[4] || l_3544)) , l_3575[0][2][0])), (*l_3429))), l_3436[2]))), (**g_1744))), l_3549))))) >= 6L) <= 0xC7L);
+ (**g_2622) = ((safe_mul_func_uint16_t_u_u((*g_643), (l_3580++))) == (safe_add_func_int64_t_s_s(((l_3590[3] = (((--(*l_3240)) <= ((***g_276) = l_3574)) == (safe_mul_func_int16_t_s_s(0xD1B3L, (safe_unary_minus_func_uint32_t_u((**g_1700))))))) | (safe_lshift_func_int16_t_s_u(0L, 13))), ((((((*l_3543) ^= ((void*)0 == g_3593)) < (*g_1739)) == ((l_3594[4][4][0] != l_3595) < 0x384FL)) , g_746) , 0L))));
+ }
+ else
+ { /* block id: 1654 */
+ uint32_t ******l_3599[8];
+ int32_t l_3609 = (-2L);
+ int32_t *l_3610 = &l_3551;
+ int8_t l_3622 = 3L;
+ int i;
+ for (i = 0; i < 8; i++)
+ l_3599[i] = &l_3598;
+ (***g_2978) = func_51(((*l_3158) ^= (!((g_3600[3][1][4] = (g_778 , l_3598)) == (((*l_3298) = (*g_457)) , (void*)0)))), ((((safe_add_func_uint16_t_u_u(((safe_mul_func_int8_t_s_s((((safe_lshift_func_uint8_t_u_s(((*g_983) = (((***g_1175) == (!((safe_unary_minus_func_int32_t_s(0x9CE8AE23L)) < 0xF4L))) || ((*g_983) , (l_3609 | g_135)))), l_3538)) > 3UL) & 0xE0A3L), l_3370)) , 65534UL), l_3363)) < l_3609) & (**g_2631)) ^ g_3176[0]), l_3489, &l_3388, l_3610);
+ (****g_2620) = l_3436[4];
+ for (g_3578 = 28; (g_3578 <= (-29)); --g_3578)
+ { /* block id: 1663 */
+ const uint32_t l_3615 = 0x1A635137L;
+ int32_t l_3623 = 0xFC5CCCB4L;
+ (****g_2978) ^= (**g_267);
+ (*g_267) = func_99(l_3482, (((**g_3116) = (!(((l_3494[0][2] <= (***g_1175)) && 0xCCDC2293L) , 1UL))) >= (l_3623 |= (safe_add_func_int64_t_s_s((*l_3610), ((l_3615 && (safe_mul_func_int16_t_s_s(l_3494[0][2], (safe_lshift_func_int8_t_s_u((((*l_3158) = (!(safe_mod_func_uint64_t_u_u((((*l_3429) | l_3622) , (*l_3610)), 2UL)))) > g_1337), (*l_3610)))))) , l_3489))))), (*g_457), (**g_276), (**g_276));
+ ++l_3626;
+ }
+ }
+ (**g_999) = (safe_rshift_func_uint16_t_u_u((((*l_3429) = l_3489) >= ((safe_mul_func_int8_t_s_s(((safe_unary_minus_func_uint64_t_u(((void*)0 != l_3634))) > ((safe_add_func_uint32_t_u_u((1UL > (safe_lshift_func_int8_t_s_s((safe_lshift_func_int8_t_s_s((safe_mul_func_uint16_t_u_u((((safe_sub_func_uint32_t_u_u((((***l_3595) = ((((*l_3437) = &g_647[5][0]) != (void*)0) > (((((l_3362 , ((safe_lshift_func_int8_t_s_s(((*l_3655) = (((-5L) == ((safe_div_func_uint16_t_u_u(((**g_1574)++), (safe_lshift_func_uint16_t_u_u((((((*l_3654) = ((*l_3158) = 0xE9L)) >= g_2033[0]) , l_3483) && 18446744073709551614UL), (*****g_3348))))) | 65528UL)) , l_3489)), g_133)) | 0xE2CB313EB04FFBB3LL)) && (**g_1700)) || 254UL) > 0xAC2D93AAL) <= l_3538))) , 0UL), l_3656)) < l_3375) , l_3580), l_3369)), g_409[0][0])), l_3436[4]))), (****g_2620))) , l_3489)), (*g_983))) < l_3371)), 9));
+ (*g_999) = &l_3553[5];
+ }
+ if ((safe_sub_func_int32_t_s_s(0x09312BA0L, ((l_3659 == (void*)0) <= (safe_sub_func_int64_t_s_s((((*g_983) = (+((l_5 ^ ((*l_3429) |= ((*g_1000) = ((safe_mod_func_int16_t_s_s(((*g_457) , ((func_97(&l_3551) , (**g_1574)) , (l_3446[4] != l_3664))), l_3665)) && 0L)))) && (-1L)))) || (*g_983)), l_3363))))))
+ { /* block id: 1685 */
+ for (l_3228.f1 = 0; (l_3228.f1 <= 19); l_3228.f1++)
+ { /* block id: 1688 */
+ for (g_1086 = 29; (g_1086 > (-2)); g_1086--)
+ { /* block id: 1691 */
+ if ((****g_2978))
+ break;
+ }
+ }
+ for (l_3624 = 0; (l_3624 < (-21)); --l_3624)
+ { /* block id: 1697 */
+ if ((*l_3429))
+ break;
+ }
+ }
+ else
+ { /* block id: 1700 */
+ int64_t ** const l_3680 = &g_127;
+ int32_t l_3690 = (-9L);
+ int32_t l_3691 = (-9L);
+ uint32_t l_3692 = 0x6CBB8C67L;
+ int16_t *l_3700[6];
+ int16_t l_3748 = 0xD93AL;
+ int16_t l_3792 = (-6L);
+ uint64_t * const * const ***l_3794 = (void*)0;
+ uint64_t * const * const **** const l_3793 = &l_3794;
+ int64_t l_3795 = 0x2DEEDFD4EC26300BLL;
+ int16_t l_3813 = 0x5ABEL;
+ uint32_t ***l_3824 = &g_1700;
+ int32_t *****l_3839 = &g_2978;
+ int32_t ******l_3838 = &l_3839;
+ int i;
+ for (i = 0; i < 6; i++)
+ l_3700[i] = &g_408;
+ (**g_999) = (g_78 != (*l_3429));
+ if (l_3523)
+ goto lbl_3862;
+ if (((*l_3429) = (safe_mul_func_int8_t_s_s(g_146, ((*g_983) = ((safe_rshift_func_int16_t_s_u((l_3693 &= (((*g_1701) , (0xE5L <= ((safe_mod_func_uint16_t_u_u((((*g_1739) > l_3371) || ((safe_sub_func_int8_t_s_s(((l_3680 != ((((safe_mul_func_uint16_t_u_u((****g_3349), (safe_sub_func_int32_t_s_s((l_3690 = ((**g_2622) = (l_5 ^ (safe_sub_func_uint64_t_u_u(((~(safe_lshift_func_int8_t_s_s((-1L), l_3371))) != 0x1357C7A0L), l_3689))))), l_3419[2])))) != (**g_3116)) , 1L) , (void*)0)) , (*l_3429)), l_3691)) > l_3446[1])), (*g_1739))) >= l_3692))) || (*l_3429))), 6)) | 0x8AD29F6C6A38AA53LL))))))
+ { /* block id: 1707 */
+ int64_t l_3694 = 1L;
+ int32_t l_3695 = 3L;
+ uint8_t *l_3699 = &l_3555;
+ union U0 ***l_3711 = &l_3534[0];
+ if ((((((((*l_3298) , 1L) <= ((*l_3699) = ((0L ^ (l_3695 = l_3694)) && (safe_unary_minus_func_uint8_t_u((--(*g_983))))))) <= ((l_3694 <= (((((l_3700[3] != (void*)0) < ((**g_3116) = (**g_1574))) , (**g_267)) || 4294967287UL) ^ 0x0D56CD8E1D75A02ELL)) | 0xF31DCA78L)) <= l_3690) , (**g_3348)) != (void*)0))
+ { /* block id: 1712 */
+ (****g_2620) &= (safe_rshift_func_uint16_t_u_s(((g_3705 = l_3703) == &l_3543), l_3695));
+ return (*g_1739);
+ }
+ else
+ { /* block id: 1716 */
+ int16_t l_3712[8][6][5] = {{{(-1L),0x482FL,0x4D1EL,0xA893L,0x63D4L},{(-1L),0x00CCL,0x00CCL,(-1L),(-9L)},{1L,0xA893L,(-6L),(-1L),0x4207L},{(-9L),0x00CCL,0x189DL,(-9L),(-9L)},{0xA2F2L,0x482FL,0xA2F2L,(-1L),0x4D1EL},{0xD746L,(-1L),(-9L),(-1L),0xD746L}},{{0xA2F2L,(-1L),(-1L),0xA893L,(-1L)},{(-9L),(-9L),(-9L),0xD746L,0xB2A8L},{1L,(-1L),0xA2F2L,(-1L),(-1L)},{(-1L),0xD746L,0x189DL,0x189DL,0x189DL},{0x63D4L,0xA893L,0x4D1EL,0x482FL,(-1L)},{0xD746L,0xB2A8L,0xD746L,(-9L),(-9L)}},{{(-6L),(-1L),(-1L),(-1L),(-6L)},{0xD746L,0x00CCL,0xB2A8L,0x189DL,0xB2A8L},{0x63D4L,(-1L),(-1L),(-1L),1L},{0x00CCL,0xD746L,0xD746L,0x00CCL,0xB2A8L},{0xA2F2L,(-1L),0x4D1EL,0x4A24L,(-6L)},{0xB2A8L,0xD746L,(-9L),(-9L),(-9L)}},{{0x4207L,(-1L),0x4207L,0x4A24L,(-1L)},{0x189DL,0x00CCL,(-9L),0x00CCL,0x189DL},{0x4207L,(-1L),0x63D4L,(-1L),0x63D4L},{0xB2A8L,0xB2A8L,(-9L),0x189DL,(-1L)},{0xA2F2L,0xA893L,0x4207L,(-1L),0x63D4L},{0x00CCL,0x189DL,(-9L),(-9L),0x189DL}},{{0x63D4L,0xA893L,0x4D1EL,0x482FL,(-1L)},{0xD746L,0xB2A8L,0xD746L,(-9L),(-9L)},{(-6L),(-1L),(-1L),(-1L),(-6L)},{0xD746L,0x00CCL,0xB2A8L,0x189DL,0xB2A8L},{0x63D4L,(-1L),(-1L),(-1L),1L},{0x00CCL,0xD746L,0xD746L,0x00CCL,0xB2A8L}},{{0xA2F2L,(-1L),0x4D1EL,0x4A24L,(-6L)},{0xB2A8L,0xD746L,(-9L),(-9L),(-9L)},{0x4207L,(-1L),0x4207L,0x4A24L,(-1L)},{0x189DL,0x00CCL,(-9L),0x00CCL,0x189DL},{0x4207L,(-1L),0x63D4L,(-1L),0x63D4L},{0xB2A8L,0xB2A8L,(-9L),0x189DL,(-1L)}},{{0xA2F2L,0xA893L,0x4207L,(-1L),0x63D4L},{0x00CCL,0x189DL,(-9L),(-9L),0x189DL},{0x63D4L,0xA893L,0x4D1EL,0x482FL,(-1L)},{0xD746L,0xB2A8L,0xD746L,(-9L),(-9L)},{(-6L),(-1L),(-1L),(-1L),(-6L)},{0xD746L,0x00CCL,0xB2A8L,0x189DL,0xB2A8L}},{{0x63D4L,(-1L),(-1L),(-1L),1L},{0x00CCL,0xD746L,0xD746L,0x00CCL,0xB2A8L},{0xA2F2L,(-1L),0x4D1EL,0x4A24L,(-6L)},{0xB2A8L,0xD746L,(-9L),(-9L),(-9L)},{0x4207L,(-1L),0x4207L,0x4A24L,(-1L)},{0x189DL,0x00CCL,(-9L),0x00CCL,(-9L)}}};
+ const uint32_t ***l_3715 = &g_3713[0];
+ int i, j, k;
+ (*l_3429) &= (**g_2622);
+ (**g_2622) = ((((((void*)0 == (*l_3314)) , &g_3349) == &g_2981) > ((safe_mod_func_int64_t_s_s((((((((((void*)0 == l_3711) == ((l_3712[7][5][4] | (((*l_3715) = (((-4L) <= (0x4E8EA59DL != l_3690)) , g_3713[1])) != l_3716)) <= (*g_983))) , l_3690) || 1UL) || 0x80L) ^ l_6) & l_3712[7][5][4]) && (*l_3429)), 2UL)) > 0xD7L)) ^ (*l_3429));
+ (***g_1175) = ((safe_mod_func_uint8_t_u_u((safe_mul_func_int16_t_s_s(l_3690, ((*l_3543) = (((0x7EL ^ (*l_3429)) , ((l_3736 = (((**g_1700) = (safe_mul_func_int16_t_s_s((((l_3363 & 0x91F6L) | (*l_3429)) && (safe_lshift_func_uint16_t_u_s(((safe_rshift_func_int16_t_s_s(((*l_3429) = 7L), (((*g_457) , (((~(safe_sub_func_int8_t_s_s((safe_lshift_func_int8_t_s_s((safe_add_func_int32_t_s_s(((safe_mul_func_int16_t_s_s(l_3694, 1L)) >= l_3580), l_3735)), 0)), 0UL))) , l_3690) & 0x6822B2381C627CA9LL)) != l_3695))) && 18446744073709551606UL), 12))), (*g_1739)))) <= l_3664)) & l_3690)) == l_3691)))), (*g_983))) , 1L);
+ }
+ if ((safe_unary_minus_func_uint32_t_u((safe_unary_minus_func_int32_t_s((!((g_133 , ((safe_mul_func_int8_t_s_s((safe_mul_func_int16_t_s_s(((safe_sub_func_int64_t_s_s(0x26C8E728EBABCF00LL, (safe_sub_func_uint16_t_u_u(1UL, l_3736)))) <= l_3695), (safe_unary_minus_func_int32_t_s((l_3748 ^ (++(**g_1700))))))), (safe_sub_func_uint64_t_u_u(l_3753, (*l_3429))))) || ((safe_lshift_func_uint8_t_u_s((safe_lshift_func_int16_t_s_s(l_3758, l_3695)), l_3495)) , l_3759[0]))) >= l_3695)))))))
+ { /* block id: 1727 */
+ int32_t **l_3760 = &l_3[7][8][1];
+ (*l_3760) = (**g_2621);
+ }
+ else
+ { /* block id: 1729 */
+ int64_t l_3791 = (-7L);
+ (**g_2622) = ((((safe_lshift_func_int16_t_s_s((safe_mod_func_int64_t_s_s((((-9L) == (((*l_3543) = (safe_sub_func_uint32_t_u_u(((**g_1700) ^= l_3748), (((((safe_mul_func_int8_t_s_s((((safe_mul_func_uint16_t_u_u((g_3771 != (((safe_lshift_func_int16_t_s_s((((((safe_mul_func_uint8_t_u_u(l_3694, (8L && (4294967293UL & (*g_3714))))) & ((safe_mul_func_uint8_t_u_u((safe_unary_minus_func_uint8_t_u((!(safe_add_func_int32_t_s_s((4L ^ ((safe_mod_func_int8_t_s_s(((safe_div_func_uint32_t_u_u((safe_add_func_int16_t_s_s(((safe_mod_func_int8_t_s_s(((((((**l_3385) = (**l_3389)) != (void*)0) & 0x33A3L) && l_3790[0][4]) || 0x233F04E3L), 0x28L)) || (**g_999)), l_3694)), l_3791)) >= 0xB1L), l_3691)) ^ 0x3CBEL)), l_3792))))), l_3791)) <= 0x7B71L)) < (*g_1000)) != 1L) > (*g_127)), 6)) , l_3748) , l_3793)), (*l_3429))) & l_3368) || 0x36914F2FD50638ECLL), 0xD0L)) > 0L) , (void*)0) == g_1185) , (*l_3429))))) >= (-5L))) > l_3419[2]), l_3695)), 4)) | (*l_3429)) | l_3495) ^ l_3795);
+ return l_3791;
+ }
+ }
+ else
+ { /* block id: 1736 */
+ uint64_t * const l_3798 = &l_3656;
+ int32_t l_3803[8][4][1] = {{{(-1L)},{1L},{(-1L)},{1L}},{{(-1L)},{1L},{(-1L)},{1L}},{{(-1L)},{1L},{(-1L)},{1L}},{{(-1L)},{1L},{(-1L)},{1L}},{{(-1L)},{1L},{(-1L)},{1L}},{{(-1L)},{1L},{(-1L)},{1L}},{{(-1L)},{1L},{(-1L)},{1L}},{{(-1L)},{1L},{(-1L)},{1L}}};
+ const uint32_t ****l_3826 = &l_3825[0][0];
+ union U0 ***l_3837 = &l_3534[4];
+ int32_t l_3853[9][7][4] = {{{0xB571F11DL,9L,(-1L),1L},{0xD0FA9223L,4L,(-2L),8L},{8L,1L,2L,1L},{0x489591CBL,(-5L),0x84DAE1CFL,0x1225A671L},{9L,1L,0xC3ACAE87L,0xF1EB5902L},{1L,(-1L),0x91EB2A23L,7L},{(-1L),0L,0L,(-1L)}},{{(-1L),0xE828EEB4L,3L,1L},{4L,0xBB7E3BACL,0xE28983ADL,0x10FCC4E9L},{0xBB7E3BACL,0L,0x1225A671L,0x053AB736L},{(-1L),1L,0xE8131784L,0xF1EB5902L},{0x7A8086E9L,0x84DAE1CFL,0xC416942FL,9L},{7L,(-5L),7L,(-1L)},{9L,(-10L),(-10L),8L}},{{0x0C547A2AL,1L,0x7D2C2085L,(-10L)},{0x1AB709E8L,9L,0x7D2C2085L,(-1L)},{0x0C547A2AL,7L,(-10L),(-1L)},{9L,(-1L),7L,0x0C547A2AL},{7L,0x0C547A2AL,0xC416942FL,0xB571F11DL},{0x7A8086E9L,0x1FB3E971L,0xE8131784L,0x7A8086E9L},{(-1L),(-1L),0x1225A671L,0x662EFE13L}},{{0xBB7E3BACL,1L,0xE28983ADL,(-1L)},{4L,(-3L),3L,1L},{(-1L),0xC416942FL,0L,0x662EFE13L},{(-1L),0x10FCC4E9L,0x91EB2A23L,0xE28983ADL},{1L,0x1FB3E971L,0xC3ACAE87L,0xD0FA9223L},{9L,1L,0x84DAE1CFL,0x0C547A2AL},{0x489591CBL,1L,2L,0x21B8CC8CL}},{{8L,7L,(-2L),0x1FB3E971L},{0xD0FA9223L,0L,(-1L),(-10L)},{0xB571F11DL,4L,0x21B8CC8CL,0L},{8L,(-10L),0L,1L},{0x2502D502L,0x73A90A79L,0x84DAE1CFL,9L},{0L,1L,1L,1L},{1L,1L,(-7L),7L}},{{0x1FB3E971L,7L,0L,0x10FCC4E9L},{0x91EB2A23L,0xE828EEB4L,1L,0L},{4L,0xE828EEB4L,8L,0x10FCC4E9L},{0xE828EEB4L,7L,0x1225A671L,7L},{(-1L),1L,1L,0x003CE246L},{0xC416942FL,(-1L),(-3L),0x7D2C2085L},{1L,0xC3ACAE87L,0x6D7917C2L,0x68B24717L}},{{0x57110039L,0xBB7E3BACL,6L,0xE8131784L},{0x1AB709E8L,0x84DAE1CFL,0xA66F9617L,0xBB7E3BACL},{0x489591CBL,6L,0x13596ED7L,0xB571F11DL},{0L,1L,6L,1L},{0x7D2C2085L,7L,(-10L),0x1AB709E8L},{1L,0L,0L,0x053AB736L},{(-1L),0xB571F11DL,1L,(-1L)}},{{0L,0L,1L,0x21B8CC8CL},{0x91EB2A23L,0L,(-1L),7L},{0xE49BE893L,(-1L),0L,0xCA2FA527L},{0L,2L,0x7A8086E9L,0x21B8CC8CL},{0xB571F11DL,1L,(-10L),0xC416942FL},{(-1L),0xB571F11DL,0x003CE246L,0x71246B4AL},{0x1225A671L,0x1AB709E8L,0x10FCC4E9L,0x1AB709E8L}},{{0x73A90A79L,0xCA2FA527L,(-1L),(-1L)},{0xE8131784L,1L,1L,1L},{0x053AB736L,0x1225A671L,0L,0xBB7E3BACL},{0x053AB736L,0xE49BE893L,1L,(-1L)},{0xE8131784L,0xBB7E3BACL,(-1L),(-1L)},{0x73A90A79L,1L,0x10FCC4E9L,0x7D2C2085L},{0x1225A671L,0x807C8DCEL,0x003CE246L,(-1L)}}};
+ int i, j, k;
+ (*g_999) = func_13((*g_983));
+ (***g_1175) = (((((safe_sub_func_int64_t_s_s((&l_3693 == l_3798), (*l_3429))) != ((((((safe_mul_func_uint8_t_u_u((((((safe_add_func_uint8_t_u_u(0UL, 0L)) < (((l_3690 < l_3803[5][2][0]) , ((safe_mod_func_uint32_t_u_u((safe_add_func_uint64_t_u_u((safe_div_func_int16_t_s_s(((&g_3600[3][1][4] != (func_97(func_13(((*g_983)--))) , (void*)0)) >= l_3812), l_3419[2])), l_3795)), (*l_3429))) == 1L)) ^ l_3813)) , (**g_642)) <= 0x2027L) <= (*l_3429)), g_3515)) && 0xCFL) ^ l_7) & l_3814) & 0x0B8C30BBDC12EE56LL) , l_3691)) || g_3815) <= (-1L)) && l_3690);
+ if ((l_3803[5][2][0] | (((0x85L || l_3691) < ((((**l_3680) = (~((safe_sub_func_int32_t_s_s(0x8D33576CL, (safe_rshift_func_uint8_t_u_u((safe_add_func_int8_t_s_s((((safe_lshift_func_uint16_t_u_s(((*g_127) != ((l_3824 == ((*l_3826) = (l_3748 , l_3825[0][0]))) || ((((l_3827[0] != (**g_3349)) || 0x1CL) == 0xE8B82DC7BBA9FDFCLL) && l_3828))), 2)) , 0xDDL) <= 1UL), l_3803[4][2][0])), l_3748)))) && (*l_3429)))) || 0L) , l_3664)) >= l_3829)))
+ { /* block id: 1742 */
+ int32_t *l_3836 = &g_75[2];
+ (***g_2621) |= (0x3F81L <= (safe_mul_func_int16_t_s_s((safe_lshift_func_uint16_t_u_u(((**g_642)--), 9)), 0xF858L)));
+ (**g_1175) = l_3836;
+ }
+ else
+ { /* block id: 1746 */
+ int16_t l_3841 = 0x5F4CL;
+ int32_t l_3852 = 0L;
+ uint64_t *****l_3854 = &g_1567;
+ int32_t l_3855[6][6] = {{3L,1L,3L,3L,1L,3L},{3L,1L,3L,3L,1L,3L},{3L,1L,3L,3L,1L,3L},{3L,1L,3L,3L,1L,3L},{3L,1L,3L,3L,1L,3L},{3L,1L,3L,3L,1L,3L}};
+ int i, j;
+ (**g_2622) = (((g_1185 == l_3837) && (l_3838 == l_3840)) < l_3803[5][1][0]);
+ l_3855[1][2] |= ((l_3841 != ((safe_add_func_uint64_t_u_u((((l_3853[3][3][2] ^= (safe_sub_func_uint64_t_u_u(((((*g_127) &= (l_3852 ^= (l_3846 && ((((((**l_3703) = ((******l_3838) <= ((**g_2620) == (void*)0))) , (g_3847 , (safe_rshift_func_int8_t_s_u(l_3803[5][1][0], (safe_mul_func_uint8_t_u_u((*g_983), 255UL)))))) , (***g_2621)) <= (*g_3714)) < 0xFB0546D3BB5BDDC7LL)))) , (*g_3310)) == (*g_3310)), 5L))) , l_3389) != l_3854), l_3841)) == l_3664)) || 1L);
+ }
+ }
+lbl_3862:
+ l_3369 = ((l_3856 >= (*g_643)) & (((l_3857 = l_3857) == (((*****l_3839) = l_3580) , l_3858)) ^ (l_5 &= (safe_rshift_func_int16_t_s_u(0L, 14)))));
+ for (l_6 = 0; (l_6 < 6); l_6++)
+ { /* block id: 1762 */
+ int8_t l_3869 = 0x66L;
+ int32_t l_3881 = 9L;
+ int16_t *l_3885 = (void*)0;
+ if ((*****l_3839))
+ { /* block id: 1763 */
+ int8_t **l_3870 = (void*)0;
+ int8_t **l_3871 = &g_3328;
+ uint8_t l_3882 = 1UL;
+ uint64_t **** const **l_3910 = &l_3909[2];
+ uint8_t l_3911[4] = {0x92L,0x92L,0x92L,0x92L};
+ const int32_t *l_3914 = &l_3881;
+ int i;
+ g_3879 |= (((safe_add_func_uint64_t_u_u((safe_mul_func_int16_t_s_s(l_3869, (*g_1739))), (&g_708 == ((*l_3871) = (void*)0)))) , (((((*****l_3839) == ((0x80L && ((*g_983) = (*g_983))) , l_3872)) && (safe_add_func_int64_t_s_s((((safe_div_func_int8_t_s_s((safe_mul_func_int16_t_s_s(0x5326L, (*l_3429))), (*g_983))) & 0L) ^ (*l_3429)), 1L))) > (*****l_3839)) , 0x75F6BE4B492A4C37LL)) , (**g_267));
+ l_3882++;
+ (******l_3838) = (**g_2622);
+ l_3914 = func_99((*****l_3839), ((((void*)0 != l_3885) == ((safe_mod_func_uint32_t_u_u(((safe_sub_func_uint64_t_u_u((safe_add_func_int64_t_s_s(((((((safe_sub_func_int64_t_s_s(((((safe_lshift_func_uint16_t_u_s((safe_sub_func_uint16_t_u_u((safe_rshift_func_int16_t_s_s((l_3881 , (safe_mod_func_uint64_t_u_u(((safe_lshift_func_uint8_t_u_s((safe_sub_func_uint8_t_u_u((*****l_3839), (*g_983))), 4)) , ((0x433AL || ((*l_3543) = (+((l_3908 < ((((*l_3910) = l_3909[4]) != (*g_3771)) || l_3911[1])) >= 0x39BC5FC44F688776LL)))) != (*g_643))), (*g_127)))), l_3912[0])), (*g_643))), 13)) ^ l_3869) == 0x0D9A3BF5L) , l_3911[0]), (*****l_3839))) && l_3869) , (void*)0) != &g_277[0]) > (*g_2632)) & (**g_642)), (******l_3838))), 0xA445774BC6D1CC7ALL)) < 0UL), 0x210284B3L)) , l_3882)) , 0x7739L), (*l_3438), g_3913, &l_3625);
+ }
+ else
+ { /* block id: 1772 */
+ int32_t **l_3915 = &l_3[7][8][1];
+ (*l_3915) = (***g_2620);
+ if ((*g_268))
+ break;
+ }
+ return (*l_3429);
+ }
+ }
+ l_3362 &= (safe_sub_func_uint64_t_u_u(((*l_3240) ^= (safe_sub_func_uint16_t_u_u((safe_rshift_func_int16_t_s_u(0L, (--(**g_1574)))), (((safe_add_func_int8_t_s_s((safe_mod_func_int64_t_s_s((((*g_1701) = (safe_rshift_func_int8_t_s_s((safe_rshift_func_int8_t_s_s((((*g_983) > ((safe_div_func_uint8_t_u_u(((&g_3601 != l_3934) & (safe_mul_func_uint8_t_u_u((safe_sub_func_int64_t_s_s((***g_276), (*g_127))), ((*****g_3348) <= (l_3419[2] > ((safe_add_func_uint8_t_u_u((l_7 != l_3912[3]), 0x03L)) == l_3912[2])))))), 3UL)) > 0x47L)) | (*l_3429)), g_2797)), 4))) != (-6L)), 2L)), l_3363)) , (*l_3429)) , 0x86BCL)))), l_3664));
+ }
+ }
+ else
+ { /* block id: 1784 */
+ int32_t l_3943[3];
+ int32_t l_3954 = (-1L);
+ uint16_t ****l_3978 = (void*)0;
+ uint16_t *****l_3977[1];
+ const uint32_t *l_3980 = &l_2;
+ uint32_t **l_3986 = &g_1701;
+ uint32_t *******l_3990 = &l_3989;
+ uint32_t *******l_3991 = (void*)0;
+ uint32_t ******l_3993[10] = {&g_3600[4][2][3],&g_3600[4][2][3],&g_3600[4][2][3],&g_3600[4][2][3],&g_3600[4][2][3],&g_3600[4][2][3],&g_3600[4][2][3],&g_3600[4][2][3],&g_3600[4][2][3],&g_3600[4][2][3]};
+ uint32_t *******l_3992 = &l_3993[3];
+ uint64_t *****l_3998[3];
+ int32_t l_4006 = 0x80D0535EL;
+ int i;
+ for (i = 0; i < 3; i++)
+ l_3943[i] = 0x14357B69L;
+ for (i = 0; i < 1; i++)
+ l_3977[i] = &l_3978;
+ for (i = 0; i < 3; i++)
+ l_3998[i] = &g_1567;
+ (**g_999) &= (-1L);
+ for (g_3407 = 26; (g_3407 >= (-14)); g_3407--)
+ { /* block id: 1788 */
+ uint32_t l_3947 = 1UL;
+ uint32_t **l_3979[8][9] = {{(void*)0,(void*)0,(void*)0,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701},{&g_1701,(void*)0,&g_1701,&g_1701,&g_1701,(void*)0,&g_1701,&g_1701,&g_1701},{&g_1701,&g_1701,&g_1701,&g_1701,(void*)0,(void*)0,(void*)0,&g_1701,&g_1701},{&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,(void*)0,&g_1701,(void*)0},{&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701},{&g_1701,&g_1701,(void*)0,&g_1701,&g_1701,&g_1701,&g_1701,(void*)0,&g_1701},{&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701},{&g_1701,(void*)0,&g_1701,(void*)0,&g_1701,&g_1701,&g_1701,&g_1701,&g_1701}};
+ int32_t l_3985 = (-6L);
+ int i, j;
+ for (l_2 = 0; (l_2 <= 5); l_2 += 1)
+ { /* block id: 1791 */
+ int32_t l_3953 = 0x2CBB6FB6L;
+ int8_t *l_3968 = (void*)0;
+ int8_t *l_3969 = (void*)0;
+ int8_t *l_3970 = (void*)0;
+ int8_t *l_3971 = &g_458.f3;
+ int32_t l_3972 = 0x21880BDEL;
+ int i, j;
+ (**g_2622) = (l_3943[0] , (*g_268));
+ (***g_1175) |= (l_3944 <= (safe_lshift_func_uint8_t_u_s(((l_3947 && (l_3943[0] == ((((*l_3158) |= (safe_rshift_func_uint16_t_u_u(l_3950, 13))) | (g_3254 = (safe_rshift_func_uint8_t_u_u(l_3953, 5)))) != ((*g_983)++)))) <= (safe_mod_func_uint64_t_u_u((l_3495 && (safe_lshift_func_uint8_t_u_u((safe_lshift_func_int8_t_s_s((safe_unary_minus_func_int64_t_s((safe_sub_func_uint32_t_u_u((safe_mul_func_int8_t_s_s(((*l_3971) = l_3954), (l_3943[1] | (*****g_3348)))), l_3664)))), l_3972)), l_3947))), l_3972))), 6)));
+ }
+ (**g_999) = ((((((**l_3596) = (safe_mod_func_uint8_t_u_u(((safe_lshift_func_uint16_t_u_u(((void*)0 != l_3977[0]), 7)) & (l_3979[4][5] != (((*g_457) = ((l_3947 && (l_3954 ^= ((l_3943[0] || (l_3980 != (((safe_rshift_func_int16_t_s_s(((****g_2978) | ((safe_mod_func_uint8_t_u_u(l_3947, l_3985)) != l_3943[1])), 7)) | l_3943[2]) , l_3980))) ^ 0xF710904B1728434FLL))) , (*g_457))) , l_3986))), l_3943[2]))) & (*g_2632)) < 0UL) >= 0x51L) ^ l_3944);
+ if (g_3515)
+ goto lbl_4001;
+ }
+lbl_4001:
+ (***g_1175) = (safe_div_func_uint16_t_u_u(0x3752L, ((((*l_3990) = l_3989) == ((*l_3992) = &g_3600[3][1][4])) , ((((safe_add_func_uint16_t_u_u((safe_mul_func_uint16_t_u_u(l_3371, ((((l_3998[0] != (void*)0) & ((((l_3954 , (safe_mul_func_uint16_t_u_u((*g_2632), ((l_3943[0] , 0xF4L) >= 1UL)))) <= 0L) | 0xF16E067CL) < (-2L))) != 9UL) > l_3362))), (*g_643))) , (void*)0) == (void*)0) , 0x3FC4L))));
+ for (g_458.f2 = 12; (g_458.f2 < 6); g_458.f2--)
+ { /* block id: 1810 */
+ uint16_t l_4014 = 0UL;
+ for (g_3879 = 0; (g_3879 >= 0); g_3879++)
+ { /* block id: 1813 */
+ int32_t *l_4007 = &l_7;
+ int32_t *l_4008 = &g_75[0];
+ int32_t *l_4009 = &l_3362;
+ int32_t *l_4010 = (void*)0;
+ int32_t *l_4011 = (void*)0;
+ int32_t *l_4012[6] = {&l_3943[0],&l_3943[0],&l_3943[0],&l_3943[0],&l_3943[0],&l_3943[0]};
+ int64_t l_4013 = 0x2BE90AF3ABBB321ALL;
+ int i;
+ ++l_4014;
+ return l_4006;
+ }
+ return l_4014;
+ }
+ }
+ return l_4017;
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_20 g_999 g_1000
+ * writes: g_20
+ */
+static int32_t * func_13(uint8_t p_14)
+{ /* block id: 10 */
+ int32_t *l_15 = (void*)0;
+ int32_t *l_16 = (void*)0;
+ int32_t l_17[7][6] = {{2L,1L,0xDDB2097EL,1L,1L,0xDDB2097EL},{2L,(-1L),1L,(-3L),0xF8DE905FL,(-9L)},{0L,(-1L),1L,(-1L),1L,1L},{0x1450187EL,1L,1L,0x1450187EL,(-1L),(-9L)},{(-3L),3L,1L,0x1450187EL,(-9L),0xDDB2097EL},{0x1450187EL,(-9L),0xDDB2097EL,(-1L),(-9L),3L},{0L,3L,(-1L),(-3L),(-1L),3L}};
+ int32_t *l_18[7] = {&g_4[0],&g_4[0],&g_4[0],&g_4[0],&g_4[0],&g_4[0],&g_4[0]};
+ int8_t l_19 = 0xA6L;
+ int16_t l_21[7][4][1] = {{{0x8108L},{0x030DL},{1L},{1L}},{{1L},{0x030DL},{0x8108L},{0x030DL}},{{1L},{1L},{1L},{0x030DL}},{{0x8108L},{0x030DL},{1L},{1L}},{{1L},{0x030DL},{0x8108L},{0x030DL}},{{1L},{1L},{1L},{0x030DL}},{{0x8108L},{0x030DL},{1L},{1L}}};
+ uint64_t l_22 = 18446744073709551615UL;
+ uint16_t l_2653 = 65530UL;
+ uint32_t l_3086 = 4294967289UL;
+ int32_t ***l_3091 = &g_999;
+ int i, j, k;
+ l_22++;
+ for (l_19 = 0; (l_19 <= (-1)); l_19 = safe_sub_func_uint32_t_u_u(l_19, 9))
+ { /* block id: 14 */
+ int32_t *l_27[5];
+ int i;
+ for (i = 0; i < 5; i++)
+ l_27[i] = &l_17[3][1];
+ g_20 = 0x22E85F59L;
+ return &g_20;
+ }
+ for (g_20 = 0; (g_20 <= 15); g_20 = safe_add_func_int64_t_s_s(g_20, 7))
+ { /* block id: 20 */
+ union U0 l_43[1][9][2] = {{{{-6L},{0xEAL}},{{0x1EL},{-2L}},{{0x1EL},{0xEAL}},{{-6L},{-6L}},{{0xEAL},{0x1EL}},{{-2L},{0x1EL}},{{0xEAL},{-6L}},{{-6L},{0xEAL}},{{0x1EL},{-2L}}}};
+ int32_t *l_2652 = &g_4[4];
+ uint64_t *l_2654 = &g_132;
+ const uint32_t *l_3095 = &g_254;
+ const uint32_t **l_3094[8][7] = {{&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095},{&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095},{&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095},{&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095},{&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095},{&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095},{&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095},{&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095,&l_3095}};
+ uint16_t **l_3114 = &g_643;
+ uint16_t ***l_3115 = &g_642;
+ uint16_t ***l_3117 = (void*)0;
+ uint16_t ***l_3118 = &l_3114;
+ int i, j, k;
+ }
+ return (**l_3091);
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_642 g_643 g_177 g_209.f2 g_2193.f0 g_1739 g_384 g_1585 g_127 g_128 g_409 g_983 g_130 g_1175 g_999 g_1000 g_20 g_2620 g_2621 g_2622 g_267 g_268 g_4 g_135 g_2193.f1 g_1738 g_147 g_78 g_458.f2 g_1679 g_2866 g_159 g_888 g_276 g_277 g_2033 g_67 g_2895 g_2797 g_2632 g_380 g_1701 g_132 g_2307 g_1574 g_254 g_209.f3 g_2980 g_458.f3 g_2193.f3 g_458.f0 g_2978 g_206 g_1567 g_1568 g_1569 g_708
+ * writes: g_647 g_209.f2 g_384 g_2193.f0 g_2193.f2 g_177 g_1000 g_268 g_383 g_78 g_1744 g_458.f2 g_130 g_1567 g_1679 g_1585 g_128 g_253 g_2895 g_254 g_132 g_209.f3 g_2978 g_2797 g_4 g_458.f3 g_2193.f3 g_67 g_206 g_1569 g_2033 g_708 g_457
+ */
+static uint64_t func_34(int32_t p_35, uint64_t p_36, int8_t p_37, int32_t * p_38)
+{ /* block id: 1210 */
+ uint32_t l_2659 = 0xE6BBA822L;
+ const uint32_t *l_2661 = &l_2659;
+ const uint32_t **l_2660 = &l_2661;
+ uint32_t ***l_2662 = &g_647[5][0];
+ union U0 l_2663[9][8][3] = {{{{0L},{0L},{0x70L}},{{1L},{-1L},{-4L}},{{-1L},{1L},{0x3EL}},{{1L},{0xBEL},{5L}},{{-1L},{0L},{0L}},{{0x45L},{-5L},{0x45L}},{{-1L},{0x70L},{0x62L}},{{7L},{0x50L},{0x60L}}},{{{1L},{7L},{0x69L}},{{0x43L},{8L},{-6L}},{{1L},{-5L},{-2L}},{{7L},{0x19L},{0L}},{{-1L},{0L},{0x60L}},{{0x45L},{0x70L},{0x37L}},{{-1L},{-1L},{-1L}},{{1L},{-1L},{0x0BL}}},{{{8L},{0x70L},{-6L}},{{-1L},{0L},{5L}},{{-9L},{0x19L},{0x69L}},{{0x60L},{-5L},{-1L}},{{0x45L},{8L},{1L}},{{7L},{7L},{-1L}},{{-1L},{0x50L},{0x69L}},{{0L},{0x70L},{5L}}},{{{0x37L},{-5L},{-6L}},{{-9L},{0L},{0x0BL}},{{-1L},{0xBEL},{-1L}},{{-1L},{-1L},{0x37L}},{{-9L},{7L},{0x60L}},{{0x37L},{-1L},{0L}},{{0L},{8L},{-2L}},{{-1L},{0xBEL},{-6L}}},{{{7L},{-1L},{0x69L}},{{0x45L},{0xBEL},{0x60L}},{{0x60L},{8L},{0x62L}},{{-9L},{-1L},{0x45L}},{{-1L},{7L},{0L}},{{8L},{-1L},{5L}},{{1L},{0xBEL},{5L}},{{-1L},{0L},{0L}}},{{{0x45L},{-5L},{0x45L}},{{-1L},{0x70L},{0x62L}},{{7L},{0x50L},{0x60L}},{{1L},{7L},{0x69L}},{{0x43L},{8L},{-6L}},{{1L},{-5L},{-2L}},{{7L},{0x19L},{0L}},{{-1L},{0L},{0x60L}}},{{{0x45L},{0x70L},{0x37L}},{{-1L},{-1L},{-1L}},{{1L},{-1L},{0x0BL}},{{8L},{0x70L},{-6L}},{{-1L},{0L},{5L}},{{-9L},{0x19L},{0x69L}},{{0x60L},{-5L},{-1L}},{{0x45L},{8L},{1L}}},{{{7L},{7L},{-1L}},{{-1L},{0x50L},{0x69L}},{{0L},{0x70L},{5L}},{{0x37L},{-5L},{-6L}},{{-9L},{0L},{0x0BL}},{{-1L},{0xBEL},{-1L}},{{-1L},{-1L},{0x37L}},{{-9L},{7L},{0x60L}}},{{{0x37L},{-1L},{0L}},{{0L},{8L},{-2L}},{{-1L},{-1L},{0xD9L}},{{-1L},{0x69L},{7L}},{{-1L},{-1L},{8L}},{{8L},{-1L},{1L}},{{0x42L},{8L},{-1L}},{{0x73L},{0L},{-1L}}}};
+ int32_t ****l_2677[8];
+ int32_t *****l_2676[1][1];
+ uint64_t ****l_2686 = &g_1568[4][1];
+ uint16_t ***l_2785 = &g_642;
+ uint16_t *** const *l_2784 = &l_2785;
+ uint32_t ****l_2874 = &g_1926[0];
+ uint32_t *****l_2873[9][1] = {{(void*)0},{&l_2874},{(void*)0},{&l_2874},{(void*)0},{&l_2874},{(void*)0},{&l_2874},{(void*)0}};
+ int8_t *l_2888[5][6] = {{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0}};
+ union U0 **l_2893[8] = {&g_457,&g_457,&g_457,&g_457,&g_457,&g_457,&g_457,&g_457};
+ int64_t l_3030 = 6L;
+ uint32_t l_3043 = 1UL;
+ uint64_t l_3070[3];
+ int8_t l_3080 = 0x9DL;
+ int i, j, k;
+ for (i = 0; i < 8; i++)
+ l_2677[i] = &g_1175;
+ for (i = 0; i < 1; i++)
+ {
+ for (j = 0; j < 1; j++)
+ l_2676[i][j] = &l_2677[1];
+ }
+ for (i = 0; i < 3; i++)
+ l_3070[i] = 0xA9198D57D8E9CE12LL;
+ if ((safe_sub_func_int32_t_s_s(((p_37 <= (l_2659 >= (l_2659 , (l_2660 != ((*l_2662) = &g_648))))) == (p_37 | ((((l_2663[5][6][0] , (0UL ^ (safe_add_func_uint16_t_u_u(65527UL, l_2659)))) || 255UL) > 0xD69664490FDEA123LL) , (**g_642)))), p_36)))
+ { /* block id: 1212 */
+ uint32_t l_2678 = 0xD9A0AAF9L;
+ int32_t l_2679 = 0xD6B89FB5L;
+ int32_t l_2729 = 0xEED0CCDFL;
+ int32_t l_2765 = (-4L);
+ int32_t l_2768[6][4][2] = {{{0L,0x5E79F3B8L},{0x77FE2768L,8L},{0x78A14A41L,8L},{0x77FE2768L,0x5E79F3B8L}},{{0L,0x35D21069L},{0L,0x5E79F3B8L},{0x77FE2768L,8L},{0x78A14A41L,8L}},{{0x77FE2768L,0x5E79F3B8L},{0L,0x35D21069L},{0L,0x5E79F3B8L},{0x77FE2768L,8L}},{{0x78A14A41L,8L},{0x77FE2768L,0x5E79F3B8L},{0L,0x35D21069L},{0L,0x5E79F3B8L}},{{0x77FE2768L,8L},{0x78A14A41L,8L},{0x77FE2768L,0x5E79F3B8L},{0L,0x35D21069L}},{{0L,0x5E79F3B8L},{0x77FE2768L,8L},{0x78A14A41L,8L},{0x77FE2768L,0x5E79F3B8L}}};
+ uint64_t ****l_2800 = &g_1568[4][0];
+ int64_t *l_2804 = &g_253;
+ uint16_t l_2820[8] = {0x422DL,65530UL,65530UL,0x422DL,65530UL,65530UL,0x422DL,65530UL};
+ uint32_t l_2877 = 0x2C8835BCL;
+ int16_t l_2914 = 0x56BAL;
+ uint16_t *** const **l_2979 = &l_2784;
+ int64_t l_3041[4];
+ int16_t *l_3062 = &g_384;
+ int32_t *l_3075 = &g_2033[0];
+ int i, j, k;
+ for (i = 0; i < 4; i++)
+ l_3041[i] = 0xDC70C96AD5BD10D0LL;
+ for (g_209.f2 = 0; (g_209.f2 > 21); g_209.f2 = safe_add_func_int64_t_s_s(g_209.f2, 4))
+ { /* block id: 1215 */
+ const int32_t *l_2672 = (void*)0;
+ union U0 l_2673 = {4L};
+ int32_t l_2736 = 0L;
+ union U0 ** const l_2753[9][8][3] = {{{(void*)0,&g_457,&g_457},{&g_457,(void*)0,&g_457},{&g_457,&g_457,(void*)0},{&g_457,&g_457,&g_457},{(void*)0,(void*)0,&g_457},{&g_457,(void*)0,&g_457},{&g_457,(void*)0,(void*)0},{&g_457,&g_457,&g_457}},{{(void*)0,&g_457,&g_457},{&g_457,(void*)0,&g_457},{&g_457,&g_457,(void*)0},{&g_457,&g_457,&g_457},{(void*)0,(void*)0,&g_457},{&g_457,(void*)0,&g_457},{&g_457,(void*)0,(void*)0},{&g_457,&g_457,&g_457}},{{(void*)0,&g_457,&g_457},{&g_457,(void*)0,&g_457},{&g_457,&g_457,(void*)0},{&g_457,&g_457,&g_457},{(void*)0,(void*)0,&g_457},{&g_457,(void*)0,&g_457},{&g_457,(void*)0,(void*)0},{&g_457,&g_457,&g_457}},{{&g_457,&g_457,(void*)0},{&g_457,(void*)0,(void*)0},{&g_457,&g_457,&g_457},{&g_457,&g_457,(void*)0},{&g_457,&g_457,(void*)0},{&g_457,(void*)0,&g_457},{&g_457,&g_457,&g_457},{&g_457,&g_457,&g_457}},{{&g_457,&g_457,(void*)0},{&g_457,(void*)0,(void*)0},{&g_457,&g_457,&g_457},{&g_457,&g_457,(void*)0},{&g_457,&g_457,(void*)0},{&g_457,(void*)0,&g_457},{&g_457,&g_457,&g_457},{&g_457,&g_457,&g_457}},{{&g_457,&g_457,(void*)0},{&g_457,(void*)0,(void*)0},{&g_457,&g_457,&g_457},{&g_457,&g_457,(void*)0},{&g_457,&g_457,(void*)0},{&g_457,(void*)0,&g_457},{&g_457,&g_457,&g_457},{&g_457,&g_457,&g_457}},{{&g_457,&g_457,(void*)0},{&g_457,(void*)0,(void*)0},{&g_457,&g_457,&g_457},{&g_457,&g_457,(void*)0},{&g_457,&g_457,(void*)0},{&g_457,(void*)0,&g_457},{&g_457,&g_457,&g_457},{&g_457,&g_457,&g_457}},{{&g_457,&g_457,(void*)0},{&g_457,(void*)0,(void*)0},{&g_457,&g_457,&g_457},{&g_457,&g_457,(void*)0},{&g_457,&g_457,(void*)0},{&g_457,(void*)0,&g_457},{&g_457,&g_457,&g_457},{&g_457,&g_457,&g_457}},{{&g_457,&g_457,(void*)0},{&g_457,(void*)0,(void*)0},{&g_457,&g_457,&g_457},{&g_457,&g_457,(void*)0},{&g_457,&g_457,(void*)0},{&g_457,(void*)0,&g_457},{&g_457,&g_457,&g_457},{&g_457,&g_457,&g_457}}};
+ int16_t l_2816 = 9L;
+ int32_t ****l_2824[10][1] = {{&g_1175},{&g_1175},{&g_1175},{&g_1175},{&g_1175},{&g_1175},{&g_1175},{&g_1175},{&g_1175},{&g_1175}};
+ int i, j, k;
+ if ((safe_mul_func_uint8_t_u_u(0xE0L, l_2659)))
+ { /* block id: 1216 */
+ int32_t *****l_2674 = (void*)0;
+ int32_t l_2735 = 1L;
+ union U0 *l_2739[5][7] = {{&l_2673,&g_458,&l_2673,&g_458,&l_2673,&g_458,&l_2673},{&g_458,&g_458,&g_458,&g_458,&g_458,&g_458,&g_458},{(void*)0,&g_458,(void*)0,&g_458,(void*)0,&g_458,(void*)0},{&g_458,&g_458,&g_458,&g_458,&g_458,&g_458,&g_458},{&l_2673,&g_458,&l_2673,&g_458,&l_2673,&g_458,&l_2673}};
+ int32_t l_2763[5][10] = {{6L,0x397EDD9EL,0x5DA38F3AL,0x1FBBC128L,(-8L),1L,1L,0x4CB10F04L,1L,1L},{0x38C35325L,8L,0xA33152A2L,8L,0x38C35325L,0x1FBBC128L,1L,0xB1074C35L,0x02D6F10EL,0x264D6A40L},{0x1FBBC128L,1L,0xB1074C35L,0x02D6F10EL,0x264D6A40L,6L,0L,0L,6L,0x264D6A40L},{0xA33152A2L,0x02D6F10EL,0x02D6F10EL,0xA33152A2L,0x38C35325L,0x397EDD9EL,0x5DA38F3AL,0x1FBBC128L,(-8L),1L},{0x99EB6806L,0x38C35325L,0x4472C795L,6L,(-8L),0x5DA38F3AL,0x02D6F10EL,0x5DA38F3AL,(-8L),6L}};
+ int32_t *l_2773 = &l_2735;
+ union U0 l_2802[3] = {{0x44L},{0x44L},{0x44L}};
+ int64_t * const l_2803 = &g_128[0][3][1];
+ int i, j;
+ for (g_384 = 0; (g_384 >= (-27)); g_384 = safe_sub_func_int8_t_s_s(g_384, 9))
+ { /* block id: 1219 */
+ int32_t ******l_2675[7];
+ int16_t *l_2702 = &g_2193.f2;
+ int16_t ***l_2705 = (void*)0;
+ union U0 l_2712[6] = {{-1L},{-1L},{-1L},{-1L},{-1L},{-1L}};
+ int32_t *l_2727[10] = {&g_67[1],&g_67[1],&g_67[1],&g_67[1],&g_67[1],&g_67[1],&g_67[1],&g_67[1],&g_67[1],&g_67[1]};
+ int64_t ***l_2734 = (void*)0;
+ int i;
+ for (i = 0; i < 7; i++)
+ l_2675[i] = &l_2674;
+ l_2679 |= (l_2673 , (p_35 = ((&g_2620 != (l_2676[0][0] = l_2674)) , l_2678)));
+ for (g_2193.f0 = (-14); (g_2193.f0 > (-17)); g_2193.f0 = safe_sub_func_uint32_t_u_u(g_2193.f0, 3))
+ { /* block id: 1225 */
+ uint16_t l_2695 = 65529UL;
+ p_35 = (safe_mul_func_int8_t_s_s(p_36, ((p_36 && ((safe_lshift_func_int16_t_s_u((*g_1739), 11)) <= (!g_1585))) || (l_2686 == ((safe_rshift_func_int16_t_s_u(((1L & (0x875FC4C2A9E98904LL >= (*g_127))) && (safe_mul_func_int16_t_s_s((safe_rshift_func_uint8_t_u_s((((1L ^ 0x59L) != g_409[0][0]) & l_2679), 5)), p_35))), 10)) , &g_1568[4][1])))));
+ return l_2695;
+ }
+ if ((safe_rshift_func_int16_t_s_u(((*l_2702) = (safe_rshift_func_int8_t_s_s(p_35, (safe_sub_func_int64_t_s_s(p_35, 0xD0504981CA921F75LL))))), 8)))
+ { /* block id: 1230 */
+ uint64_t *****l_2723 = &l_2686;
+ uint64_t *****l_2725 = &l_2686;
+ uint64_t ******l_2724 = &l_2725;
+ const int32_t l_2726 = 0x5342A3C5L;
+ int32_t l_2728 = (-1L);
+ int8_t l_2730[2][2] = {{0xAAL,0xAAL},{0xAAL,0xAAL}};
+ int i, j;
+ l_2728 ^= (((safe_lshift_func_int8_t_s_s(1L, 2)) ^ ((l_2705 == (((((safe_div_func_int64_t_s_s((safe_add_func_uint16_t_u_u((~((**g_642) = 5UL)), ((-1L) | (p_37 && (255UL ^ (safe_div_func_uint16_t_u_u((l_2712[4] , (safe_rshift_func_int8_t_s_u((safe_lshift_func_int16_t_s_s((safe_lshift_func_int16_t_s_s((((safe_mod_func_uint32_t_u_u((safe_mul_func_uint16_t_u_u((l_2723 != ((*l_2724) = (void*)0)), (*g_1739))), p_37)) | p_35) == p_35), 7)), l_2726)), (*g_983)))), 0xB71CL))))))), (*g_127))) , (void*)0) != l_2727[5]) || 0x8EL) , (void*)0)) >= (*g_1739))) , (***g_1175));
+ if ((****g_2620))
+ break;
+ l_2730[1][1] = l_2729;
+ }
+ else
+ { /* block id: 1236 */
+ return p_37;
+ }
+ if ((safe_lshift_func_uint16_t_u_u(((((*l_2702) = 0L) != p_36) | p_37), 7)))
+ { /* block id: 1240 */
+ uint32_t l_2733 = 0x82ED76E6L;
+ l_2733 = (-1L);
+ }
+ else
+ { /* block id: 1242 */
+ l_2735 &= (l_2734 == l_2734);
+ }
+ }
+ l_2736 |= (**g_267);
+ if ((safe_add_func_uint8_t_u_u((l_2736 = ((void*)0 == l_2739[3][2])), p_35)))
+ { /* block id: 1248 */
+ uint16_t l_2740 = 1UL;
+ int32_t l_2761 = (-6L);
+ int32_t l_2762 = 0x8DFA1675L;
+ int32_t l_2766 = (-5L);
+ uint32_t l_2770[4] = {0UL,0UL,0UL,0UL};
+ int i;
+ ++l_2740;
+ for (l_2740 = 27; (l_2740 != 5); l_2740 = safe_sub_func_uint16_t_u_u(l_2740, 2))
+ { /* block id: 1252 */
+ int16_t l_2760[10];
+ int32_t l_2764 = 6L;
+ int32_t l_2769[3];
+ int i;
+ for (i = 0; i < 10; i++)
+ l_2760[i] = (-8L);
+ for (i = 0; i < 3; i++)
+ l_2769[i] = (-6L);
+ (**g_1175) = &l_2736;
+ --l_2770[2];
+ (*g_999) = (void*)0;
+ return l_2760[2];
+ }
+ }
+ else
+ { /* block id: 1261 */
+ uint32_t l_2796 = 9UL;
+ int32_t *l_2798[5] = {(void*)0,(void*)0,(void*)0,(void*)0,(void*)0};
+ int i;
+ if ((*g_268))
+ { /* block id: 1262 */
+ uint16_t *** const **l_2786 = &l_2784;
+ int32_t l_2795 = 0x7599A3ABL;
+ uint64_t ****l_2799 = &g_1568[4][0];
+ int16_t *l_2801 = &l_2673.f2;
+ if (p_37)
+ break;
+ l_2773 = ((*g_999) = (*g_999));
+ (*g_267) = func_99(p_36, ((*l_2801) = (p_37 > (safe_mul_func_uint16_t_u_u(((((safe_rshift_func_uint16_t_u_s((0xA7D8L | 0x13AAL), (((safe_sub_func_uint16_t_u_u((((p_36 < (((p_35 , (***g_2620)) != (void*)0) & p_37)) | p_35) > p_35), p_36)) , l_2799) != l_2800))) || p_35) < (**g_999)) , 0x0759L), p_37)))), l_2802[1], l_2803, l_2804);
+ (*g_999) = (*g_999);
+ }
+ else
+ { /* block id: 1271 */
+ int32_t *l_2805 = &g_4[3];
+ int32_t l_2819 = 0x77B6F82EL;
+ uint8_t *l_2821 = &g_183;
+ int16_t *l_2822 = &g_383;
+ int32_t ****l_2823 = &g_1175;
+ (*g_999) = &p_35;
+ (**g_999) |= (p_37 , 0xFCBABA69L);
+ (***g_1175) = (((*g_1739) >= ((&g_2630[1] == (void*)0) ^ (l_2820[0] & ((((p_37 && ((((*l_2822) = ((void*)0 == l_2821)) , ((l_2823 = &g_1175) == l_2824[5][0])) || (****l_2823))) >= (*g_1739)) ^ 1UL) == l_2678)))) >= 0xCDL);
+ return p_35;
+ }
+ for (g_2193.f0 = 4; (g_2193.f0 == (-22)); g_2193.f0 = safe_sub_func_int16_t_s_s(g_2193.f0, 1))
+ { /* block id: 1283 */
+ return p_37;
+ }
+ return p_37;
+ }
+ }
+ else
+ { /* block id: 1288 */
+ uint8_t l_2841 = 255UL;
+ int32_t l_2855 = 0x59A23047L;
+ for (g_2193.f0 = 0; (g_2193.f0 <= 2); g_2193.f0 += 1)
+ { /* block id: 1291 */
+ const int32_t *l_2842 = &g_135;
+ const uint64_t *l_2844 = (void*)0;
+ const uint64_t **l_2843 = &l_2844;
+ int32_t *l_2857 = &l_2736;
+ int i;
+ for (g_78 = 0; (g_78 <= 8); g_78 += 1)
+ { /* block id: 1294 */
+ uint16_t l_2827 = 7UL;
+ int32_t l_2830 = 0xE016D88CL;
+ l_2827++;
+ l_2830 &= (-1L);
+ }
+ if (((safe_rshift_func_uint16_t_u_s(l_2820[(g_2193.f0 + 1)], (safe_add_func_uint16_t_u_u((l_2663[7][2][0] , (*l_2842)), p_36)))) | 0xBE527B2BDF448059LL))
+ { /* block id: 1299 */
+ int8_t l_2856 = 0x29L;
+ (*g_999) = func_57((*g_999), ((l_2843 == (void*)0) , ((safe_mod_func_uint8_t_u_u((safe_add_func_int8_t_s_s(((((safe_div_func_uint8_t_u_u((safe_mod_func_uint32_t_u_u((l_2768[3][3][1] = ((safe_add_func_uint8_t_u_u(((void*)0 != &l_2800), (p_36 , (p_37 > ((((p_35 ^ 0xB492343EL) > l_2855) || p_36) | l_2856))))) == (****g_2620))), p_36)), g_2193.f1)) && 0xE3L) && (*l_2842)) < 0xE6DA936EL), (*g_983))), 0x29L)) , (void*)0)), (*g_999), (*l_2842), l_2857);
+ }
+ else
+ { /* block id: 1302 */
+ return l_2855;
+ }
+ }
+ p_35 = (**g_999);
+ }
+ for (g_1585 = 26; (g_1585 > 26); g_1585++)
+ { /* block id: 1310 */
+ l_2768[5][3][0] ^= 0x7E03A76CL;
+ }
+ }
+ if ((safe_sub_func_uint8_t_u_u((*g_983), (((safe_sub_func_uint16_t_u_u((safe_mod_func_int16_t_s_s(g_2866, ((((safe_rshift_func_uint8_t_u_u(0x04L, 0)) , (((safe_mul_func_int8_t_s_s((!(((safe_rshift_func_uint8_t_u_u(p_37, p_35)) || ((((l_2873[7][0] == &l_2874) , (p_36 > (p_35 > g_159))) || (****g_2620)) != p_36)) , 0x8FL)), p_37)) , 0xC51F7467L) <= p_35)) , p_36) & p_37))), (*g_643))) && p_36) == g_888))))
+ { /* block id: 1314 */
+ int32_t l_2875 = 0x072117A4L;
+ int16_t *l_2876 = &l_2663[5][6][0].f2;
+ int32_t l_2896 = 0x3B26EDE4L;
+ uint8_t l_2905 = 0xBBL;
+ int32_t l_2925 = 0xF4C5A4F9L;
+ uint64_t *l_2935 = &g_132;
+ uint64_t ****l_3012[7];
+ int32_t l_3036 = 0x9F84FF97L;
+ int32_t l_3037[3];
+ int i;
+ for (i = 0; i < 7; i++)
+ l_3012[i] = (void*)0;
+ for (i = 0; i < 3; i++)
+ l_3037[i] = 0x4970F08FL;
+ if ((((l_2877 = ((((*l_2876) = l_2875) & (((***g_276) = p_35) > 0x1D03E76480D707F5LL)) && (-7L))) | ((((safe_mul_func_uint8_t_u_u((safe_lshift_func_uint16_t_u_u(((((*l_2804) = (0x9B49AC22L < l_2820[0])) != 18446744073709551615UL) > ((((*g_983) = (safe_mul_func_uint16_t_u_u(65535UL, l_2875))) , 0x307F9F6FL) == 0x9122E523L)), 2)), 247UL)) > 0L) <= 0xD0L) ^ (-6L))) > p_36))
+ { /* block id: 1320 */
+ int8_t *l_2889 = &g_458.f1;
+ int32_t l_2892 = 8L;
+ int64_t *l_2899 = &g_91;
+ int16_t ***l_2923 = &g_2230;
+ int32_t l_2924 = 4L;
+ int32_t l_2936 = 1L;
+ int32_t l_2940 = 1L;
+ for (g_458.f2 = 0; (g_458.f2 <= 1); g_458.f2 += 1)
+ { /* block id: 1323 */
+ union U0 l_2897 = {0x8FL};
+ int64_t * const l_2898 = (void*)0;
+ int16_t l_2926 = 0xAAA4L;
+ int16_t *l_2937 = &g_2193.f2;
+ int16_t *l_2938[10][6] = {{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0}};
+ int32_t l_2939 = 0x635F255EL;
+ const int16_t ** const *l_2964[8][6][5] = {{{&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][6],(void*)0,&g_1738[0][0][1]},{&g_1738[0][0][1],&g_1738[2][0][0],&g_1738[2][0][5],&g_1738[0][0][0],&g_1738[0][0][1]},{&g_1738[0][0][1],&g_1738[0][0][2],(void*)0,&g_1738[2][0][6],&g_1738[0][0][1]},{&g_1738[1][0][2],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][0],&g_1738[0][0][1]},{&g_1738[0][0][1],&g_1738[0][0][1],(void*)0,(void*)0,&g_1738[0][0][2]},{&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][5],&g_1738[0][0][0],&g_1738[0][0][1]}},{{&g_1738[0][0][1],&g_1738[0][0][2],&g_1738[2][0][6],&g_1738[2][0][6],&g_1738[0][0][2]},{&g_1738[1][0][2],&g_1738[2][0][0],&g_1738[0][0][1],&g_1738[0][0][0],&g_1738[0][0][1]},{&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][6],(void*)0,&g_1738[0][0][1]},{&g_1738[0][0][1],&g_1738[2][0][0],&g_1738[2][0][5],&g_1738[0][0][0],&g_1738[0][0][1]},{&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][2],&g_1738[0][0][1],&g_1738[0][0][1]},{(void*)0,&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][3]}},{{&g_1738[1][0][4],&g_1738[1][0][2],&g_1738[2][0][2],&g_1738[0][0][2],&g_1738[0][0][1]},{&g_1738[0][0][5],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][0],&g_1738[0][0][1]},{&g_1738[1][0][4],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1]},{(void*)0,&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][0],&g_1738[0][0][3]},{&g_1738[0][0][1],&g_1738[1][0][2],&g_1738[0][0][1],&g_1738[0][0][2],&g_1738[0][0][1]},{&g_1738[0][0][5],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1]}},{{&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][2],&g_1738[0][0][1],&g_1738[0][0][1]},{(void*)0,&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][3]},{&g_1738[1][0][4],&g_1738[1][0][2],&g_1738[2][0][2],&g_1738[0][0][2],&g_1738[0][0][1]},{&g_1738[0][0][5],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][0],&g_1738[0][0][1]},{&g_1738[1][0][4],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1]},{(void*)0,&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][0],&g_1738[0][0][3]}},{{&g_1738[0][0][1],&g_1738[1][0][2],&g_1738[0][0][1],&g_1738[0][0][2],&g_1738[0][0][1]},{&g_1738[0][0][5],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1]},{&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][2],&g_1738[0][0][1],&g_1738[0][0][1]},{(void*)0,&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][3]},{&g_1738[1][0][4],&g_1738[1][0][2],&g_1738[2][0][2],&g_1738[0][0][2],&g_1738[0][0][1]},{&g_1738[0][0][5],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][0],&g_1738[0][0][1]}},{{&g_1738[1][0][4],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1]},{(void*)0,&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][0],&g_1738[0][0][3]},{&g_1738[0][0][1],&g_1738[1][0][2],&g_1738[0][0][1],&g_1738[0][0][2],&g_1738[0][0][1]},{&g_1738[0][0][5],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1]},{&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][2],&g_1738[0][0][1],&g_1738[0][0][1]},{(void*)0,&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][3]}},{{&g_1738[1][0][4],&g_1738[1][0][2],&g_1738[2][0][2],&g_1738[0][0][2],&g_1738[0][0][1]},{&g_1738[0][0][5],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][0],&g_1738[0][0][1]},{&g_1738[1][0][4],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1]},{(void*)0,&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][0],&g_1738[0][0][3]},{&g_1738[0][0][1],&g_1738[1][0][2],&g_1738[0][0][1],&g_1738[0][0][2],&g_1738[0][0][1]},{&g_1738[0][0][5],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1]}},{{&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][2],&g_1738[0][0][1],&g_1738[0][0][1]},{(void*)0,&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][3]},{&g_1738[1][0][4],&g_1738[1][0][2],&g_1738[2][0][2],&g_1738[0][0][2],&g_1738[0][0][1]},{&g_1738[0][0][5],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][0],&g_1738[0][0][1]},{&g_1738[1][0][4],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[0][0][1]},{(void*)0,&g_1738[0][0][1],&g_1738[0][0][1],&g_1738[2][0][0],&g_1738[0][0][3]}}};
+ int32_t ****l_2977 = (void*)0;
+ int i, j, k;
+ if ((safe_add_func_uint64_t_u_u(g_2033[(g_458.f2 + 2)], (g_67[g_458.f2] | g_2033[(g_458.f2 + 2)]))))
+ { /* block id: 1324 */
+ int16_t *l_2894[5][3];
+ int i, j;
+ for (i = 0; i < 5; i++)
+ {
+ for (j = 0; j < 3; j++)
+ l_2894[i][j] = (void*)0;
+ }
+ (*g_267) = func_99((l_2888[4][1] == l_2889), (l_2896 |= (p_36 ^ (((void*)0 == (*g_2621)) <= (g_2895 |= (((((l_2765 <= l_2892) , (void*)0) == l_2893[1]) <= l_2875) , p_36))))), l_2897, l_2898, l_2899);
+ l_2924 ^= (safe_sub_func_uint16_t_u_u((safe_add_func_int64_t_s_s((safe_unary_minus_func_uint32_t_u(p_35)), (((((l_2905 , (p_37 > (l_2892 , p_37))) , (safe_lshift_func_int8_t_s_u((p_37 = ((safe_div_func_uint32_t_u_u((safe_mul_func_int16_t_s_s((safe_sub_func_int16_t_s_s(((l_2765 ^= l_2914) | ((g_2797 > ((((safe_mod_func_uint64_t_u_u(l_2679, (safe_lshift_func_uint8_t_u_s((safe_div_func_int8_t_s_s((l_2923 != (void*)0), l_2892)), p_35)))) <= 0L) != (-6L)) != 18446744073709551615UL)) && p_37)), l_2897.f1)), 0UL)), p_37)) < p_37)), 2))) ^ (*g_2632)) ^ (**g_2622)) , p_36))), 0L));
+ l_2925 |= l_2896;
+ }
+ else
+ { /* block id: 1332 */
+ return p_35;
+ }
+ if ((l_2940 = ((l_2892 = (l_2926 = ((*g_1701) = p_36))) != (safe_mul_func_int16_t_s_s(((safe_rshift_func_int16_t_s_s(((g_384 ^= (safe_lshift_func_uint8_t_u_u((safe_add_func_int8_t_s_s(((p_37 , l_2935) == (void*)0), (l_2936 = (l_2924 = g_128[0][2][0])))), 7))) || (0x8B05L < (l_2939 &= p_35))), l_2940)) , (((++(*l_2935)) > p_37) , l_2877)), l_2925)))))
+ { /* block id: 1344 */
+ const int16_t l_2973 = (-1L);
+ l_2939 = (***g_1175);
+ l_2940 = l_2940;
+ l_2679 &= (safe_mul_func_int8_t_s_s((g_209.f3 &= ((safe_lshift_func_int8_t_s_s((!((safe_add_func_uint64_t_u_u(l_2936, ((*l_2935) = (((safe_mul_func_int16_t_s_s((((safe_lshift_func_int16_t_s_s((safe_add_func_int32_t_s_s((l_2875 , (safe_sub_func_int8_t_s_s(p_37, (safe_mod_func_uint8_t_u_u((l_2896 |= (!((safe_unary_minus_func_uint32_t_u((((safe_sub_func_int8_t_s_s((safe_sub_func_uint16_t_u_u((0UL && ((p_35 <= ((l_2964[2][0][4] = &g_1744) == &g_2230)) && ((safe_div_func_uint64_t_u_u(((safe_div_func_uint8_t_u_u(((((safe_div_func_int16_t_s_s((safe_mul_func_uint16_t_u_u(0xA02BL, (((((***g_276) = ((&l_2804 == (*g_276)) >= p_36)) >= 18446744073709551613UL) , p_37) >= l_2925))), p_35)) == p_36) | g_2307) > (**g_2622)), l_2905)) & 248UL), p_36)) || 0xE419L))), (**g_1574))), p_36)) <= (-6L)) > l_2973))) ^ 0xA2D2L))), p_35))))), (*g_1701))), p_36)) <= 0x9B4DL) , p_37), 0x744CL)) >= (-1L)) ^ (*g_1000))))) && 0x21C8L)), 2)) > 0xFECFL)), g_4[3]));
+ if (l_2729)
+ break;
+ }
+ else
+ { /* block id: 1354 */
+ int16_t l_2974 = 0xDE74L;
+ if (l_2974)
+ break;
+ (*g_267) = &p_35;
+ g_1679 |= 0xE00E2B68L;
+ l_2925 ^= (safe_mul_func_int8_t_s_s(1L, (((l_2977 == (g_2978 = (void*)0)) , l_2979) != g_2980)));
+ }
+ for (g_2797 = 0; (g_2797 <= 9); g_2797 += 1)
+ { /* block id: 1363 */
+ int32_t l_2982 = 0L;
+ return l_2982;
+ }
+ }
+ l_2924 ^= (g_4[3] = p_36);
+ }
+ else
+ { /* block id: 1369 */
+ uint32_t l_2989[2];
+ uint32_t **l_2997 = &g_1701;
+ uint16_t l_3029 = 0x6DA0L;
+ int32_t *l_3032[6] = {&g_4[3],&g_4[3],&g_4[3],&g_4[3],&g_4[3],&g_4[3]};
+ int i;
+ for (i = 0; i < 2; i++)
+ l_2989[i] = 7UL;
+ for (g_458.f3 = 0; (g_458.f3 == 7); g_458.f3 = safe_add_func_int8_t_s_s(g_458.f3, 1))
+ { /* block id: 1372 */
+ uint8_t *l_2994 = &l_2905;
+ const int32_t l_2998[9] = {0xD7B4CD8BL,0xD7B4CD8BL,0xD7B4CD8BL,0xD7B4CD8BL,0xD7B4CD8BL,0xD7B4CD8BL,0xD7B4CD8BL,0xD7B4CD8BL,0xD7B4CD8BL};
+ int32_t l_3005 = 0xAAEA9947L;
+ int i;
+ p_35 = 0x8484AAF9L;
+ p_35 = (safe_rshift_func_int8_t_s_s((p_35 , ((-3L) & (safe_lshift_func_uint16_t_u_u((((!(0xD881L != l_2875)) ^ (l_2925 = (((*g_983) = (l_2989[1] | ((*g_983) == 0x98L))) != (safe_mul_func_int8_t_s_s((((*l_2994) = (0x948A6B78L < ((safe_mod_func_uint8_t_u_u(((***g_276) && 1L), l_2989[1])) >= 0L))) , 0x51L), l_2989[1]))))) & 0x515EFCB8L), 15)))), g_135));
+ l_3005 |= (p_35 = (((safe_lshift_func_uint16_t_u_u(((void*)0 == l_2997), l_2998[6])) & ((&g_277[0] == (void*)0) , (safe_rshift_func_uint16_t_u_s((l_2820[0] == ((**l_2997) = (safe_mul_func_int16_t_s_s((safe_add_func_int16_t_s_s(p_36, (l_2875 , (((void*)0 == &g_1744) | l_2989[1])))), p_36)))), 14)))) != l_2729));
+ for (l_2765 = 0; (l_2765 != 28); l_2765 = safe_add_func_uint32_t_u_u(l_2765, 1))
+ { /* block id: 1383 */
+ return p_35;
+ }
+ }
+ l_2679 = (safe_mul_func_uint8_t_u_u(0x51L, (p_37 &= (l_2925 = 0L))));
+ if ((safe_rshift_func_int8_t_s_s((&g_1568[0][2] != l_3012[4]), 6)))
+ { /* block id: 1390 */
+ int32_t l_3034 = (-1L);
+ int32_t l_3038[6] = {(-3L),(-3L),(-3L),(-3L),(-3L),(-3L)};
+ int32_t l_3039[2];
+ int32_t l_3040 = 1L;
+ int32_t l_3042 = 0x14408B26L;
+ int i;
+ for (i = 0; i < 2; i++)
+ l_3039[i] = (-1L);
+ for (g_2193.f3 = 0; (g_2193.f3 >= (-11)); --g_2193.f3)
+ { /* block id: 1393 */
+ const uint8_t l_3028 = 0UL;
+ int32_t *l_3031 = &g_67[3];
+ int32_t l_3033 = 0xC6523790L;
+ int32_t l_3035[1][8][9];
+ int i, j, k;
+ for (i = 0; i < 1; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ for (k = 0; k < 9; k++)
+ l_3035[i][j][k] = 1L;
+ }
+ }
+ (*g_267) = ((safe_add_func_uint16_t_u_u(((safe_unary_minus_func_uint16_t_u((p_37 , (l_2925 != (((*l_3031) = (safe_sub_func_uint8_t_u_u(((safe_mod_func_int64_t_s_s(((*g_127) = (p_35 > ((((p_35 & (safe_mod_func_uint8_t_u_u(((l_2905 ^ ((((safe_mul_func_uint16_t_u_u(0x8184L, ((*l_2876) = (*g_1739)))) && 2L) && ((((safe_mod_func_int64_t_s_s((l_3028 < 0xC09FFC866F9194E5LL), 1UL)) , l_3029) != p_36) ^ p_37)) != p_37)) == g_458.f0), l_2875))) >= (-10L)) < l_3029) & l_3030))), p_36)) == p_36), p_36))) , (*g_1739)))))) < p_35), 0x0B16L)) , (void*)0);
+ (*g_267) = (l_3032[3] = ((***g_2978) = (void*)0));
+ l_2896 |= (l_3033 = (7L && p_37));
+ ++l_3043;
+ }
+ for (g_206 = 0; (g_206 <= 45); g_206 = safe_add_func_uint64_t_u_u(g_206, 6))
+ { /* block id: 1407 */
+ return p_35;
+ }
+ }
+ else
+ { /* block id: 1410 */
+ (*g_267) = &l_2679;
+ }
+ }
+ for (g_458.f3 = 0; (g_458.f3 != 1); g_458.f3 = safe_add_func_int64_t_s_s(g_458.f3, 2))
+ { /* block id: 1416 */
+ return p_36;
+ }
+ }
+ else
+ { /* block id: 1419 */
+ (**l_2800) = (**g_1567);
+ return p_36;
+ }
+ l_2765 = ((0x31F40544L >= (p_35 = ((safe_add_func_int16_t_s_s(((*l_3062) &= p_36), ((g_708 ^= ((((*l_3075) = (0x9F19L | ((l_2679 = ((safe_unary_minus_func_uint16_t_u(p_35)) , (safe_add_func_int64_t_s_s(((safe_mod_func_int32_t_s_s(l_2820[3], ((safe_div_func_uint32_t_u_u(p_35, p_35)) , (~(l_3070[1] & ((safe_rshift_func_int8_t_s_s(((safe_lshift_func_int8_t_s_u((-10L), p_37)) , (-1L)), p_35)) >= 65526UL)))))) == l_2765), p_35)))) | 0xCFL))) , l_2765) | p_37)) | 0UL))) , p_37))) , 1L);
+ }
+ else
+ { /* block id: 1429 */
+ int32_t l_3076 = 5L;
+ int32_t l_3077 = 0x01390D7CL;
+ int32_t l_3078 = 1L;
+ int32_t l_3079[10][1][4];
+ uint16_t l_3081 = 0xC356L;
+ uint32_t **l_3084[2];
+ union U0 *l_3085 = (void*)0;
+ int i, j, k;
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 1; j++)
+ {
+ for (k = 0; k < 4; k++)
+ l_3079[i][j][k] = 0x2CFC8E74L;
+ }
+ }
+ for (i = 0; i < 2; i++)
+ l_3084[i] = &g_1701;
+ l_3081--;
+ g_457 = (((void*)0 == l_3084[0]) , l_3085);
+ }
+ return p_36;
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_983 g_130 g_384 g_999 g_1000 g_2497 g_1700 g_1701 g_209.f0 g_648 g_258 g_1175 g_20 g_276 g_277 g_127 g_2620 g_2621 g_2622 g_2630 g_1739 g_458.f2 g_206 g_128 g_2648
+ * writes: g_384 g_130 g_1000 g_2497 g_254 g_209.f0 g_128 g_408 g_2630 g_2648
+ */
+static union U0 func_48(int32_t * p_49, int32_t p_50)
+{ /* block id: 1167 */
+ int32_t l_2545 = (-1L);
+ int32_t l_2546 = 0x87F12CDAL;
+ const int16_t **l_2547[4];
+ int16_t *l_2558[1];
+ int16_t **l_2559 = &l_2558[0];
+ const int16_t *l_2560 = &g_383;
+ int16_t *l_2561 = &g_384;
+ int32_t l_2571 = 9L;
+ uint32_t l_2588 = 18446744073709551615UL;
+ int32_t l_2634 = 0x6D47EBBBL;
+ int32_t l_2639 = 0xC7967847L;
+ int32_t l_2640 = 0L;
+ int32_t l_2641[7][10] = {{(-5L),(-1L),0xF1BE8DC3L,0x401C4A67L,0x401C4A67L,0xF1BE8DC3L,(-1L),(-5L),(-1L),0xF1BE8DC3L},{0xE0B57CFEL,(-10L),0x401C4A67L,(-10L),0xE0B57CFEL,0xF1BE8DC3L,0xF1BE8DC3L,0xE0B57CFEL,(-10L),0x401C4A67L},{(-5L),(-5L),0x401C4A67L,0xE0B57CFEL,0x010A09B7L,0xE0B57CFEL,0x401C4A67L,(-5L),(-5L),0x401C4A67L},{(-10L),0xE0B57CFEL,0xF1BE8DC3L,0xF1BE8DC3L,0xE0B57CFEL,(-10L),0x401C4A67L,(-10L),0xE0B57CFEL,0xF1BE8DC3L},{(-1L),(-5L),(-1L),0xF1BE8DC3L,0x401C4A67L,0x401C4A67L,0xF1BE8DC3L,(-1L),(-5L),(-1L)},{(-1L),(-10L),(-5L),0xE0B57CFEL,(-5L),(-10L),(-1L),(-1L),(-10L),(-5L)},{(-10L),(-1L),(-1L),(-10L),(-5L),0xE0B57CFEL,(-5L),(-10L),(-1L),(-1L)}};
+ int32_t l_2646 = 0xAB5CC4D6L;
+ union U0 l_2651[8] = {{0L},{0L},{0L},{0L},{0L},{0L},{0L},{0L}};
+ int i, j;
+ for (i = 0; i < 4; i++)
+ l_2547[i] = &g_1739;
+ for (i = 0; i < 1; i++)
+ l_2558[i] = &g_408;
+ if ((safe_div_func_int16_t_s_s((l_2545 != l_2545), (6L && (((p_50 | l_2546) > (((l_2547[1] == (void*)0) >= ((safe_lshift_func_uint8_t_u_u(p_50, 0)) ^ ((*l_2561) ^= (safe_add_func_uint16_t_u_u((safe_div_func_int8_t_s_s((safe_lshift_func_uint16_t_u_s((safe_add_func_int16_t_s_s((((*l_2559) = l_2558[0]) == l_2560), 0xD0D4L)), l_2545)), (*g_983))), l_2545))))) , l_2546)) , p_50)))))
+ { /* block id: 1170 */
+ const int32_t l_2566 = 0x8C4F6DEDL;
+ int8_t *l_2569 = &g_458.f3;
+ int64_t ***l_2570 = &g_277[0];
+ union U0 l_2574 = {0x6BL};
+ (*p_49) |= 8L;
+ (*p_49) &= (safe_mod_func_uint16_t_u_u(0x825FL, ((((safe_div_func_uint64_t_u_u(p_50, l_2566)) != ((*g_983)++)) <= (((1L ^ l_2546) ^ ((((l_2571 |= (((((((void*)0 != l_2569) , l_2570) != l_2570) & 0x08L) ^ p_50) | 1UL)) && l_2566) < 0UL) , p_50)) , l_2566)) & p_50)));
+ (*g_999) = (*g_999);
+ for (g_2497 = (-22); (g_2497 <= 51); g_2497 = safe_add_func_uint16_t_u_u(g_2497, 6))
+ { /* block id: 1178 */
+ return l_2574;
+ }
+ }
+ else
+ { /* block id: 1181 */
+ const int16_t *l_2579 = &g_383;
+ int16_t ****l_2580 = (void*)0;
+ int16_t ***l_2582[8] = {&l_2559,&g_2230,&g_2230,&l_2559,&g_2230,&g_2230,&l_2559,&g_2230};
+ int16_t ****l_2581 = &l_2582[4];
+ int32_t l_2587 = 0x3DDB5117L;
+ int32_t l_2589 = 0x0C8D3A4BL;
+ union U0 * const l_2613 = &g_2193;
+ int32_t * const ***l_2623 = &g_2621;
+ int32_t l_2637 = 0x562CC356L;
+ int32_t l_2638 = (-2L);
+ int32_t l_2642 = 0xE1F5DA34L;
+ int8_t l_2643 = 1L;
+ int32_t l_2644 = 0x6E195AD1L;
+ int32_t l_2645 = 0x43E382B8L;
+ int32_t l_2647[6][7] = {{(-10L),(-10L),0x9007E50DL,(-10L),0x21CE23DEL,0xE2A2E5C5L,(-10L)},{0x4CDA0905L,(-1L),0xAA8B12F5L,(-4L),0xAA8B12F5L,(-1L),0x4CDA0905L},{(-1L),(-10L),0x0750F30FL,0xAA8B12F5L,0x4CDA0905L,(-1L),0xAA8B12F5L},{(-10L),0x21CE23DEL,0xE2A2E5C5L,(-10L),(-10L),0xE2A2E5C5L,0x21CE23DEL},{(-10L),0x8742E80AL,0x0750F30FL,(-4L),0x8742E80AL,0xAA8B12F5L,0x21CE23DEL},{0L,(-10L),0xAA8B12F5L,0L,0x21CE23DEL,0L,0xAA8B12F5L}};
+ int i, j;
+ l_2589 &= (safe_add_func_int32_t_s_s((safe_add_func_int16_t_s_s((((~((**g_1700) = (((*l_2559) = (*l_2559)) == l_2579))) , (void*)0) == ((*l_2581) = (void*)0)), ((safe_mod_func_uint8_t_u_u((((((*l_2561) &= (safe_add_func_uint8_t_u_u(3UL, 250UL))) , ((void*)0 != &g_1744)) | (((p_50 && l_2571) < 5UL) , l_2587)) != l_2588), p_50)) && p_50))), l_2587));
+ for (g_384 = 0; (g_384 >= (-3)); g_384 = safe_sub_func_uint64_t_u_u(g_384, 6))
+ { /* block id: 1189 */
+ uint16_t l_2599[6];
+ int32_t * const *l_2605 = (void*)0;
+ int32_t * const **l_2604 = &l_2605;
+ union U0 *l_2612 = &g_209;
+ int32_t ****l_2625 = &g_1175;
+ int32_t *****l_2624 = &l_2625;
+ const uint16_t ****l_2633 = &g_2630[4];
+ int32_t *l_2635 = &l_2587;
+ int32_t *l_2636[2][1][9] = {{{&g_75[0],&g_75[0],(void*)0,&g_75[0],&g_75[0],(void*)0,&g_75[0],&g_75[0],(void*)0}},{{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0}}};
+ int i, j, k;
+ for (i = 0; i < 6; i++)
+ l_2599[i] = 0x61ADL;
+ for (g_209.f0 = 0; (g_209.f0 == (-9)); g_209.f0--)
+ { /* block id: 1192 */
+ int32_t l_2594 = 6L;
+ int32_t *l_2595 = &g_75[0];
+ int32_t *l_2596 = &l_2587;
+ int32_t *l_2597 = &l_2587;
+ int32_t *l_2598[6] = {(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0};
+ int i;
+ l_2599[3]--;
+ }
+ (*p_49) |= (((***g_276) = ((p_50 , ((*g_648) , (safe_rshift_func_uint16_t_u_s((0xE4L && (((*l_2604) = (*g_1175)) != (*g_1175))), (safe_mod_func_int64_t_s_s((safe_sub_func_int32_t_s_s((safe_mod_func_uint16_t_u_u((l_2612 == (l_2588 , l_2613)), p_50)), l_2545)), 0xBC30D72CE9D82791LL)))))) | (*g_1000))) == p_50);
+ (*p_49) = ((safe_add_func_int64_t_s_s((safe_div_func_uint16_t_u_u((((1UL <= (safe_sub_func_int32_t_s_s(((l_2623 = ((p_50 , 0UL) , g_2620)) != ((*l_2624) = (void*)0)), (*p_49)))) && (((**g_1700) = (l_2571 <= ((l_2634 = (safe_mod_func_int8_t_s_s(((((**l_2559) = (****l_2623)) <= (safe_lshift_func_uint8_t_u_s((((((*l_2633) = g_2630[0]) != &g_642) || (*g_1739)) == 0xE3F1882A87241F9BLL), g_458.f2))) || g_206), (****l_2623)))) == (*g_127)))) , p_50)) , p_50), l_2589)), 0L)) , 0x44DFB60CL);
+ ++g_2648;
+ }
+ }
+ return l_2651[4];
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_67 g_268 g_4 g_999 g_1000 g_133 g_159 g_1175 g_983 g_1701 g_147 g_1574 g_643 g_177 g_1738 g_1739 g_384 g_20 g_78 g_642 g_458.f2 g_1679
+ * writes: g_183 g_130 g_254 g_1744 g_458.f2 g_1567 g_177 g_1679 g_1000
+ */
+static int32_t * func_51(int8_t p_52, uint16_t p_53, uint16_t p_54, int32_t * p_55, int32_t * p_56)
+{ /* block id: 22 */
+ uint32_t l_66 = 0UL;
+ const uint32_t l_1737 = 0x5BD5EC1CL;
+ int16_t *l_1823 = &g_383;
+ int8_t l_1838 = 0L;
+ int32_t **** const l_1867 = &g_1175;
+ uint32_t ***l_1888 = (void*)0;
+ int64_t *l_1900[2][9] = {{&g_91,&g_91,(void*)0,&g_91,&g_91,(void*)0,&g_91,&g_91,(void*)0},{&g_91,&g_91,(void*)0,&g_91,&g_91,(void*)0,&g_91,&g_91,(void*)0}};
+ union U0 *l_1912 = &g_458;
+ int32_t l_1970 = 0L;
+ uint64_t l_2017 = 0x186654FB36088AB8LL;
+ const int64_t l_2109 = 1L;
+ uint64_t *** const *l_2119 = &g_1568[4][0];
+ int32_t l_2147 = 0xAFE66B6AL;
+ int32_t l_2148 = 0xB7803ABDL;
+ int32_t l_2149 = 0xD2562CEEL;
+ int16_t l_2150 = 0L;
+ int32_t l_2151[7] = {0x25F1C8C3L,0x25F1C8C3L,(-8L),0x25F1C8C3L,0x25F1C8C3L,(-8L),0x25F1C8C3L};
+ uint64_t l_2152 = 0x5E2B98CD90F720CALL;
+ uint32_t l_2172 = 0x68E686C5L;
+ union U0 l_2192 = {6L};
+ uint16_t ***l_2272 = &g_642;
+ int64_t l_2294 = 0xE3EA39F0464915B4LL;
+ int32_t l_2357 = 0x6F9A5C36L;
+ uint32_t l_2449[10] = {18446744073709551615UL,0xEC1892ABL,0xEC1892ABL,18446744073709551615UL,0xEC1892ABL,0xEC1892ABL,18446744073709551615UL,0xEC1892ABL,0xEC1892ABL,18446744073709551615UL};
+ const int64_t l_2470[5] = {0L,0L,0L,0L,0L};
+ int16_t l_2485 = 4L;
+ int i, j;
+ (**g_1175) = func_57(func_63(l_66, p_55), p_56, p_56, (safe_mod_func_int16_t_s_s((p_53 || (safe_mod_func_int64_t_s_s(((safe_rshift_func_uint8_t_u_s((safe_mod_func_uint16_t_u_u((l_66 , p_54), (l_1737 || 0xECL))), l_66)) | g_147), 0xEDC64461E26EA04ALL))), (**g_1574))), (*g_999));
+ return p_55;
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_1738 g_458.f2 g_1739 g_384 g_999 g_1000 g_20 g_147 g_78 g_983 g_642 g_643 g_1679 g_177 g_135 l_3230 l_8
+ * writes: g_1744 g_458.f2 g_130 g_1567 g_177 g_1679 l_8
+ */
+static int32_t * func_57(int32_t * p_58, const int32_t * p_59, int32_t * p_60, int32_t p_61, int32_t * p_62)
+{ /* block id: 777 */
+ const int16_t ***l_1740[6];
+ const int16_t **l_1742 = &g_1739;
+ const int16_t ***l_1741[8] = {&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742};
+ const int16_t ***l_1743[6][4][7] = {{{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,(void*)0},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742}},{{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,(void*)0},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742}},{{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,(void*)0,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742}},{{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742}},{{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,(void*)0,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742}},{{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742},{&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,&l_1742,(void*)0}}};
+ union U0 *l_1746 = &g_209;
+ int32_t l_1754 = 1L;
+ int32_t l_1768 = 0x095CDAFAL;
+ int32_t l_1769 = 0xDB75B53DL;
+ int32_t l_1770 = 4L;
+ int32_t l_1771 = 0x9C09D373L;
+ int32_t l_1772 = 0x10206477L;
+ int32_t l_1773[7] = {(-1L),(-1L),(-1L),(-1L),(-1L),(-1L),(-1L)};
+ uint8_t l_1774 = 0x9DL;
+ int16_t *l_1792[4] = {&g_408,&g_408,&g_408,&g_408};
+ const uint32_t **l_1798 = (void*)0;
+ const uint32_t ***l_1797 = &l_1798;
+ int32_t ***l_1799 = &g_999;
+ int i, j, k;
+ for (i = 0; i < 6; i++)
+ l_1740[i] = (void*)0;
+ g_1744 = g_1738[0][0][1];
+ for (g_458.f2 = 1; (g_458.f2 >= 0); g_458.f2 -= 1)
+ { /* block id: 781 */
+ int32_t ***l_1745 = &g_999;
+ union U0 *l_1747 = (void*)0;
+ int32_t l_1762 = 1L;
+ int32_t *l_1763 = &l_1754;
+ int32_t *l_1764 = (void*)0;
+ int32_t *l_1765 = &g_135;
+ int32_t *l_1766 = &l_1762;
+ int32_t *l_1767[2][8];
+ int i, j;
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 8; j++)
+ l_1767[i][j] = &g_135;
+ }
+ }
+ if (((((safe_mod_func_uint16_t_u_u((safe_mod_func_int64_t_s_s((safe_add_func_uint64_t_u_u(l_1769, (((l_1774 & (safe_sub_func_uint16_t_u_u(((((safe_mul_func_uint16_t_u_u((safe_div_func_uint32_t_u_u((((*g_1739) || (l_1772 |= l_1774)) < ((void*)0 != p_62)), p_61)), (safe_add_func_uint16_t_u_u(p_61, ((((safe_add_func_uint16_t_u_u(((p_61 , l_1797) == &l_1798), p_61)) , (void*)0) != l_1799) >= p_61))))) | p_61) , 0xEAL) || 0x64L), p_61))) , (***l_1799)) && (***l_1799)))), (***l_1799))), 0x29C2L)) >= 252UL) , (***l_1799)) || (***l_1799)))
+ { /* block id: 801 */
+ uint64_t ****l_1808 = &g_1568[1][0];
+ uint64_t *****l_1809 = &g_1567;
+ int32_t l_1810 = 0xF7553BC3L;
+ int32_t *l_1815 = &l_1754;
+ g_1679 ^= ((*l_1815) = (safe_lshift_func_uint16_t_u_u((((((safe_mod_func_int8_t_s_s(g_147, g_78)) == ((safe_div_func_int8_t_s_s((-1L), (safe_mul_func_int8_t_s_s(((((*g_983) = p_61) , l_1808) != ((*l_1809) = l_1808)), p_61)))) || l_1810)) , ((safe_rshift_func_int8_t_s_s((safe_add_func_uint16_t_u_u(((**g_642) = p_61), l_1810)), p_61)) | 1L)) != g_458.f2) , p_61), (***l_1799))));
+ }
+ else
+ { /* block id: 807 */
+ int64_t l_1816 = 5L;
+ l_1816 &= ((((***l_1799) <= ((*g_643) < (((-1L) != ((void*)0 == l_1792[2])) & p_61))) >= (p_61 > (***l_1799))) | p_61);
+ }
+ return (**l_1799);
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_67 g_183 g_268 g_4 g_999 g_1000 g_133 g_159 g_1175 g_983 g_1701 l_17 g_20 g_135 g_75 l_6 l_3388
+ * writes: g_183 g_130 g_254 l_17 g_135 g_75 l_6 l_3388
+ */
+static int32_t * func_63(uint32_t p_64, int32_t * p_65)
+{ /* block id: 23 */
+ int8_t l_92 = (-1L);
+ union U0 l_107 = {0xFCL};
+ int64_t *l_108 = &g_91;
+ int32_t l_1362 = (-2L);
+ int32_t l_1363 = 0x44B08332L;
+ int32_t l_1364 = 0xC342F325L;
+ int32_t l_1365 = 5L;
+ int32_t l_1366 = 1L;
+ int32_t l_1367 = 0L;
+ int32_t l_1368 = (-6L);
+ int32_t l_1369 = 0x025C5BA3L;
+ int32_t l_1370 = 0xD02642ECL;
+ int32_t l_1372 = 0L;
+ int32_t l_1373 = (-4L);
+ int32_t l_1374 = (-8L);
+ int32_t l_1375[9];
+ int8_t l_1376 = (-5L);
+ const int32_t *l_1416 = &l_1369;
+ uint64_t ****l_1428 = (void*)0;
+ const int32_t ***l_1507 = (void*)0;
+ uint8_t *l_1555[8] = {&g_206,&g_206,&g_206,&g_206,&g_206,&g_206,&g_206,&g_206};
+ uint64_t * const l_1584 = &g_1585;
+ uint64_t * const *l_1583 = &l_1584;
+ uint64_t * const **l_1582 = &l_1583;
+ uint64_t * const ***l_1581[1];
+ uint32_t l_1590 = 0xF2612A68L;
+ uint16_t l_1636 = 0x963DL;
+ union U0 **l_1671[3][5] = {{&g_457,&g_457,&g_457,&g_457,&g_457},{&g_457,&g_457,&g_457,&g_457,&g_457},{&g_457,&g_457,&g_457,&g_457,&g_457}};
+ union U0 ***l_1718 = &l_1671[2][3];
+ int32_t l_1721[9][10][2] = {{{1L,0xAE07A814L},{0L,(-5L)},{4L,0L},{0x8B11D955L,1L},{0x8B11D955L,0L},{4L,(-5L)},{0L,0xAE07A814L},{1L,(-2L)},{1L,(-5L)},{0xCA567AF2L,1L}},{{0x8B11D955L,0x74157914L},{0x2A0A03D6L,0L},{0xCA567AF2L,0x83600AB0L},{0L,(-2L)},{1L,(-2L)},{0L,0x83600AB0L},{0xCA567AF2L,0L},{0x2A0A03D6L,0x74157914L},{0x8B11D955L,1L},{0xCA567AF2L,(-5L)}},{{1L,(-2L)},{1L,0xAE07A814L},{0L,(-5L)},{4L,0L},{0x8B11D955L,1L},{0x8B11D955L,0L},{4L,(-5L)},{0L,0xAE07A814L},{1L,(-2L)},{1L,(-5L)}},{{0xCA567AF2L,1L},{0x8B11D955L,0x74157914L},{0x2A0A03D6L,0L},{0xCA567AF2L,0x83600AB0L},{0L,(-2L)},{1L,(-2L)},{0L,0x83600AB0L},{0xCA567AF2L,0L},{0x2A0A03D6L,0x74157914L},{0x8B11D955L,1L}},{{0xCA567AF2L,(-5L)},{1L,(-2L)},{1L,0xAE07A814L},{0L,(-5L)},{4L,0L},{0x8B11D955L,1L},{0x8B11D955L,0L},{4L,(-5L)},{0L,0xAE07A814L},{1L,(-2L)}},{{1L,(-5L)},{0xCA567AF2L,1L},{0x8B11D955L,0x74157914L},{0x2A0A03D6L,0L},{0xCA567AF2L,0x83600AB0L},{0L,(-2L)},{1L,(-2L)},{0L,0x83600AB0L},{0xCA567AF2L,0L},{0x2A0A03D6L,0x74157914L}},{{0x8B11D955L,1L},{0xCA567AF2L,(-5L)},{1L,(-2L)},{1L,0xAE07A814L},{0L,(-5L)},{4L,0L},{0x8B11D955L,1L},{0x8B11D955L,0L},{4L,(-5L)},{0L,0xAE07A814L}},{{1L,(-2L)},{1L,(-5L)},{0xCA567AF2L,1L},{0x8B11D955L,0x74157914L},{0x2A0A03D6L,1L},{0xD30CC12AL,0xEF7C4AB6L},{1L,1L},{(-8L),1L},{1L,0xEF7C4AB6L},{0xD30CC12AL,1L}},{{0x1648D157L,0L},{1L,0x45440744L},{0xD30CC12AL,0L},{0L,1L},{(-9L),0x4EBF4A0AL},{1L,0L},{(-3L),1L},{1L,1L},{1L,1L},{(-3L),0L}}};
+ union U0 **l_1728 = &g_457;
+ int i, j, k;
+ for (i = 0; i < 9; i++)
+ l_1375[i] = 0L;
+ for (i = 0; i < 1; i++)
+ l_1581[i] = &l_1582;
+ for (p_64 = 0; (p_64 <= 6); p_64 += 1)
+ { /* block id: 26 */
+ int32_t *l_74 = &g_75[2];
+ uint16_t *l_76 = (void*)0;
+ uint16_t *l_77[9][7] = {{(void*)0,&g_78,(void*)0,(void*)0,(void*)0,(void*)0,&g_78},{&g_78,&g_78,&g_78,&g_78,&g_78,&g_78,&g_78},{(void*)0,(void*)0,(void*)0,(void*)0,&g_78,(void*)0,(void*)0},{(void*)0,(void*)0,&g_78,&g_78,&g_78,(void*)0,(void*)0},{(void*)0,(void*)0,&g_78,(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,&g_78,(void*)0,&g_78,&g_78,(void*)0,&g_78},{(void*)0,&g_78,&g_78,&g_78,&g_78,(void*)0,&g_78},{(void*)0,&g_78,&g_78,(void*)0,&g_78,(void*)0,&g_78},{(void*)0,(void*)0,(void*)0,&g_78,(void*)0,(void*)0,(void*)0}};
+ int8_t l_79 = 6L;
+ int32_t l_80 = (-1L);
+ int32_t l_81 = (-7L);
+ int32_t l_82 = 0x52CE760CL;
+ int32_t l_83 = 0L;
+ int32_t l_84 = (-1L);
+ int32_t l_85[9];
+ int64_t *l_90[2];
+ uint32_t l_446 = 4294967293UL;
+ int32_t l_1371 = 7L;
+ uint32_t l_1380 = 4294967295UL;
+ const uint32_t l_1397[10][9][2] = {{{0x24B8C904L,0x1B2BEC57L},{0UL,4294967295UL},{0x485AA879L,0x47938DEEL},{4294967292UL,0x6EBB7F7CL},{3UL,0xF30D44D8L},{4294967295UL,0UL},{1UL,1UL},{0x6E6627B8L,0UL},{4294967286UL,4294967288UL}},{{0xF30D44D8L,0xCF5DB912L},{0x486E3104L,0x9792D2F9L},{0UL,0xD58A0B2DL},{0xCF5DB912L,4294967292UL},{4294967294UL,0x58CE859BL},{4294967295UL,0xA874F9BCL},{1UL,0xA874F9BCL},{4294967295UL,0x58CE859BL},{4294967294UL,4294967292UL}},{{0xCF5DB912L,0xD58A0B2DL},{0UL,0x9792D2F9L},{0x486E3104L,0xCF5DB912L},{0xF30D44D8L,4294967288UL},{4294967286UL,0UL},{0x6E6627B8L,1UL},{1UL,0UL},{4294967295UL,0xF30D44D8L},{3UL,0x6EBB7F7CL}},{{4294967292UL,0x47938DEEL},{0x485AA879L,4294967295UL},{0UL,0x1B2BEC57L},{0x24B8C904L,4294967286UL},{0xD58A0B2DL,4294967292UL},{0x01BACA47L,0x0EB5F177L},{0x02BDCA84L,0x73AB4C3EL},{0UL,0UL},{0x47938DEEL,1UL}},{{4294967295UL,4294967295UL},{4294967286UL,4294967293UL},{0x9792D2F9L,4294967295UL},{4294967290UL,4294967286UL},{0x99258856L,4294967290UL},{4294967295UL,4294967288UL},{4294967295UL,4294967290UL},{0x99258856L,4294967286UL},{4294967290UL,4294967295UL}},{{0x9792D2F9L,4294967293UL},{4294967286UL,4294967295UL},{4294967295UL,1UL},{0x47938DEEL,4294967294UL},{0x02BDCA84L,0xFE00AE09L},{0xED55B852L,0xF30D44D8L},{4294967295UL,4294967295UL},{4294967286UL,4294967286UL},{0x47938DEEL,4294967290UL}},{{1UL,1UL},{4294967286UL,4294967288UL},{4294967295UL,4294967288UL},{0xF1A18079L,0x9792D2F9L},{0x485AA879L,0xA874F9BCL},{0xD58A0B2DL,0UL},{1UL,1UL},{4294967295UL,0UL},{0x9792D2F9L,0x486E3104L}},{{0UL,3UL},{0xA874F9BCL,4294967286UL},{0x486E3104L,4294967295UL},{0x0EB5F177L,0x0E6844C1L},{4294967295UL,4294967295UL},{0UL,4294967295UL},{4294967295UL,0x0E6844C1L},{0x0EB5F177L,4294967295UL},{0x486E3104L,4294967286UL}},{{0xA874F9BCL,3UL},{0UL,0x486E3104L},{0x9792D2F9L,0UL},{4294967295UL,1UL},{1UL,0UL},{0xD58A0B2DL,0xA874F9BCL},{0x485AA879L,0x9792D2F9L},{0xF1A18079L,4294967288UL},{4294967295UL,4294967288UL}},{{4294967286UL,1UL},{1UL,4294967290UL},{0x47938DEEL,4294967286UL},{4294967286UL,4294967295UL},{4294967295UL,0xF30D44D8L},{0xED55B852L,0xFE00AE09L},{0x02BDCA84L,4294967294UL},{4294967288UL,0xD58A0B2DL},{0x35C33860L,0x35C33860L}}};
+ union U0 l_1457 = {-5L};
+ union U0 *l_1469 = &g_458;
+ uint16_t ***l_1483 = &g_642;
+ int32_t l_1484 = 0x6F092448L;
+ int32_t l_1485 = 0xA2A7E2F9L;
+ int16_t l_1614 = 0L;
+ int8_t l_1680[8] = {0L,0L,0L,0L,0L,0L,0L,0L};
+ uint32_t l_1699 = 4294967295UL;
+ int64_t l_1706[2];
+ int i, j, k;
+ for (i = 0; i < 9; i++)
+ l_85[i] = 7L;
+ for (i = 0; i < 2; i++)
+ l_90[i] = &g_91;
+ for (i = 0; i < 2; i++)
+ l_1706[i] = 0xC7929D515FFB46B7LL;
+ if (g_67[p_64])
+ break;
+ }
+ for (g_183 = 0; (g_183 >= 2); ++g_183)
+ { /* block id: 767 */
+ if ((*l_1416))
+ break;
+ if ((*g_268))
+ continue;
+ return (*g_999);
+ }
+ (*p_65) = ((safe_lshift_func_int8_t_s_u(g_133, 7)) && ((*g_1701) = (safe_rshift_func_uint8_t_u_s(((*g_983) = (safe_rshift_func_uint8_t_u_u(((+(((((safe_lshift_func_uint8_t_u_u((((*l_1718) = &g_457) == ((!(safe_mul_func_uint8_t_u_u(((l_1721[7][2][1] & (safe_mod_func_uint8_t_u_u(((*l_1416) > (safe_sub_func_int32_t_s_s((*p_65), (((&g_1700 != ((+(safe_mul_func_int16_t_s_s(g_159, (p_64 == (&p_65 == (*g_1175)))))) , &g_1700)) == (-1L)) > p_64)))), 0x79L))) && 5L), p_64))) , l_1728)), 5)) > p_64) | (-10L)) & (*l_1416)) <= (*l_1416))) , (*l_1416)), 3))), p_64))));
+ return (*g_999);
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_209.f0 g_128 g_258 g_159 g_457 g_458 g_4 g_253 g_267 g_458.f1 g_458.f3 g_643 g_177 g_78 g_642 g_91 g_268 g_67 g_383 g_127 g_983 g_130 g_1175 g_999 g_1000 g_146 g_135 g_75 g_274 g_20 g_409 g_183 g_277 g_629 g_578 g_204 g_133 g_1326 g_276 g_206 g_1086
+ * writes: g_209.f0 g_206 g_253 g_209.f2 g_268 g_458.f1 g_458.f3 g_75 g_708 g_146 g_91 g_578 g_130 g_135 g_1000 g_159 g_204 g_1326 g_1334 g_127 g_177
+ */
+static int32_t func_68(int32_t p_69, uint32_t p_70, int8_t p_71, int16_t p_72, int64_t p_73)
+{ /* block id: 208 */
+ int8_t *l_447 = (void*)0;
+ int8_t *l_448 = &g_209.f0;
+ union U0 l_449 = {0xE9L};
+ uint8_t *l_454 = &g_206;
+ int16_t *l_461 = &l_449.f2;
+ int32_t l_462[8][2] = {{9L,9L},{9L,9L},{9L,9L},{9L,9L},{9L,9L},{9L,9L},{9L,9L},{9L,9L}};
+ uint16_t l_472[9][9][3] = {{{0xC221L,0xC874L,65535UL},{65535UL,1UL,0xBF13L},{0x3BF1L,3UL,0xBD1BL},{0xDEE1L,65529UL,0xBD1BL},{7UL,0xBF03L,0xBF13L},{65535UL,0xE8C6L,65535UL},{1UL,65535UL,1UL},{65535UL,0x7567L,65529UL},{0xBD1BL,0x53ECL,65535UL}},{{0x8B2AL,65535UL,0xADA0L},{1UL,65535UL,0x75E0L},{0x8B2AL,7UL,65535UL},{0xBD1BL,0x5DA5L,0x9346L},{65535UL,0xC221L,0xC874L},{1UL,0x9346L,65527UL},{65535UL,0xDEE1L,0x53ECL},{7UL,0xBF13L,5UL},{0xDEE1L,0xBF13L,65535UL}},{{0x3BF1L,0xDEE1L,0xBF03L},{65535UL,0x9346L,0xFD83L},{0xC221L,0xC221L,0x3BF1L},{0xBF03L,0x5DA5L,0xC221L},{65535UL,7UL,0xE8C6L},{0xADA0L,65535UL,0x7567L},{0xC874L,65535UL,0xE8C6L},{65535UL,0x53ECL,0xC221L},{65535UL,0x7567L,0x3BF1L}},{{65527UL,65535UL,65535UL},{0x8B2AL,65535UL,0x505FL},{6UL,0x505FL,0x7567L},{7UL,0x7C61L,0x046CL},{7UL,1UL,0x8B2AL},{6UL,0xADA0L,0xC221L},{0x8B2AL,0x53ECL,0x53ECL},{65535UL,0xFD83L,8UL},{0xE8C6L,65535UL,65535UL}},{{65535UL,5UL,65529UL},{0x53ECL,65535UL,65535UL},{65535UL,5UL,0xBF03L},{0x5DA5L,65535UL,0x7C61L},{0x505FL,0xFD83L,65535UL},{0x3BF1L,0x53ECL,0xE8C6L},{0xBD1BL,0xADA0L,3UL},{65531UL,1UL,65535UL},{65527UL,0x7C61L,65535UL}},{{1UL,0x505FL,3UL},{0xFD83L,65535UL,0xE8C6L},{65535UL,0xBF03L,65535UL},{0x7567L,0x75E0L,0x7C61L},{65535UL,0x8B2AL,0xBF03L},{0xBF13L,0x5DA5L,65535UL},{0xADA0L,0x9346L,65529UL},{0xBF13L,1UL,65535UL},{65535UL,0x1FBEL,8UL}},{{0x7567L,0x3BF1L,0x53ECL},{65535UL,8UL,0xC221L},{0xFD83L,65527UL,0x8B2AL},{1UL,3UL,0x046CL},{65527UL,3UL,0x7567L},{65531UL,65527UL,0x505FL},{0xBD1BL,8UL,65535UL},{0x3BF1L,0x3BF1L,65531UL},{0x505FL,0x1FBEL,0x3BF1L}},{{0x5DA5L,1UL,65535UL},{65535UL,0x9346L,0x75E0L},{0x53ECL,0x5DA5L,65535UL},{65535UL,0x8B2AL,0x3BF1L},{0xE8C6L,0x75E0L,65531UL},{65535UL,0xBF03L,65535UL},{0x8B2AL,65535UL,0x505FL},{6UL,0x505FL,0x7567L},{7UL,0x7C61L,0x046CL}},{{7UL,1UL,0x8B2AL},{6UL,0xADA0L,0xC221L},{0x8B2AL,0x53ECL,0x53ECL},{65535UL,0xFD83L,8UL},{0xE8C6L,65535UL,65535UL},{65535UL,5UL,65529UL},{0x53ECL,65535UL,65535UL},{65535UL,5UL,0xBF03L},{0x5DA5L,65535UL,0x7C61L}}};
+ uint32_t *l_557 = &g_258[3];
+ const uint32_t *l_559[5][9] = {{&g_258[3],&g_258[3],&g_258[3],(void*)0,&g_147,&g_258[3],(void*)0,&g_258[6],&g_258[3]},{&g_258[3],&g_258[0],&g_258[3],&g_258[5],&g_258[0],&g_258[3],(void*)0,&g_258[3],&g_258[0]},{&g_258[3],&g_258[3],&g_258[3],&g_258[3],&g_258[6],&g_258[0],&g_258[3],&g_258[3],&g_258[3]},{&g_258[3],&g_258[6],&g_147,&g_147,&g_258[3],&g_258[3],&g_258[6],(void*)0,(void*)0},{&g_258[0],&g_258[3],(void*)0,&g_258[3],(void*)0,&g_258[3],&g_258[0],&g_258[0],&g_258[3]}};
+ uint64_t * const l_607 = &g_133;
+ uint8_t l_714 = 0x10L;
+ int16_t l_733 = 1L;
+ int32_t l_911[4];
+ int8_t l_947 = 8L;
+ int32_t l_1001 = 0x805C6618L;
+ uint64_t l_1046[1];
+ int16_t l_1059 = 7L;
+ int64_t * const *l_1083 = &g_127;
+ int64_t * const **l_1082 = &l_1083;
+ int64_t *l_1150 = &g_746;
+ union U0 **l_1163[2][6] = {{&g_457,&g_457,&g_457,&g_457,&g_457,&g_457},{&g_457,&g_457,&g_457,&g_457,&g_457,&g_457}};
+ union U0 l_1198 = {-2L};
+ int32_t ** const l_1203 = &g_1000;
+ uint32_t l_1235[9][5] = {{2UL,4294967290UL,0x2053E66BL,0xCE24B125L,0x2053E66BL},{0x466813F7L,0x466813F7L,1UL,0xCE24B125L,0x51EA397BL},{4294967290UL,2UL,0x96D42934L,4294967290UL,0x466813F7L},{4294967294UL,7UL,4294967289UL,0xFC0413B2L,7UL},{0x466813F7L,2UL,0xE2CADD70L,1UL,1UL},{0x96D42934L,0x466813F7L,0x96D42934L,4294967289UL,1UL},{0xCE24B125L,4294967290UL,7UL,4294967294UL,7UL},{2UL,4294967294UL,4294967295UL,0xCE24B125L,0x466813F7L},{0x2053E66BL,0x466813F7L,7UL,7UL,0x51EA397BL}};
+ int8_t l_1237 = 0xB2L;
+ uint32_t *l_1292 = (void*)0;
+ uint32_t * const *l_1291 = &l_1292;
+ uint32_t l_1324[6][2] = {{18446744073709551611UL,18446744073709551611UL},{18446744073709551611UL,18446744073709551611UL},{18446744073709551611UL,18446744073709551611UL},{18446744073709551611UL,18446744073709551611UL},{18446744073709551611UL,18446744073709551611UL},{18446744073709551611UL,18446744073709551611UL}};
+ int i, j, k;
+ for (i = 0; i < 4; i++)
+ l_911[i] = 1L;
+ for (i = 0; i < 1; i++)
+ l_1046[i] = 0x02E0C98E42D89AB0LL;
+ if (((((*l_448) ^= (-6L)) < ((!(((l_449 , ((((p_71 = (safe_rshift_func_uint8_t_u_s(((*l_454) = (safe_add_func_uint16_t_u_u(g_128[0][3][2], g_258[4]))), (((g_159 , l_449) , (safe_mod_func_uint16_t_u_u((g_457 == &g_458), ((*l_461) = (safe_lshift_func_int16_t_s_u((!(((l_449.f3 <= 0x2FL) , (*g_457)) , 1L)), 1)))))) && (-1L))))) || l_449.f3) < 6UL) > 1L)) & g_4[3]) | l_462[0][0])) != l_462[0][0])) <= (-8L)))
+ { /* block id: 213 */
+ uint16_t l_486 = 7UL;
+ uint64_t l_503 = 0xC3FC38227B8D68D9LL;
+ int32_t l_526[9] = {1L,0x3C3F3ACAL,0x3C3F3ACAL,1L,0x3C3F3ACAL,0x3C3F3ACAL,1L,0x3C3F3ACAL,0x3C3F3ACAL};
+ int i;
+ for (g_253 = 1; (g_253 >= 0); g_253 -= 1)
+ { /* block id: 216 */
+ int32_t *l_463 = (void*)0;
+ int32_t *l_464 = (void*)0;
+ int32_t *l_465 = &g_75[0];
+ int32_t *l_466 = &l_462[0][0];
+ int32_t *l_467 = &g_75[2];
+ int32_t *l_468 = &g_135;
+ int32_t *l_469 = (void*)0;
+ int32_t *l_470[10][3] = {{&l_462[0][0],&l_462[0][0],&l_462[0][0]},{&g_75[0],&l_462[2][0],(void*)0},{(void*)0,&g_75[2],&l_462[2][0]},{(void*)0,&g_4[3],&l_462[0][0]},{&g_75[0],&g_20,&g_75[0]},{&l_462[0][0],&g_4[3],(void*)0},{&l_462[2][0],&g_75[2],(void*)0},{(void*)0,&l_462[2][0],&g_75[0]},{&l_462[0][0],&l_462[0][0],&l_462[0][0]},{(void*)0,&l_462[0][0],&l_462[2][0]}};
+ int16_t l_530 = (-7L);
+ int32_t l_535 = (-5L);
+ int i, j;
+ l_472[4][3][2]--;
+ for (g_209.f2 = 0; (g_209.f2 <= 1); g_209.f2 += 1)
+ { /* block id: 220 */
+ uint32_t *l_477 = &g_258[3];
+ int64_t l_480[1][10][6] = {{{(-6L),(-2L),(-6L),0x3F7C68C20FEF92FCLL,(-6L),(-2L)},{(-1L),(-6L),(-6L),(-4L),0x539AEC78E0FAAD68LL,0x3F7C68C20FEF92FCLL},{0x61375C96C76C8D7DLL,(-4L),(-2L),(-2L),(-4L),0x61375C96C76C8D7DLL},{(-2L),(-4L),0x61375C96C76C8D7DLL,0x0DB3BFBB48C1FAC4LL,0x539AEC78E0FAAD68LL,(-6L)},{(-6L),(-6L),(-1L),(-6L),(-6L),(-4L)},{(-6L),(-2L),(-6L),0x0DB3BFBB48C1FAC4LL,1L,1L},{(-2L),0x539AEC78E0FAAD68LL,0x539AEC78E0FAAD68LL,(-2L),(-1L),1L},{0x61375C96C76C8D7DLL,1L,(-6L),(-4L),0x0DB3BFBB48C1FAC4LL,(-4L)},{(-1L),(-4L),(-1L),0x3F7C68C20FEF92FCLL,0x0DB3BFBB48C1FAC4LL,(-6L)},{(-6L),1L,0x61375C96C76C8D7DLL,(-1L),(-1L),0x61375C96C76C8D7DLL}}};
+ int32_t l_484 = 0x84166A81L;
+ int32_t *l_504[7] = {&g_75[2],&g_20,&g_20,&g_75[2],&g_20,&g_20,&g_75[2]};
+ uint8_t *l_511 = (void*)0;
+ int32_t l_519 = 0x56952E57L;
+ int8_t l_524 = 0x02L;
+ int i, j, k;
+ (*g_267) = (void*)0;
+ }
+ }
+ }
+ else
+ { /* block id: 252 */
+ int32_t l_545[4] = {0xA15CE5BAL,0xA15CE5BAL,0xA15CE5BAL,0xA15CE5BAL};
+ union U0 l_606 = {0xEDL};
+ int32_t *l_653 = &g_146;
+ int64_t l_713 = 8L;
+ int32_t **l_722 = &l_653;
+ int32_t ***l_721 = &l_722;
+ int i;
+ for (g_458.f1 = 20; (g_458.f1 == (-7)); g_458.f1 = safe_sub_func_int16_t_s_s(g_458.f1, 2))
+ { /* block id: 255 */
+ int32_t l_615[1];
+ uint8_t l_620 = 0UL;
+ uint32_t **l_649 = &l_557;
+ int32_t *l_707 = &g_75[2];
+ int32_t *l_709 = &g_146;
+ int32_t *l_710 = &l_545[0];
+ int32_t *l_711 = &l_545[1];
+ int32_t *l_712[6][1][3] = {{{&l_615[0],&g_135,&g_135}},{{&g_135,&l_462[0][0],(void*)0}},{{&l_615[0],&l_462[0][0],&l_615[0]}},{{&l_615[0],&g_135,(void*)0}},{{&l_615[0],&l_615[0],&g_135}},{{&l_615[0],&g_135,&g_135}}};
+ int64_t l_726 = (-4L);
+ int64_t l_789 = 0xDB7474E2223FA5BCLL;
+ int i, j, k;
+ for (i = 0; i < 1; i++)
+ l_615[i] = (-4L);
+ }
+ }
+ for (g_458.f3 = 0; (g_458.f3 != 12); g_458.f3 = safe_add_func_int64_t_s_s(g_458.f3, 1))
+ { /* block id: 371 */
+ int32_t *l_827 = &g_75[2];
+ union U0 l_834 = {0x56L};
+ int8_t *l_839 = &g_708;
+ uint32_t l_840 = 9UL;
+ uint16_t **l_892[9] = {&g_643,&g_643,&g_643,&g_643,&g_643,&g_643,&g_643,&g_643,&g_643};
+ int64_t **l_902 = &g_127;
+ int16_t l_903 = 0x0ED8L;
+ uint16_t l_904 = 0x826EL;
+ int32_t l_906 = 0L;
+ int32_t l_907 = (-2L);
+ uint32_t l_912 = 3UL;
+ int32_t l_917 = (-5L);
+ int32_t l_925 = 0xC1557A2EL;
+ int32_t l_926[1][4][9] = {{{0xD18E9BE1L,0xD18E9BE1L,0x900B22F3L,0x7F48F33DL,0x693ED394L,(-2L),0xD18E9BE1L,0x693ED394L,0x8757C95BL},{0xF7B5BB4CL,1L,2L,0x693ED394L,0x693ED394L,2L,1L,0xF7B5BB4CL,0x900B22F3L},{0xF7B5BB4CL,0x693ED394L,0x900B22F3L,0xF7B5BB4CL,1L,2L,0x693ED394L,0x693ED394L,2L},{0xD18E9BE1L,0x693ED394L,0x8757C95BL,0x693ED394L,0xD18E9BE1L,(-2L),0x693ED394L,0x7F48F33DL,0x900B22F3L}}};
+ int64_t l_930 = 9L;
+ uint32_t l_935 = 1UL;
+ union U0 **l_971 = &g_457;
+ int i, j, k;
+ g_146 = (p_73 , (((safe_add_func_int64_t_s_s((safe_rshift_func_uint8_t_u_s(((safe_rshift_func_uint16_t_u_u(((safe_mod_func_uint32_t_u_u(1UL, ((*l_827) = l_449.f2))) || ((((*l_839) = ((safe_rshift_func_int8_t_s_u((!((*l_448) = ((((safe_mul_func_uint8_t_u_u(((safe_div_func_int8_t_s_s((l_834 , (safe_add_func_uint32_t_u_u((safe_sub_func_uint16_t_u_u((l_462[1][0] | l_462[4][1]), 0xE028L)), (-1L)))), (p_73 && p_71))) <= (*g_643)), g_78)) != p_72) && (**g_642)) && 255UL))), l_714)) >= 0xCFL)) || g_128[0][3][1]) != p_69)), 12)) >= p_71), 2)), p_73)) < l_840) , p_69));
+ for (g_91 = 0; (g_91 <= (-13)); g_91 = safe_sub_func_uint32_t_u_u(g_91, 8))
+ { /* block id: 378 */
+ uint64_t **l_859 = &g_333[6][0];
+ uint64_t ***l_858[5] = {&l_859,&l_859,&l_859,&l_859,&l_859};
+ int32_t l_875 = 2L;
+ int32_t l_886 = (-1L);
+ int32_t l_908 = 1L;
+ int32_t l_909 = 0xA85A818CL;
+ int32_t l_910 = 0x9B9DDF32L;
+ int32_t *l_923 = &l_909;
+ int8_t l_927 = (-1L);
+ int32_t l_929[5] = {0x2105F6E1L,0x2105F6E1L,0x2105F6E1L,0x2105F6E1L,0x2105F6E1L};
+ int64_t *l_948 = &g_128[0][3][1];
+ union U0 **l_974 = &g_457;
+ uint32_t l_1073 = 8UL;
+ uint32_t l_1095 = 8UL;
+ uint64_t l_1103 = 18446744073709551615UL;
+ int i;
+ }
+ }
+ for (g_91 = 0; (g_91 <= 2); g_91 += 1)
+ { /* block id: 489 */
+ union U0 l_1106[2][1] = {{{0xE5L}},{{0xE5L}}};
+ int64_t * const l_1107[1] = {(void*)0};
+ int32_t *l_1110[4][9][2] = {{{&g_135,&g_4[3]},{&g_135,&g_135},{&g_4[3],&g_135},{&g_135,&g_4[3]},{&g_135,&g_135},{&g_4[3],&g_135},{&g_135,&g_4[3]},{&g_135,&g_135},{&g_4[3],&g_135}},{{&g_135,&g_4[3]},{&g_135,&g_135},{&g_4[3],&g_135},{&g_135,&g_4[3]},{&g_135,&g_135},{&g_4[3],&g_135},{&g_135,&g_4[3]},{&g_135,&g_135},{&g_4[3],&g_135}},{{&g_135,&g_4[3]},{&g_135,&g_135},{&g_4[3],&g_135},{&g_135,&g_4[3]},{&g_135,&g_135},{&g_4[3],&g_135},{&g_135,&g_4[3]},{&g_135,&g_135},{&g_4[3],&g_135}},{{&g_135,&g_4[3]},{&g_135,&g_135},{&g_4[3],&g_135},{&g_135,&g_4[3]},{&g_135,&g_135},{&g_4[3],&g_135},{&g_135,&g_4[3]},{&g_135,&g_135},{&g_4[3],&g_135}}};
+ uint64_t **l_1119[6][3][8] = {{{&g_333[0][0],(void*)0,&g_333[1][1],&g_333[2][0],(void*)0,&g_333[5][0],&g_333[3][1],&g_333[2][1]},{&g_333[1][1],&g_333[3][0],&g_333[1][1],&g_333[7][1],&g_333[7][1],&g_333[7][1],&g_333[7][1],&g_333[7][1]},{(void*)0,&g_333[0][0],&g_333[7][1],&g_333[7][1],&g_333[4][0],(void*)0,&g_333[7][1],&g_333[4][0]}},{{&g_333[7][1],&g_333[7][1],&g_333[5][0],(void*)0,&g_333[3][1],(void*)0,&g_333[3][0],&g_333[3][1]},{(void*)0,&g_333[7][1],(void*)0,(void*)0,&g_333[7][1],&g_333[7][1],(void*)0,&g_333[7][1]},{&g_333[4][0],&g_333[5][0],&g_333[7][1],(void*)0,(void*)0,(void*)0,(void*)0,&g_333[7][1]}},{{&g_333[7][1],&g_333[7][1],&g_333[3][0],&g_333[5][0],&g_333[3][1],&g_333[7][1],(void*)0,&g_333[1][1]},{&g_333[5][0],&g_333[0][0],&g_333[7][1],&g_333[4][0],&g_333[7][1],&g_333[7][1],(void*)0,&g_333[1][1]},{&g_333[0][0],&g_333[7][1],&g_333[3][0],&g_333[5][0],&g_333[7][1],&g_333[7][1],&g_333[7][1],&g_333[7][1]}},{{&g_333[7][1],&g_333[7][1],&g_333[7][1],(void*)0,&g_333[2][0],&g_333[0][0],&g_333[3][0],(void*)0},{&g_333[7][1],&g_333[7][1],&g_333[4][0],&g_333[5][0],&g_333[3][0],(void*)0,&g_333[7][1],&g_333[3][0]},{&g_333[1][1],&g_333[2][1],(void*)0,(void*)0,&g_333[3][0],&g_333[5][0],(void*)0,&g_333[4][1]}},{{&g_333[7][1],&g_333[7][1],&g_333[7][1],(void*)0,&g_333[7][1],&g_333[7][1],&g_333[7][1],&g_333[7][1]},{&g_333[7][1],&g_333[7][1],&g_333[5][0],&g_333[1][0],(void*)0,&g_333[7][1],&g_333[4][1],&g_333[7][1]},{&g_333[7][1],(void*)0,&g_333[7][1],&g_333[0][0],(void*)0,&g_333[7][1],(void*)0,(void*)0}},{{&g_333[7][1],&g_333[1][1],&g_333[5][1],&g_333[7][1],&g_333[7][1],(void*)0,&g_333[7][1],&g_333[4][0]},{&g_333[7][1],&g_333[7][1],&g_333[7][1],(void*)0,&g_333[3][0],(void*)0,&g_333[7][1],(void*)0},{&g_333[1][1],&g_333[7][1],&g_333[7][1],(void*)0,&g_333[3][0],&g_333[7][1],&g_333[1][1],&g_333[7][1]}}};
+ uint64_t ***l_1118 = &l_1119[1][0][4];
+ int32_t l_1125 = (-7L);
+ uint16_t ***l_1129 = &g_642;
+ int16_t l_1159 = 0x354CL;
+ int64_t l_1215 = 6L;
+ uint64_t l_1239[5];
+ const uint16_t l_1271 = 65533UL;
+ int16_t l_1272 = 0x065AL;
+ int64_t *l_1331 = &g_778;
+ int i, j, k;
+ for (i = 0; i < 5; i++)
+ l_1239[i] = 0xE1DC6819E6A1D5B8LL;
+ for (g_578 = 0; (g_578 <= 0); g_578 += 1)
+ { /* block id: 492 */
+ int i;
+ for (l_449.f3 = 0; (l_449.f3 <= 0); l_449.f3 += 1)
+ { /* block id: 495 */
+ (*g_267) = (*g_267);
+ }
+ return g_67[(g_91 + 3)];
+ }
+ (*g_267) = func_99((0xD0B072D2L || l_1046[0]), g_383, l_1106[1][0], l_1107[0], &p_73);
+ p_69 = (safe_rshift_func_int8_t_s_u(l_1106[1][0].f3, 2));
+ for (g_130 = 0; (g_130 <= 0); g_130 += 1)
+ { /* block id: 504 */
+ uint64_t l_1111[6][3] = {{0xB02A9711D519CD71LL,0UL,0UL},{0xB02A9711D519CD71LL,0UL,0UL},{0xB02A9711D519CD71LL,0UL,0UL},{0xB02A9711D519CD71LL,0UL,0UL},{0xB02A9711D519CD71LL,0UL,0UL},{0xB02A9711D519CD71LL,0UL,0UL}};
+ int32_t l_1124 = 0x5544602EL;
+ int32_t l_1126 = 0x0C53A3EEL;
+ const union U0 l_1137 = {1L};
+ int64_t ***l_1226 = &g_277[0];
+ uint32_t l_1325 = 0xB38004C2L;
+ int i, j;
+ ++l_1111[1][0];
+ for (g_135 = 0; (g_135 <= 1); g_135 += 1)
+ { /* block id: 508 */
+ uint32_t l_1122 = 18446744073709551615UL;
+ int32_t l_1123 = 1L;
+ uint16_t ***l_1131[10] = {&g_642,&g_642,&g_642,&g_642,&g_642,&g_642,&g_642,&g_642,&g_642,&g_642};
+ uint16_t ** const *l_1132[2][3] = {{(void*)0,(void*)0,(void*)0},{&g_642,&g_642,&g_642}};
+ uint32_t l_1154 = 0x0F03542AL;
+ int32_t l_1158 = 0x24F7942FL;
+ int64_t ***l_1170[1][1][7];
+ union U0 l_1204 = {0x3DL};
+ const uint16_t l_1227 = 65535UL;
+ int i, j, k;
+ for (i = 0; i < 1; i++)
+ {
+ for (j = 0; j < 1; j++)
+ {
+ for (k = 0; k < 7; k++)
+ l_1170[i][j][k] = (void*)0;
+ }
+ }
+ l_1126 ^= (p_70 == ((l_1125 ^= (((safe_mul_func_int8_t_s_s(((p_69 , 6L) & (l_1124 = ((safe_sub_func_int8_t_s_s((l_1118 != (void*)0), ((safe_add_func_uint8_t_u_u((6L != (((l_1122 &= (p_73 &= (*g_127))) | 18446744073709551615UL) ^ g_209.f0)), 9UL)) == l_1123))) | 1UL))), (*g_983))) , l_1124) | p_70)) < (*g_268)));
+ }
+ if (p_73)
+ { /* block id: 588 */
+ int32_t * const l_1274 = &g_75[2];
+ int32_t **l_1275 = &g_1000;
+ (*l_1275) = l_1274;
+ (**g_1175) = l_1110[0][1][1];
+ for (g_159 = 0; (g_159 <= 0); g_159 += 1)
+ { /* block id: 593 */
+ uint8_t l_1276[6][9] = {{0xECL,5UL,0xECL,5UL,0xECL,5UL,0xECL,5UL,0xECL},{250UL,0xC6L,0xC6L,250UL,250UL,0xC6L,0xC6L,250UL,250UL},{0UL,5UL,0UL,5UL,0UL,5UL,0UL,5UL,0UL},{250UL,250UL,0xC6L,0xC6L,250UL,250UL,0xC6L,0xC6L,250UL},{0xECL,5UL,0xECL,5UL,0xECL,5UL,0xECL,5UL,0xECL},{250UL,0xC6L,0xC6L,250UL,250UL,0xC6L,0xC6L,250UL,250UL}};
+ int i, j;
+ if ((*g_1000))
+ break;
+ (*l_1274) ^= (p_69 = ((**l_1275) && p_72));
+ (*g_267) = func_99(((1UL > 65535UL) , l_1276[5][6]), g_274, l_1137, (*l_1083), (p_69 , &p_73));
+ }
+ }
+ else
+ { /* block id: 599 */
+ uint32_t *l_1283 = &g_204;
+ int32_t l_1284 = 9L;
+ (*g_267) = func_99(((safe_lshift_func_int8_t_s_s((g_458.f1 = (**l_1203)), 1)) || g_159), (((safe_sub_func_int64_t_s_s((safe_div_func_uint32_t_u_u(((*l_1283) = l_1137.f1), g_177)), (((((*l_448) = l_1284) , ((((safe_div_func_uint32_t_u_u((p_71 && 0xB48FL), (safe_lshift_func_int16_t_s_u(((*l_461) = (((((+((safe_div_func_uint16_t_u_u((((g_409[0][1] , l_1126) < 1UL) , 0x1B93L), p_72)) , (-1L))) ^ l_1126) , (void*)0) != (void*)0) == 0x15F9L)), 13)))) && l_1137.f0) != p_71) != l_1111[1][0])) , p_69) == g_183))) || (**g_642)) & p_72), l_1137, &l_1215, (**l_1226));
+ }
+ for (g_159 = 0; (g_159 <= 2); g_159 += 1)
+ { /* block id: 608 */
+ int32_t l_1322 = 1L;
+ int32_t l_1327 = (-7L);
+ if (((*g_457) , p_73))
+ { /* block id: 609 */
+ uint32_t * const **l_1293 = &l_1291;
+ int32_t l_1318 = 0x0E5EFF82L;
+ uint16_t l_1328 = 0xE7BCL;
+ (*l_1293) = l_1291;
+ for (l_1198.f3 = 0; (l_1198.f3 <= 0); l_1198.f3 += 1)
+ { /* block id: 613 */
+ uint32_t **l_1321 = &l_557;
+ int32_t l_1323 = 9L;
+ int i;
+ g_1326 &= (safe_mod_func_uint32_t_u_u((safe_lshift_func_uint8_t_u_s(((safe_mul_func_uint8_t_u_u((safe_mul_func_int16_t_s_s(((*l_461) = (((safe_mod_func_int64_t_s_s((safe_add_func_int16_t_s_s(0x728EL, (((**l_1203) >= ((safe_lshift_func_int16_t_s_s(g_629, 12)) , (safe_mod_func_int16_t_s_s((p_72 <= (safe_sub_func_int8_t_s_s((safe_lshift_func_int8_t_s_s((safe_mul_func_int8_t_s_s(g_75[2], (g_578 | (3UL ^ (safe_mod_func_uint32_t_u_u((+((l_1318 < (l_1126 = ((safe_sub_func_int8_t_s_s((((*l_1321) = l_557) != (void*)0), p_71)) | g_128[0][3][1]))) & p_73)), g_146)))))), p_69)), l_1322))), 0x0C7AL)))) || p_69))), l_1322)) && 1L) , g_204)), g_133)), l_1323)) , l_1324[0][1]), 2)), l_1325));
+ }
+ ++l_1328;
+ }
+ else
+ { /* block id: 620 */
+ int64_t **l_1333 = &l_1150;
+ int64_t ***l_1332[7][3];
+ const int64_t *l_1336 = &g_1337;
+ const int64_t **l_1335 = &l_1336;
+ int i, j;
+ for (i = 0; i < 7; i++)
+ {
+ for (j = 0; j < 3; j++)
+ l_1332[i][j] = &l_1333;
+ }
+ g_146 &= ((l_1331 = &l_1215) != ((*l_1335) = (((*g_276) == (g_1334 = &l_1150)) , (void*)0)));
+ }
+ }
+ }
+ }
+ p_69 = ((safe_mul_func_int8_t_s_s(((!p_70) , (p_71 = (safe_sub_func_uint16_t_u_u((safe_add_func_int32_t_s_s(((((**g_276) = (void*)0) != (((safe_lshift_func_int16_t_s_u(((*l_461) = (safe_add_func_uint8_t_u_u(((*g_983)--), (safe_sub_func_uint8_t_u_u(((*g_457) , (g_458.f1 & ((*l_454)--))), (0xE33CL & (**l_1203))))))), 1)) && ((*g_643) = 0xE1FCL)) , (void*)0)) ^ ((safe_rshift_func_uint8_t_u_u(((**l_1203) , 0xAAL), p_73)) && 9UL)), 0x35057CD6L)), (**l_1203))))), g_1086)) , p_73);
+ return p_71;
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads : g_20 g_91 g_4 g_128 g_130 g_132 g_147 g_159 g_133 g_135 g_177 g_67 g_183 g_146 g_206 g_209 g_127 g_204 g_209.f1 g_209.f0 g_209.f3 g_254 g_258 g_267 g_276 g_268 g_274 l_17
+ * writes: g_127 g_130 g_132 g_133 g_147 g_159 g_177 g_183 g_135 g_146 g_204 g_206 g_254 g_258 g_267 g_268
+ */
+static union U0 func_97(const int32_t * p_98)
+{ /* block id: 35 */
+ union U0 l_118[10][7][1] = {{{{0xC9L}},{{0L}},{{0xFDL}},{{-10L}},{{-1L}},{{-1L}},{{-10L}}},{{{0xFDL}},{{0L}},{{0xC9L}},{{0L}},{{0L}},{{0xEEL}},{{-1L}}},{{{0xEEL}},{{0L}},{{0L}},{{0xC9L}},{{0L}},{{0xFDL}},{{-10L}}},{{{-1L}},{{-1L}},{{-10L}},{{0xFDL}},{{0L}},{{0xC9L}},{{0L}}},{{{0L}},{{0xEEL}},{{-1L}},{{0xEEL}},{{0L}},{{0L}},{{0xC9L}}},{{{0L}},{{0xFDL}},{{-10L}},{{-1L}},{{-1L}},{{-10L}},{{0xFDL}}},{{{0L}},{{0xC9L}},{{0L}},{{0L}},{{0xEEL}},{{-1L}},{{0xEEL}}},{{{0L}},{{0L}},{{0xC9L}},{{0L}},{{0xFDL}},{{-10L}},{{-1L}}},{{{-1L}},{{-10L}},{{0xFDL}},{{0L}},{{0xC9L}},{{0L}},{{0L}}},{{{0xEEL}},{{-1L}},{{0xEEL}},{{0L}},{{0L}},{{0xC9L}},{{0L}}}};
+ int32_t *l_121 = &g_20;
+ int32_t *l_123 = (void*)0;
+ int32_t **l_122 = &l_123;
+ int64_t *l_124 = (void*)0;
+ int64_t *l_126 = &g_91;
+ int64_t **l_125[2];
+ uint8_t *l_129 = &g_130;
+ uint64_t *l_131 = &g_132;
+ int32_t l_142 = 0x28050347L;
+ int32_t l_158[8][5] = {{0x58A6C8DEL,0xA13AD1F1L,(-1L),0xA13AD1F1L,0x58A6C8DEL},{0L,0xBB4E128BL,0xBB4E128BL,0L,0x815FF81FL},{(-2L),0xA13AD1F1L,(-2L),(-1L),(-2L)},{0L,0L,0x7C678778L,0xBB4E128BL,0x815FF81FL},{0x58A6C8DEL,(-1L),(-1L),(-1L),0x58A6C8DEL},{0x815FF81FL,0xBB4E128BL,0x7C678778L,0L,0L},{(-2L),(-1L),(-2L),0xA13AD1F1L,(-2L)},{0x815FF81FL,0L,0xBB4E128BL,0xBB4E128BL,0L}};
+ int64_t l_162 = (-1L);
+ uint32_t *l_230 = (void*)0;
+ int64_t l_330[6][10] = {{3L,0x18470653C73B861FLL,0xCCF0B8B5409C4288LL,0L,0L,0xCCF0B8B5409C4288LL,0x18470653C73B861FLL,3L,0x18470653C73B861FLL,0xCCF0B8B5409C4288LL},{0xA5B1CB5A17DCD406LL,0x7E45F49753809639LL,0L,0x7E45F49753809639LL,0xA5B1CB5A17DCD406LL,0xCCF0B8B5409C4288LL,0xCCF0B8B5409C4288LL,0xA5B1CB5A17DCD406LL,0x7E45F49753809639LL,0L},{3L,3L,0L,0xA5B1CB5A17DCD406LL,0xE47515C299F0A386LL,0xA5B1CB5A17DCD406LL,0L,3L,3L,0L},{0x7E45F49753809639LL,0xA5B1CB5A17DCD406LL,0xCCF0B8B5409C4288LL,0xCCF0B8B5409C4288LL,0xA5B1CB5A17DCD406LL,0x7E45F49753809639LL,0L,0x7E45F49753809639LL,0xA5B1CB5A17DCD406LL,0xCCF0B8B5409C4288LL},{0x18470653C73B861FLL,3L,0x18470653C73B861FLL,0xCCF0B8B5409C4288LL,0L,0L,0xCCF0B8B5409C4288LL,0x18470653C73B861FLL,3L,0x18470653C73B861FLL},{0x18470653C73B861FLL,0x7E45F49753809639LL,3L,0xA5B1CB5A17DCD406LL,3L,0x7E45F49753809639LL,0x18470653C73B861FLL,0x18470653C73B861FLL,0x7E45F49753809639LL,3L}};
+ int32_t l_338 = 4L;
+ uint64_t l_353 = 1UL;
+ const uint64_t l_440 = 0x55F846FE51E95657LL;
+ uint16_t *l_444[2];
+ uint16_t **l_443 = &l_444[0];
+ int i, j, k;
+ for (i = 0; i < 2; i++)
+ l_125[i] = &l_126;
+ for (i = 0; i < 2; i++)
+ l_444[i] = (void*)0;
+ if ((safe_div_func_int32_t_s_s(g_20, (safe_lshift_func_int8_t_s_s((safe_unary_minus_func_uint64_t_u((g_91 < (g_133 = (g_91 != ((*l_131) &= (((*l_129) |= (l_118[4][5][0] , (g_4[3] == ((((safe_rshift_func_uint8_t_u_u((((!(l_121 != ((*l_122) = (void*)0))) , l_124) == (g_127 = &g_91)), 0)) , (*l_121)) & g_128[1][2][0]) <= 0x94F4A132L)))) , (*l_121)))))))), 7)))))
+ { /* block id: 41 */
+ int32_t *l_134 = &g_135;
+ int32_t *l_136 = (void*)0;
+ int32_t l_137 = 0x8EC8C7DFL;
+ int32_t *l_138 = &g_135;
+ int32_t *l_139 = (void*)0;
+ int32_t *l_140 = &g_135;
+ int32_t *l_141[2][10][5] = {{{&g_135,(void*)0,&g_135,&g_135,(void*)0},{(void*)0,&g_4[4],&g_4[0],(void*)0,&g_20},{(void*)0,&g_4[3],&g_4[1],&g_4[0],(void*)0},{(void*)0,(void*)0,(void*)0,(void*)0,&g_135},{&l_137,(void*)0,(void*)0,&g_20,(void*)0},{(void*)0,&g_20,&g_135,(void*)0,&g_135},{&g_4[0],&g_4[0],(void*)0,&g_20,(void*)0},{(void*)0,&g_4[4],&g_135,&g_4[0],(void*)0},{&g_135,(void*)0,&g_20,(void*)0,&g_135},{&l_137,&g_4[4],&g_20,&g_4[3],(void*)0}},{{&g_20,&g_4[0],(void*)0,(void*)0,(void*)0},{&g_4[3],&g_20,&g_4[3],&g_4[4],(void*)0},{&g_4[1],(void*)0,&g_4[0],&g_4[3],&g_135},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,(void*)0,&g_4[0],&g_135,(void*)0},{&g_20,&g_20,&g_4[3],&g_135,&g_135},{&g_135,(void*)0,(void*)0,&g_135,(void*)0},{&g_20,(void*)0,&g_20,&l_137,&g_135},{(void*)0,&l_137,&g_20,&g_4[0],&g_20},{(void*)0,(void*)0,&g_135,&l_137,&g_20}}};
+ uint8_t l_143 = 0UL;
+ int i, j, k;
+ ++l_143;
+ g_147--;
+ }
+ else
+ { /* block id: 44 */
+ int32_t *l_150 = &l_142;
+ int32_t *l_151 = &l_142;
+ int32_t *l_152 = (void*)0;
+ int32_t *l_153 = &l_142;
+ int32_t *l_154 = &l_142;
+ int32_t *l_155 = &g_146;
+ int32_t *l_156 = &g_146;
+ int32_t *l_157[2];
+ int16_t l_222[5] = {(-1L),(-1L),(-1L),(-1L),(-1L)};
+ uint16_t *l_275 = &g_177;
+ int64_t *l_282 = &l_162;
+ int32_t **l_287 = &l_154;
+ union U0 l_299[3] = {{0L},{0L},{0L}};
+ int32_t l_306 = 0xE7992D64L;
+ uint8_t l_346 = 0x8BL;
+ uint8_t l_378 = 0UL;
+ uint16_t ***l_445 = &l_443;
+ int i;
+ for (i = 0; i < 2; i++)
+ l_157[i] = &g_135;
+ (*l_150) = 0xCCA6638CL;
+ g_159--;
+ for (g_133 = 0; (g_133 <= 0); g_133 += 1)
+ { /* block id: 49 */
+ uint16_t *l_176 = &g_177;
+ uint8_t *l_182 = &g_183;
+ int32_t l_202 = 0xFD7715F6L;
+ int32_t l_225 = 0xCDD8E95DL;
+ int32_t **l_265 = (void*)0;
+ uint64_t *l_278[2];
+ uint32_t *l_319 = &g_159;
+ union U0 l_352 = {0xE1L};
+ int64_t ***l_406 = &g_277[0];
+ int i;
+ for (i = 0; i < 2; i++)
+ l_278[i] = &g_132;
+ if (l_162)
+ break;
+ if ((safe_mul_func_uint16_t_u_u(g_132, (safe_lshift_func_int8_t_s_u(((!(safe_lshift_func_uint16_t_u_u((safe_mod_func_uint32_t_u_u(g_91, ((*l_153) = (safe_lshift_func_int8_t_s_u((safe_div_func_int16_t_s_s((g_135 != (((((safe_unary_minus_func_int64_t_s(0L)) <= g_4[3]) | ((*l_176)--)) , &g_132) != (void*)0)), ((((*l_182) = (g_130++)) || g_128[0][0][1]) ^ 0UL))), 1))))), 9))) == g_67[5]), g_159)))))
+ { /* block id: 55 */
+ int32_t *l_184[2][4][9] = {{{(void*)0,&g_135,&g_146,&g_146,&g_135,(void*)0,&g_135,&g_146,&g_146},{&g_135,&g_135,(void*)0,(void*)0,(void*)0,&g_135,&g_135,(void*)0,(void*)0},{(void*)0,&g_135,(void*)0,(void*)0,(void*)0,(void*)0,&g_135,(void*)0,(void*)0},{&g_4[3],(void*)0,(void*)0,&g_4[3],&l_142,&g_4[3],(void*)0,(void*)0,&g_4[3]}},{{&g_4[2],(void*)0,&g_146,(void*)0,&g_4[2],&g_4[2],(void*)0,&g_146,(void*)0},{(void*)0,&l_142,(void*)0,(void*)0,&l_142,(void*)0,&l_142,(void*)0,(void*)0},{&g_4[2],&g_4[2],(void*)0,&g_146,(void*)0,&g_4[2],&g_4[2],(void*)0,&g_146},{&g_4[3],&l_142,&g_4[3],(void*)0,(void*)0,&g_4[3],&l_142,&g_4[3],(void*)0}}};
+ int32_t *l_185 = &l_158[5][4];
+ int32_t l_226 = 0x35E0E7B4L;
+ int8_t l_227 = (-7L);
+ int8_t l_229 = 0x9BL;
+ int i, j, k;
+ l_185 = (l_184[1][2][2] = ((*l_122) = (void*)0));
+ for (g_135 = 0; (g_135 >= 0); g_135 -= 1)
+ { /* block id: 61 */
+ int16_t l_205 = 0x495EL;
+ for (l_142 = 0; (l_142 <= 0); l_142 += 1)
+ { /* block id: 64 */
+ uint32_t *l_199 = &g_159;
+ int32_t l_203 = 1L;
+ g_204 = (safe_sub_func_uint8_t_u_u((safe_sub_func_uint16_t_u_u((safe_lshift_func_uint8_t_u_s((!0xEBL), ((safe_mod_func_int32_t_s_s((*p_98), ((*l_121) & (safe_rshift_func_uint16_t_u_u((safe_unary_minus_func_int64_t_s((0x15133C6BL <= g_183))), ((safe_add_func_uint64_t_u_u(9UL, 0xE941047791FE6ADBLL)) | ((--(*l_199)) & ((*l_156) |= ((~l_202) || (((*l_131) = (g_130 , l_203)) | 0x206A442AE9B445DALL)))))))))) < g_67[3]))), g_128[0][0][0])), 0x5CL));
+ if (l_205)
+ break;
+ g_206--;
+ }
+ return g_209;
+ }
+ if (g_67[1])
+ { /* block id: 74 */
+ uint32_t *l_228 = &g_159;
+ int32_t l_238 = 0x66868886L;
+ int32_t l_257[8] = {(-6L),(-6L),(-6L),(-6L),(-6L),(-6L),(-6L),(-6L)};
+ const uint16_t *l_273 = &g_274;
+ int i;
+ if ((((((safe_add_func_uint32_t_u_u(((void*)0 != p_98), ((((safe_mul_func_uint16_t_u_u((((((safe_lshift_func_int8_t_s_s((safe_lshift_func_uint8_t_u_u((*l_121), 4)), (0UL & (g_4[0] , (((((*l_129) = (safe_mod_func_int64_t_s_s((l_222[3] = (*g_127)), g_204))) ^ l_202) <= ((((*l_228) = ((((safe_rshift_func_uint8_t_u_s((l_225 = ((-10L) || 4L)), 1)) & l_226) == l_227) | 1L)) && 0x4375D102L) | (*g_127))) <= g_209.f1))))) ^ g_209.f0) == 0x0DDE07FD64A67530LL) && 0L) , l_229), 0xA2EDL)) | (*g_127)) != 18446744073709551615UL) >= g_133))) || g_146) , g_209.f3) >= l_202) ^ g_91))
+ { /* block id: 79 */
+ int32_t **l_231 = (void*)0;
+ int32_t **l_232 = (void*)0;
+ int32_t **l_233 = (void*)0;
+ int32_t **l_234 = &l_152;
+ (*l_154) = (0x1EL >= 0L);
+ l_202 |= (((l_230 = l_155) != l_121) <= 0x0F1CL);
+ (*l_234) = ((*l_122) = (void*)0);
+ }
+ else
+ { /* block id: 85 */
+ uint32_t l_235 = 4294967295UL;
+ l_235--;
+ }
+ if (((*l_155) = (l_202 < g_4[3])))
+ { /* block id: 89 */
+ const int16_t l_245 = 0x1D43L;
+ uint64_t *l_248 = (void*)0;
+ int32_t l_249 = 0x4F5E980EL;
+ int32_t l_250 = (-1L);
+ int32_t l_251 = 0x2859D2BFL;
+ int32_t l_252 = 1L;
+ (*l_150) &= ((((*l_176) = 0xA8DEL) | l_238) >= ((*l_182) |= (safe_lshift_func_uint8_t_u_u((g_4[3] != g_146), 6))));
+ (*l_155) = (safe_lshift_func_int8_t_s_s(((safe_mod_func_int8_t_s_s(((l_245 ^ ((-1L) < (1UL <= ((((safe_div_func_uint32_t_u_u((((!((void*)0 != &g_132)) > ((&g_133 == (g_209.f1 , l_248)) >= (0x9357L || l_245))) <= (-3L)), 1L)) && g_209.f1) <= g_209.f0) <= 0xACL)))) <= (*g_127)), (-3L))) != 0UL), 3));
+ ++g_254;
+ }
+ else
+ { /* block id: 95 */
+ int32_t ***l_266 = &l_265;
+ const int32_t ***l_269 = &g_267;
+ const uint16_t *l_270 = &g_177;
+ const uint16_t **l_271 = (void*)0;
+ const uint16_t **l_272 = &l_270;
+ union U0 l_279[6][7] = {{{-7L},{1L},{1L},{1L},{1L},{-7L},{1L}},{{-3L},{-7L},{-7L},{-3L},{1L},{-3L},{-7L}},{{-10L},{-10L},{-7L},{1L},{-7L},{-10L},{-10L}},{{-10L},{-3L},{1L},{-3L},{-7L},{-7L},{-3L}},{{1L},{-10L},{1L},{-3L},{-3L},{1L},{-10L}},{{-3L},{-10L},{1L},{1L},{-10L},{-3L},{-10L}}};
+ union U0 *l_280[2];
+ int64_t * const l_281 = (void*)0;
+ int i, j;
+ for (i = 0; i < 2; i++)
+ l_280[i] = (void*)0;
+ --g_258[3];
+ (*l_156) = ((p_98 == p_98) != ((safe_mod_func_uint8_t_u_u((((l_238 ^ (safe_lshift_func_int16_t_s_u(((((*l_266) = l_265) != ((*l_269) = g_267)) , (l_257[5] > ((l_273 = ((*l_272) = l_270)) == l_275))), ((((!(g_209.f1 && 4294967295UL)) , 18446744073709551615UL) , 0xDDL) <= l_257[5])))) , &l_125[1]) != g_276), l_257[5])) >= l_238));
+ (**l_269) = func_99(((*l_176) = 0xD72BL), (~(&g_132 != ((+(***l_269)) , l_278[0]))), (l_118[1][1][0] = l_279[4][4]), l_281, l_282);
+ }
+ if ((*g_268))
+ break;
+ return g_209;
+ }
+ else
+ { /* block id: 108 */
+ uint32_t l_283 = 0x9C6F2927L;
+ uint32_t *l_286 = &l_283;
+ l_283 = 0L;
+ (*l_156) |= (safe_sub_func_uint32_t_u_u((g_147 || ((((*l_286) = g_91) , (65526UL <= (((l_287 != ((+l_225) , &l_151)) || (safe_lshift_func_uint16_t_u_s(0x0559L, 15))) >= (((1L == ((((*l_129) = ((-2L) > g_4[3])) > g_177) , g_20)) , g_147) == l_283)))) <= 8L)), g_20));
+ }
+ }
+ else
+ { /* block id: 114 */
+ uint32_t *l_292 = &g_254;
+ int8_t *l_297 = &g_209.f3;
+ int8_t *l_298[3];
+ int i;
+ for (i = 0; i < 3; i++)
+ l_298[i] = (void*)0;
+ (*l_153) = (**l_287);
+ g_135 ^= (safe_div_func_int16_t_s_s((((((((**g_267) >= ((*l_292) = ((void*)0 != (*g_267)))) > ((*l_282) = (safe_mod_func_uint32_t_u_u(0xB1D3D90BL, (safe_mul_func_int8_t_s_s(((+(g_130 , (*l_150))) <= ((*l_156) = g_209.f1)), (*l_121))))))) >= (((((~((g_183 || (-1L)) || g_274)) & 0x12DC9772L) ^ g_67[0]) == 3L) , (*l_121))) != 0xEB08L) == (*l_121)) , (*l_121)), (*l_121)));
+ (*l_122) = ((*l_287) = (*l_287));
+ for (g_132 = 0; (g_132 <= 1); g_132 += 1)
+ { /* block id: 124 */
+ return l_299[2];
+ }
+ }
+ (*g_267) = p_98;
+ for (g_132 = 0; (g_132 <= 0); g_132 += 1)
+ { /* block id: 131 */
+ const uint8_t l_328 = 253UL;
+ int8_t *l_329 = &g_209.f1;
+ int32_t l_345 = 0x37E602FBL;
+ int8_t l_379 = 0x45L;
+ int32_t l_381 = (-1L);
+ int64_t *** const l_405 = (void*)0;
+ }
+ }
+ (*l_445) = l_443;
+ }
+ return l_118[6][0][0];
+}
+
+
+/* ------------------------------------------ */
+/*
+ * reads :
+ * writes:
+ */
+static const int32_t * func_99(uint16_t p_100, int16_t p_101, union U0 p_102, int64_t * const p_103, int64_t * p_104)
+{ /* block id: 32 */
+ int64_t * const l_111 = &g_91;
+ int64_t * const *l_110 = &l_111;
+ int64_t * const **l_109 = &l_110;
+ const int32_t *l_112[3][1][6];
+ int i, j, k;
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 1; j++)
+ {
+ for (k = 0; k < 6; k++)
+ l_112[i][j][k] = &g_4[3];
+ }
+ }
+ (*l_109) = &p_103;
+ return l_112[2][0][0];
+}
+
+
+
+
+/* ---------------------------------------- */
+int main (int argc, char* argv[])
+{
+ int i, j, k;
+ int print_hash_value = 0;
+ if (argc == 2 && strcmp(argv[1], "1") == 0) print_hash_value = 1;
+ platform_main_begin();
+ crc32_gentab();
+ func_1();
+ for (i = 0; i < 5; i++)
+ {
+ transparent_crc(g_4[i], "g_4[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ transparent_crc(g_20, "g_20", print_hash_value);
+ for (i = 0; i < 7; i++)
+ {
+ transparent_crc(g_67[i], "g_67[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ for (i = 0; i < 3; i++)
+ {
+ transparent_crc(g_75[i], "g_75[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ transparent_crc(g_78, "g_78", print_hash_value);
+ transparent_crc(g_91, "g_91", print_hash_value);
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ for (k = 0; k < 3; k++)
+ {
+ transparent_crc(g_128[i][j][k], "g_128[i][j][k]", print_hash_value);
+ if (print_hash_value) printf("index = [%d][%d][%d]\n", i, j, k);
+
+ }
+ }
+ }
+ transparent_crc(g_130, "g_130", print_hash_value);
+ transparent_crc(g_132, "g_132", print_hash_value);
+ transparent_crc(g_133, "g_133", print_hash_value);
+ transparent_crc(g_135, "g_135", print_hash_value);
+ transparent_crc(g_146, "g_146", print_hash_value);
+ transparent_crc(g_147, "g_147", print_hash_value);
+ transparent_crc(g_159, "g_159", print_hash_value);
+ transparent_crc(g_177, "g_177", print_hash_value);
+ transparent_crc(g_183, "g_183", print_hash_value);
+ transparent_crc(g_204, "g_204", print_hash_value);
+ transparent_crc(g_206, "g_206", print_hash_value);
+ transparent_crc(g_209.f0, "g_209.f0", print_hash_value);
+ transparent_crc(g_209.f1, "g_209.f1", print_hash_value);
+ transparent_crc(g_209.f3, "g_209.f3", print_hash_value);
+ transparent_crc(g_253, "g_253", print_hash_value);
+ transparent_crc(g_254, "g_254", print_hash_value);
+ for (i = 0; i < 8; i++)
+ {
+ transparent_crc(g_258[i], "g_258[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ transparent_crc(g_274, "g_274", print_hash_value);
+ transparent_crc(g_380, "g_380", print_hash_value);
+ transparent_crc(g_383, "g_383", print_hash_value);
+ transparent_crc(g_384, "g_384", print_hash_value);
+ transparent_crc(g_408, "g_408", print_hash_value);
+ for (i = 0; i < 1; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ transparent_crc(g_409[i][j], "g_409[i][j]", print_hash_value);
+ if (print_hash_value) printf("index = [%d][%d]\n", i, j);
+
+ }
+ }
+ transparent_crc(g_458.f0, "g_458.f0", print_hash_value);
+ transparent_crc(g_458.f1, "g_458.f1", print_hash_value);
+ transparent_crc(g_458.f3, "g_458.f3", print_hash_value);
+ transparent_crc(g_471, "g_471", print_hash_value);
+ transparent_crc(g_578, "g_578", print_hash_value);
+ transparent_crc(g_629, "g_629", print_hash_value);
+ transparent_crc(g_708, "g_708", print_hash_value);
+ transparent_crc(g_746, "g_746", print_hash_value);
+ transparent_crc(g_778, "g_778", print_hash_value);
+ transparent_crc(g_888, "g_888", print_hash_value);
+ transparent_crc(g_1086, "g_1086", print_hash_value);
+ transparent_crc(g_1326, "g_1326", print_hash_value);
+ transparent_crc(g_1337, "g_1337", print_hash_value);
+ transparent_crc(g_1413, "g_1413", print_hash_value);
+ transparent_crc(g_1585, "g_1585", print_hash_value);
+ transparent_crc(g_1622, "g_1622", print_hash_value);
+ transparent_crc(g_1679, "g_1679", print_hash_value);
+ transparent_crc(g_1860, "g_1860", print_hash_value);
+ transparent_crc(g_1962, "g_1962", print_hash_value);
+ for (i = 0; i < 10; i++)
+ {
+ transparent_crc(g_2033[i], "g_2033[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ transparent_crc(g_2193.f0, "g_2193.f0", print_hash_value);
+ transparent_crc(g_2193.f1, "g_2193.f1", print_hash_value);
+ transparent_crc(g_2193.f3, "g_2193.f3", print_hash_value);
+ transparent_crc(g_2307, "g_2307", print_hash_value);
+ transparent_crc(g_2497, "g_2497", print_hash_value);
+ transparent_crc(g_2508, "g_2508", print_hash_value);
+ transparent_crc(g_2648, "g_2648", print_hash_value);
+ transparent_crc(g_2767, "g_2767", print_hash_value);
+ transparent_crc(g_2797, "g_2797", print_hash_value);
+ transparent_crc(g_2866, "g_2866", print_hash_value);
+ transparent_crc(g_2895, "g_2895", print_hash_value);
+ for (i = 0; i < 4; i++)
+ {
+ transparent_crc(g_3176[i], "g_3176[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ transparent_crc(g_3254, "g_3254", print_hash_value);
+ transparent_crc(g_3261, "g_3261", print_hash_value);
+ for (i = 0; i < 7; i++)
+ {
+ transparent_crc(g_3322[i], "g_3322[i]", print_hash_value);
+ if (print_hash_value) printf("index = [%d]\n", i);
+
+ }
+ transparent_crc(g_3340, "g_3340", print_hash_value);
+ transparent_crc(g_3407, "g_3407", print_hash_value);
+ transparent_crc(g_3485, "g_3485", print_hash_value);
+ transparent_crc(g_3515, "g_3515", print_hash_value);
+ transparent_crc(g_3578, "g_3578", print_hash_value);
+ transparent_crc(g_3815, "g_3815", print_hash_value);
+ transparent_crc(g_3847, "g_3847", print_hash_value);
+ transparent_crc(g_3879, "g_3879", print_hash_value);
+ transparent_crc(g_3880, "g_3880", print_hash_value);
+ platform_main_end(crc32_context ^ 0xFFFFFFFFUL, print_hash_value);
+ return 0;
+}
+
+/************************ statistics *************************
+XXX max struct depth: 0
+breakdown:
+ depth: 0, occurrence: 1041
+XXX total union variables: 31
+
+XXX non-zero bitfields defined in structs: 0
+XXX zero bitfields defined in structs: 0
+XXX const bitfields defined in structs: 0
+XXX volatile bitfields defined in structs: 0
+XXX structs with bitfields in the program: 0
+breakdown:
+XXX full-bitfields structs in the program: 0
+breakdown:
+XXX times a bitfields struct's address is taken: 0
+XXX times a bitfields struct on LHS: 0
+XXX times a bitfields struct on RHS: 0
+XXX times a single bitfield on LHS: 0
+XXX times a single bitfield on RHS: 0
+
+XXX max expression depth: 47
+breakdown:
+ depth: 1, occurrence: 335
+ depth: 2, occurrence: 80
+ depth: 3, occurrence: 8
+ depth: 4, occurrence: 4
+ depth: 5, occurrence: 5
+ depth: 6, occurrence: 2
+ depth: 7, occurrence: 4
+ depth: 8, occurrence: 3
+ depth: 9, occurrence: 4
+ depth: 10, occurrence: 2
+ depth: 15, occurrence: 3
+ depth: 16, occurrence: 4
+ depth: 17, occurrence: 2
+ depth: 18, occurrence: 5
+ depth: 19, occurrence: 8
+ depth: 20, occurrence: 8
+ depth: 21, occurrence: 3
+ depth: 22, occurrence: 7
+ depth: 23, occurrence: 2
+ depth: 24, occurrence: 2
+ depth: 25, occurrence: 4
+ depth: 26, occurrence: 2
+ depth: 27, occurrence: 7
+ depth: 28, occurrence: 2
+ depth: 29, occurrence: 3
+ depth: 30, occurrence: 3
+ depth: 31, occurrence: 1
+ depth: 32, occurrence: 1
+ depth: 34, occurrence: 2
+ depth: 36, occurrence: 1
+ depth: 39, occurrence: 1
+ depth: 41, occurrence: 1
+ depth: 44, occurrence: 1
+ depth: 47, occurrence: 1
+
+XXX total number of pointers: 777
+
+XXX times a variable address is taken: 1700
+XXX times a pointer is dereferenced on RHS: 704
+breakdown:
+ depth: 1, occurrence: 460
+ depth: 2, occurrence: 141
+ depth: 3, occurrence: 54
+ depth: 4, occurrence: 38
+ depth: 5, occurrence: 9
+ depth: 6, occurrence: 2
+XXX times a pointer is dereferenced on LHS: 578
+breakdown:
+ depth: 1, occurrence: 460
+ depth: 2, occurrence: 71
+ depth: 3, occurrence: 35
+ depth: 4, occurrence: 10
+ depth: 5, occurrence: 1
+ depth: 6, occurrence: 1
+XXX times a pointer is compared with null: 83
+XXX times a pointer is compared with address of another variable: 24
+XXX times a pointer is compared with another pointer: 23
+XXX times a pointer is qualified to be dereferenced: 13137
+
+XXX max dereference level: 6
+breakdown:
+ level: 0, occurrence: 0
+ level: 1, occurrence: 3348
+ level: 2, occurrence: 779
+ level: 3, occurrence: 469
+ level: 4, occurrence: 276
+ level: 5, occurrence: 33
+ level: 6, occurrence: 10
+XXX number of pointers point to pointers: 359
+XXX number of pointers point to scalars: 399
+XXX number of pointers point to structs: 0
+XXX percent of pointers has null in alias set: 28.4
+XXX average alias set size: 1.47
+
+XXX times a non-volatile is read: 4088
+XXX times a non-volatile is write: 1844
+XXX times a volatile is read: 0
+XXX times read thru a pointer: 0
+XXX times a volatile is write: 0
+XXX times written thru a pointer: 0
+XXX times a volatile is available for access: 0
+XXX percentage of non-volatile access: 100
+
+XXX forward jumps: 2
+XXX backward jumps: 8
+
+XXX stmts: 344
+XXX max block depth: 5
+breakdown:
+ depth: 0, occurrence: 29
+ depth: 1, occurrence: 40
+ depth: 2, occurrence: 37
+ depth: 3, occurrence: 58
+ depth: 4, occurrence: 74
+ depth: 5, occurrence: 106
+
+XXX percentage a fresh-made variable is used: 15.7
+XXX percentage an existing variable is used: 84.3
+********************* end of statistics **********************/
+
diff --git a/tests/fuzz/21.c.txt b/tests/fuzz/21.c.txt
new file mode 100644
index 00000000..135eae10
--- /dev/null
+++ b/tests/fuzz/21.c.txt
@@ -0,0 +1 @@
+checksum = BE13AE15
diff --git a/tests/gl_teximage.c b/tests/gl_teximage.c
new file mode 100644
index 00000000..9cafce9c
--- /dev/null
+++ b/tests/gl_teximage.c
@@ -0,0 +1,120 @@
+/*
+ * GLES2 test for glTexImage2D parameters
+ *
+ * Original author: Jason Green <jason@transgaming.com>
+ *
+ */
+#include "GLES2/gl2.h"
+#include "SDL/SDL.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <emscripten.h>
+#include <unistd.h>
+
+typedef enum {
+ TEST_STATUS_SUCCESS = 0,
+ TEST_STATUS_FAILURE = 1
+} TestStatus;
+
+/* Report success or failure (1 or 0) to Emscripten's test harness. Also, exit
+ * with the given error code. */
+static void exit_with_status(TestStatus code)
+{
+#ifdef REPORT_RESULT
+ int result = (code == TEST_STATUS_SUCCESS) ? 1 : 0;
+ REPORT_RESULT();
+#endif
+
+ exit(code);
+}
+
+/* Loop over all glGetError() results until GL reports GL_NO_ERROR */
+static void clear_gl_errors()
+{
+ GLenum err;
+ do {
+ err = glGetError();
+ } while (err != GL_NO_ERROR);
+}
+
+int main(int argc, char *argv[])
+{
+ TestStatus passed = TEST_STATUS_SUCCESS;
+ SDL_Surface *screen;
+
+ if (SDL_Init(SDL_INIT_VIDEO) != 0) {
+ printf("SDL_Init failed with %s\n", SDL_GetError());
+ exit_with_status(TEST_STATUS_FAILURE);
+ }
+
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ screen = SDL_SetVideoMode(640, 480, 16, SDL_OPENGL);
+ if (!screen) {
+ printf("SDL_SetVideoMode failed with %s\n", SDL_GetError());
+ exit_with_status(TEST_STATUS_FAILURE);
+ }
+
+ GLuint texture;
+ glGenTextures(1, &texture);
+
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ // Allocate space for a 32x32 image with 4 bytes per pixel.
+ // No need to fill it with any useful information, as these tests are
+ // only designed to make sure glTexImage2D doesn't crash on unsupported
+ // formats.
+ void* pixels = malloc(4 * 32 * 32);
+ if (pixels == NULL) {
+ printf("Unable to allocate pixel data\n");
+ exit_with_status(TEST_STATUS_FAILURE);
+ }
+
+ // First, try 0xffff for the internal format - should fail
+ glTexImage2D(GL_TEXTURE_2D, 0, 0xffff, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ GLenum err = glGetError();
+ if (err == GL_NO_ERROR) {
+ printf("internal format == 0xffff succeeded, but should have failed\n");
+ passed = TEST_STATUS_FAILURE;
+ }
+ clear_gl_errors();
+
+ // Try 0xffff for the format - should fail
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, 0xffff, GL_UNSIGNED_BYTE, pixels);
+ err = glGetError();
+ if (err == GL_NO_ERROR) {
+ printf("format == 0xffff succeeded, but should have failed\n");
+ passed = TEST_STATUS_FAILURE;
+ }
+ clear_gl_errors();
+
+ // Try 0xffff for the type - should fail
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, 0xffff, pixels);
+ err = glGetError();
+ if (err == GL_NO_ERROR) {
+ printf("type == 0xffff succeeded, but should have failed\n");
+ passed = TEST_STATUS_FAILURE;
+ }
+ clear_gl_errors();
+
+ // Try GL_RGBA/GL_UNSIGNED_BYTE - should succeed
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ err = glGetError();
+ if (err != GL_NO_ERROR) {
+ printf("GL_RGBA/GL_UNSIGNED_BYTE failed with %x, but should have succeeded\n", err);
+ passed = TEST_STATUS_FAILURE;
+ }
+ clear_gl_errors();
+
+ // Clean up objects
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDeleteTextures(1, &texture);
+ free(pixels);
+
+ // 'screen' is freed implicitly by SDL_Quit()
+ SDL_Quit();
+
+ exit_with_status(passed);
+}
diff --git a/tests/hello_world_file.cpp b/tests/hello_world_file.cpp
index 71fb953b..97ea395e 100644
--- a/tests/hello_world_file.cpp
+++ b/tests/hello_world_file.cpp
@@ -1,6 +1,10 @@
#include <stdio.h>
int main() {
FILE *file = fopen("tests/hello_world_file.txt", "rb");
+ if (!file) {
+ printf("cannot open file\n");
+ return 1;
+ }
while (!feof(file)) {
char c = fgetc(file);
if (c != EOF) {
diff --git a/tests/life.c b/tests/life.c
index 4ce8d385..263fa0e6 100644
--- a/tests/life.c
+++ b/tests/life.c
@@ -67,7 +67,9 @@ void game(int w, int h, int i)
i--;
nudge(univ, w, h); // keep it interesting for benchmark
} else {
+#if !__EMSCRIPTEN__
usleep(20000);
+#endif
show(univ, w, h);
}
}
diff --git a/tests/return64bit/test.c b/tests/return64bit/test.c
new file mode 100644
index 00000000..e75ee5c1
--- /dev/null
+++ b/tests/return64bit/test.c
@@ -0,0 +1,6 @@
+
+// This is just a trivial test function, the key bit of interest is that it returns a 64 bit long.
+long long test() {
+ long long x = ((long long)1234 << 32) + 5678;
+ return x;
+}
diff --git a/tests/return64bit/testbind.js b/tests/return64bit/testbind.js
new file mode 100644
index 00000000..f2cc0e7b
--- /dev/null
+++ b/tests/return64bit/testbind.js
@@ -0,0 +1,18 @@
+// This code represents a simple native JavaScript binding to a test C function
+// that returns a 64 bit long. Notice that the least significant 32 bits are
+// returned in the normal return value, but the most significant 32 bits are
+// returned via the accessor method Runtime.getTempRet0()
+
+var Module = {
+ 'noExitRuntime' : true
+};
+
+Module['runtest'] = function() {
+ var low = _test();
+ var high = Runtime.getTempRet0();
+
+ console.log("low = " + low);
+ console.log("high = " + high);
+};
+
+
diff --git a/tests/return64bit/testbindend.js b/tests/return64bit/testbindend.js
new file mode 100644
index 00000000..2218f14d
--- /dev/null
+++ b/tests/return64bit/testbindend.js
@@ -0,0 +1,2 @@
+
+})(); // End of self calling lambda used to wrap library.
diff --git a/tests/return64bit/testbindstart.js b/tests/return64bit/testbindstart.js
new file mode 100644
index 00000000..4956806b
--- /dev/null
+++ b/tests/return64bit/testbindstart.js
@@ -0,0 +1,3 @@
+
+(function() { // Start of self-calling lambda used to avoid polluting global namespace.
+
diff --git a/tests/sdl_audio_mix.c b/tests/sdl_audio_mix.c
index a1c0485d..422fc122 100644
--- a/tests/sdl_audio_mix.c
+++ b/tests/sdl_audio_mix.c
@@ -58,7 +58,9 @@ void one_iter() {
Mix_HaltChannel(soundChannel);
Mix_HaltMusic();
int result = 1;
+#ifdef REPORT_RESULT
REPORT_RESULT();
+#endif
break;
};
}
diff --git a/tests/sdl_audio_quickload.c b/tests/sdl_audio_quickload.c
deleted file mode 100644
index 1525d048..00000000
--- a/tests/sdl_audio_quickload.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <SDL/SDL.h>
-#include <SDL/SDL_mixer.h>
-#include <assert.h>
-#include <limits.h>
-#include <emscripten.h>
-
-Mix_Chunk *sound;
-
-void play() {
- int channel = Mix_PlayChannel(-1, sound, 1);
- assert(channel == 0);
-
- int result = 1;
- REPORT_RESULT();
-}
-
-int main(int argc, char **argv) {
- SDL_Init(SDL_INIT_AUDIO);
-
- int ret = Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024);
- assert(ret == 0);
-
- Uint16* buffer = (Uint16*)malloc(10*44100*sizeof(Uint16));
- for (Uint32 i = 0; i < 10*44100; ++i) {
- buffer[i] = (i * 5) % UINT32_MAX;
- }
- sound = Mix_QuickLoad_RAW((Uint8*) buffer, 10*44100*sizeof(Uint16));
- assert(sound);
-
- play();
-
- emscripten_run_script("element = document.createElement('input');"
- "element.setAttribute('type', 'button');"
- "element.setAttribute('value', 'replay!');"
- "element.setAttribute('onclick', 'Module[\"_play\"]()');"
- "document.body.appendChild(element);");
-
- printf("you should one sounds. press the button to replay!\n");
-
- return 0;
-}
-
diff --git a/tests/sdl_image.c b/tests/sdl_image.c
index 523f8903..9639ea37 100644
--- a/tests/sdl_image.c
+++ b/tests/sdl_image.c
@@ -4,6 +4,7 @@
#include <assert.h>
#include <emscripten.h>
#include <unistd.h>
+#include <stdlib.h>
int testImage(SDL_Surface* screen, const char* fileName) {
SDL_Surface *image = IMG_Load(fileName);
@@ -18,7 +19,16 @@ int testImage(SDL_Surface* screen, const char* fileName) {
int result = image->w;
SDL_BlitSurface (image, NULL, screen, NULL);
+
+ int w, h;
+ char *data = emscripten_get_preloaded_image_data(fileName, &w, &h);
+
+ assert(data);
+ assert(w == image->w);
+ assert(h == image->h);
+
SDL_FreeSurface (image);
+ free(data);
return result;
}
diff --git a/tests/sdl_touch.c b/tests/sdl_touch.c
index 1fce1df1..dc315c58 100644
--- a/tests/sdl_touch.c
+++ b/tests/sdl_touch.c
@@ -66,9 +66,12 @@ int main() {
for(var d in data) event[d] = data[d];
Module['canvas'].dispatchEvent(event);
}
- sendEvent('touchstart', { touches: [ { pageX: 300, pageY: 400, deviceID: 1, identifier: 1, force: 1 } ] });
- sendEvent('touchmove', { touches: [ { pageX: 350, pageY: 400, deviceID: 1, identifier: 1, force: 1 } ] });
- sendEvent('touchend', { changedTouches: [ { pageX: 350, pageY: 400, deviceID: 1, identifier: 1, force: 1 } ] });
+ // Pass test coordinates in canvas element coordinate frame.
+ var x = Module['canvas'].getBoundingClientRect().left;
+ var y = Module['canvas'].getBoundingClientRect().top;
+ sendEvent('touchstart', { touches: [ { pageX: x+300, pageY: y+225, deviceID: 1, identifier: 1, force: 1 } ] });
+ sendEvent('touchmove', { touches: [ { pageX: x+400, pageY: y+225, deviceID: 1, identifier: 1, force: 1 } ] });
+ sendEvent('touchend', { changedTouches: [ { pageX: x+400, pageY: y+225, deviceID: 1, identifier: 1, force: 1 } ] });
);
#endif
diff --git a/tests/test_benchmark.py b/tests/test_benchmark.py
index 735f0feb..16abbfdd 100644
--- a/tests/test_benchmark.py
+++ b/tests/test_benchmark.py
@@ -112,6 +112,7 @@ process(sys.argv[1])
'--memory-init-file', '0', '--js-transform', 'python hardcode.py',
'-s', 'TOTAL_MEMORY=128*1024*1024',
#'-profiling',
+ #'--closure', '1',
'-o', final] + shared_args + emcc_args + self.extra_args, stdout=PIPE, stderr=PIPE, env=self.env).communicate()
assert os.path.exists(final), 'Failed to compile file: ' + output[0]
self.filename = final
@@ -407,6 +408,42 @@ class benchmark(RunnerCore):
'''
self.do_benchmark('ifs', src, 'ok', reps=TEST_REPS*5)
+ def test_conditionals(self):
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ int main(int argc, char *argv[]) {
+ int arg = argc > 1 ? argv[1][0] - '0' : 3;
+ switch(arg) {
+ case 0: return 0; break;
+ case 1: arg = 3*75; break;
+ case 2: arg = 3*625; break;
+ case 3: arg = 3*1250; break;
+ case 4: arg = 3*5*1250; break;
+ case 5: arg = 3*10*1250; break;
+ default: printf("error: %d\\n", arg); return -1;
+ }
+
+ int x = 0;
+
+ for (int j = 0; j < 27000; j++) {
+ for (int i = 0; i < arg; i++) {
+ if (((x*x+11) % 3 == 0) | ((x*(x+2)+17) % 5 == 0)) {
+ x += 2;
+ } else {
+ x++;
+ }
+ }
+ }
+
+ printf("ok %d\n", x);
+
+ return x;
+ }
+ '''
+ self.do_benchmark('conditionals', src, 'ok', reps=TEST_REPS*5)
+
def test_fannkuch(self):
src = open(path_from_root('tests', 'fannkuch.cpp'), 'r').read().replace(
'int n = argc > 1 ? atoi(argv[1]) : 0;',
diff --git a/tests/test_browser.py b/tests/test_browser.py
index c06f11ac..c8e07b25 100644
--- a/tests/test_browser.py
+++ b/tests/test_browser.py
@@ -1300,7 +1300,7 @@ keydown(100);keyup(100); // trigger the end
time.sleep(2)
def test_glgears(self):
- self.btest('hello_world_gles.c', reference='gears.png', reference_slack=1,
+ self.btest('hello_world_gles.c', reference='gears.png', reference_slack=2,
args=['-DHAVE_BUILTIN_SINCOS'], outfile='something.html',
message='You should see animating gears.')
@@ -1322,7 +1322,7 @@ keydown(100);keyup(100); // trigger the end
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.btest('hello_world_gles_deriv.c', reference='gears.png', reference_slack=1,
+ self.btest('hello_world_gles_deriv.c', reference='gears.png', reference_slack=2,
args=['-DHAVE_BUILTIN_SINCOS'], outfile='something.html',
message='You should see animating gears.')
with open('something.html') as f:
@@ -1425,6 +1425,9 @@ keydown(100);keyup(100); // trigger the end
def test_sdlglshader(self):
self.btest('sdlglshader.c', reference='sdlglshader.png', args=['-O2', '--closure', '1', '-s', 'LEGACY_GL_EMULATION=1'])
+ def test_gl_glteximage(self):
+ self.btest('gl_teximage.c', '1')
+
def test_gl_ps(self):
# pointers and a shader
shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
@@ -1553,7 +1556,7 @@ void *getBindBuffer() {
def test_sdl_rotozoom(self):
shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
- self.btest('sdl_rotozoom.c', reference='sdl_rotozoom.png', args=['--preload-file', 'screenshot.png'])
+ self.btest('sdl_rotozoom.c', reference='sdl_rotozoom.png', args=['--preload-file', 'screenshot.png'], reference_slack=3)
def test_sdl_gfx_primitives(self):
self.btest('sdl_gfx_primitives.c', reference='sdl_gfx_primitives.png', reference_slack=1)
diff --git a/tests/test_core.py b/tests/test_core.py
index ab4897f8..b9057f4e 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -425,6 +425,11 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
self.do_run_from_file(src, output, 'waka fleefl asdfasdfasdfasdf'.split(' '))
+ def test_double_varargs(self):
+ test_path = path_from_root('tests', 'core', 'test_double_varargs')
+ src, output = (test_path + s for s in ('.c', '.out'))
+ self.do_run_from_file(src, output)
+
def test_i32_mul_precise(self):
if self.emcc_args == None: return self.skip('needs ta2')
@@ -519,47 +524,25 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
def test_cube2hash(self):
# extra testing for various codegen modes
- for x86 in [0, 1] if self.run_name == 'asm2' else [0]:
- print 'x86', x86
- try:
- old_x86 = os.environ.get('EMCC_LLVM_TARGET') or ''
- if x86:
- os.environ['EMCC_LLVM_TARGET'] = "i386-pc-linux-gnu"
- try:
- old_fastcomp = os.environ.get('EMCC_FAST_COMPILER') or ''
- if x86:
- os.environ['EMCC_FAST_COMPILER'] = "0"
- try:
- old_chunk_size = os.environ.get('EMSCRIPT_MAX_CHUNK_SIZE') or ''
-
- for chunk_size in ['1', old_chunk_size]: # test splitting out each function to a chunk in emscripten.py (21 functions here)
- print ' chunks', chunk_size
- os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = chunk_size
-
- # A good test of i64 math
- if Settings.USE_TYPED_ARRAYS != 2: return self.skip('requires ta2 C-style memory aliasing')
- self.do_run('', 'Usage: hashstring <seed>',
- libraries=self.get_library('cube2hash', ['cube2hash.bc'], configure=None, cache_name_extra=str(x86)),
- includes=[path_from_root('tests', 'cube2hash')])
-
- for text, output in [('fleefl', '892BDB6FD3F62E863D63DA55851700FDE3ACF30204798CE9'),
- ('fleefl2', 'AA2CC5F96FC9D540CA24FDAF1F71E2942753DB83E8A81B61'),
- ('64bitisslow', '64D8470573635EC354FEE7B7F87C566FCAF1EFB491041670')]:
- self.do_run('', 'hash value: ' + output, [text], no_build=True)
- finally:
- os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = old_chunk_size
- finally:
- if x86:
- if old_fastcomp:
- os.environ['EMCC_FAST_COMPILER'] = old_fastcomp
- else:
- del os.environ['EMCC_FAST_COMPILER']
- finally:
- if x86:
- if old_x86:
- os.environ['EMCC_LLVM_TARGET'] = old_x86
- else:
- del os.environ['EMCC_LLVM_TARGET']
+ try:
+ old_chunk_size = os.environ.get('EMSCRIPT_MAX_CHUNK_SIZE') or ''
+
+ for chunk_size in ['1', old_chunk_size]: # test splitting out each function to a chunk in emscripten.py (21 functions here)
+ print ' chunks', chunk_size
+ os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = chunk_size
+
+ # A good test of i64 math
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('requires ta2 C-style memory aliasing')
+ self.do_run('', 'Usage: hashstring <seed>',
+ libraries=self.get_library('cube2hash', ['cube2hash.bc'], configure=None),
+ includes=[path_from_root('tests', 'cube2hash')])
+
+ for text, output in [('fleefl', '892BDB6FD3F62E863D63DA55851700FDE3ACF30204798CE9'),
+ ('fleefl2', 'AA2CC5F96FC9D540CA24FDAF1F71E2942753DB83E8A81B61'),
+ ('64bitisslow', '64D8470573635EC354FEE7B7F87C566FCAF1EFB491041670')]:
+ self.do_run('', 'hash value: ' + output, [text], no_build=True)
+ finally:
+ os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = old_chunk_size
def test_unaligned(self):
if Settings.QUANTUM_SIZE == 1: return self.skip('No meaning to unaligned addresses in q1')
@@ -792,6 +775,8 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
self.do_run_from_file(src, output)
def test_floatvars(self):
+ if self.run_name == 'slow2asm': return self.skip('FIXME in slow2asm')
+
test_path = path_from_root('tests', 'core', 'test_floatvars')
src, output = (test_path + s for s in ('.in', '.out'))
@@ -865,6 +850,7 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
self.do_run_from_file(src, output)
def test_frexp(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sprintf.')
test_path = path_from_root('tests', 'core', 'test_frexp')
src, output = (test_path + s for s in ('.in', '.out'))
@@ -966,6 +952,7 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
self.do_run_from_file(src, output)
def test_strings(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sscanf.')
test_path = path_from_root('tests', 'core', 'test_strings')
src, output = (test_path + s for s in ('.in', '.out'))
@@ -1160,7 +1147,6 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
self.do_run_from_file(src, output)
def test_longjmp_repeat(self):
- if os.environ.get('EMCC_FAST_COMPILER') == '0': Settings.MAX_SETJMPS = 1 # todo: do this more strict thing in fastcomp too
test_path = path_from_root('tests', 'core', 'test_longjmp_repeat')
src, output = (test_path + s for s in ('.in', '.out'))
self.do_run_from_file(src, output)
@@ -1184,8 +1170,6 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
self.do_run_from_file(src, output)
def test_setjmp_many(self):
- if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp: make MAX_SETJMPS take effect')
-
src = r'''
#include <stdio.h>
#include <setjmp.h>
@@ -1197,9 +1181,42 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
return 0;
}
'''
- for num in [Settings.MAX_SETJMPS, Settings.MAX_SETJMPS+1]:
- print num
- self.do_run(src.replace('NUM', str(num)), '0\n' * num if num <= Settings.MAX_SETJMPS or not Settings.ASM_JS else 'build with a higher value for MAX_SETJMPS')
+ for maxx in [Settings.MAX_SETJMPS/2, Settings.MAX_SETJMPS, 2*Settings.MAX_SETJMPS]:
+ Settings.MAX_SETJMPS = maxx
+ for num in [maxx, maxx+1]:
+ print maxx, num
+ self.do_run(src.replace('NUM', str(num)), '0\n' * num if num <= Settings.MAX_SETJMPS or not Settings.ASM_JS else 'build with a higher value for MAX_SETJMPS')
+
+ def test_setjmp_many_2(self):
+ if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('non-fastcomp do not hit the limit.')
+
+ src = r'''
+#include <setjmp.h>
+#include <stdio.h>
+
+jmp_buf env;
+
+void luaWork(int d){
+ int x;
+ printf("d is at %d\n", d);
+
+ longjmp(env, 1);
+}
+
+int main()
+{
+ const int ITERATIONS=25;
+ for(int i = 0; i < ITERATIONS; i++){
+ if(!setjmp(env)){
+ luaWork(i);
+ }
+ }
+ return 0;
+}
+'''
+
+ self.do_run(src, r'''d is at 19
+too many setjmps in a function call, build with a higher value for MAX_SETJMPS''')
def test_exceptions(self):
if Settings.QUANTUM_SIZE == 1: return self.skip("we don't support libcxx in q1")
@@ -1311,6 +1328,33 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
test_path = path_from_root('tests', 'core', 'test_exceptions_white_list')
src, output = (test_path + s for s in ('.in', '.out'))
self.do_run_from_file(src, output)
+ size = len(open('src.cpp.o.js').read())
+ shutil.copyfile('src.cpp.o.js', 'orig.js')
+
+ if os.environ.get('EMCC_FAST_COMPILER') != '0':
+ # check that an empty whitelist works properly (as in, same as exceptions disabled)
+ empty_output = path_from_root('tests', 'core', 'test_exceptions_white_list_empty.out')
+
+ Settings.EXCEPTION_CATCHING_WHITELIST = []
+ self.do_run_from_file(src, empty_output)
+ empty_size = len(open('src.cpp.o.js').read())
+ shutil.copyfile('src.cpp.o.js', 'empty.js')
+
+ Settings.EXCEPTION_CATCHING_WHITELIST = ['fake']
+ self.do_run_from_file(src, empty_output)
+ fake_size = len(open('src.cpp.o.js').read())
+ shutil.copyfile('src.cpp.o.js', 'fake.js')
+
+ Settings.DISABLE_EXCEPTION_CATCHING = 1
+ self.do_run_from_file(src, empty_output)
+ disabled_size = len(open('src.cpp.o.js').read())
+ shutil.copyfile('src.cpp.o.js', 'disabled.js')
+
+ assert size - empty_size > 2000, [empty_size, size] # big change when we disable entirely
+ assert size - fake_size > 2000, [fake_size, size]
+ assert empty_size == fake_size, [empty_size, fake_size]
+ assert empty_size - disabled_size < 100, [empty_size, disabled_size] # full disable removes a tiny bit more
+ assert fake_size - disabled_size < 100, [disabled_size, fake_size]
def test_exceptions_white_list_2(self):
Settings.DISABLE_EXCEPTION_CATCHING = 2
@@ -1917,6 +1961,15 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
self.do_run_from_file(src, output)
+ def test_set_align(self):
+ if self.run_name == 'slow2asm': return self.skip('FIXME in slow2asm')
+
+ Settings.SAFE_HEAP = 1
+
+ test_path = path_from_root('tests', 'core', 'test_set_align')
+ src, output = (test_path + s for s in ('.c', '.out'))
+ self.do_run_from_file(src, output)
+
def test_emscripten_api(self):
#if Settings.MICRO_OPTS or Settings.RELOOP or Building.LLVM_OPTS: return self.skip('FIXME')
@@ -2032,10 +2085,10 @@ def process(filename):
if self.emcc_args and '-O2' in self.emcc_args:
# Make sure ALLOW_MEMORY_GROWTH generates different code (should be less optimized)
- code_start = 'var TOTAL_MEMORY = '
+ code_start = 'var TOTAL_MEMORY'
fail = fail[fail.find(code_start):]
win = win[win.find(code_start):]
- assert len(fail) < len(win), 'failing code - without memory growth on - is more optimized, and smaller'
+ assert len(fail) < len(win), 'failing code - without memory growth on - is more optimized, and smaller' + str([len(fail), len(win)])
def test_ssr(self): # struct self-ref
src = '''
@@ -2152,6 +2205,7 @@ def process(filename):
self.do_run(src, '*4,3,4*\n*6,4,6*')
def test_varargs(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sprintf.')
if Settings.QUANTUM_SIZE == 1: return self.skip('FIXME: Add support for this')
if not self.is_emscripten_abi(): return self.skip('we do not support all varargs stuff without asmjs-unknown-emscripten')
@@ -2461,6 +2515,7 @@ The current type of b is: 9
self.do_run_from_file(src, output)
def test_strtol_hex(self):
+ if self.run_name.startswith('s_'): return self.skip('Needs musl libc.')
# tests strtoll for hex strings (0x...)
test_path = path_from_root('tests', 'core', 'test_strtol_hex')
src, output = (test_path + s for s in ('.in', '.out'))
@@ -2468,6 +2523,7 @@ The current type of b is: 9
self.do_run_from_file(src, output)
def test_strtol_dec(self):
+ if self.run_name.startswith('s_'): return self.skip('Needs musl libc.')
# tests strtoll for decimal strings (0x...)
test_path = path_from_root('tests', 'core', 'test_strtol_dec')
src, output = (test_path + s for s in ('.in', '.out'))
@@ -2475,6 +2531,7 @@ The current type of b is: 9
self.do_run_from_file(src, output)
def test_strtol_bin(self):
+ if self.run_name.startswith('s_'): return self.skip('Needs musl libc.')
# tests strtoll for binary strings (0x...)
test_path = path_from_root('tests', 'core', 'test_strtol_bin')
src, output = (test_path + s for s in ('.in', '.out'))
@@ -2482,6 +2539,7 @@ The current type of b is: 9
self.do_run_from_file(src, output)
def test_strtol_oct(self):
+ if self.run_name.startswith('s_'): return self.skip('Needs musl libc.')
# tests strtoll for decimal strings (0x...)
test_path = path_from_root('tests', 'core', 'test_strtol_oct')
src, output = (test_path + s for s in ('.in', '.out'))
@@ -3204,7 +3262,7 @@ def process(filename):
break
else:
raise Exception('Could not find symbol table!')
- table = table[table.find('{'):table.rfind('}')+1]
+ table = table[table.find('{'):table.find('}')+1]
# ensure there aren't too many globals; we don't want unnamed_addr
assert table.count(',') <= 4
@@ -3258,6 +3316,7 @@ def process(filename):
self.do_run(src, 'success', force_c=True, post_build=self.dlfcn_post_build)
def test_dlfcn_stacks(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('snprintf needs ta2 to be able to bitcast int<->float')
if not self.can_dlfcn(): return
self.prep_dlfcn_lib()
@@ -3713,6 +3772,7 @@ int main()
self.do_run(src, expected)
def test_transtrcase(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('musl libc needs ta2')
test_path = path_from_root('tests', 'core', 'test_transtrcase')
src, output = (test_path + s for s in ('.in', '.out'))
@@ -3747,6 +3807,7 @@ int main()
self.do_run_from_file(src, output)
def test_printf_more(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sprintf.')
test_path = path_from_root('tests', 'core', 'test_printf_more')
src, output = (test_path + s for s in ('.in', '.out'))
@@ -3845,18 +3906,21 @@ Pass: 0.000012 0.000012
Pass: 0.000012 0.000012''')
def test_sscanf_n(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sscanf.')
test_path = path_from_root('tests', 'core', 'test_sscanf_n')
src, output = (test_path + s for s in ('.in', '.out'))
self.do_run_from_file(src, output)
def test_sscanf_whitespace(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sscanf.')
test_path = path_from_root('tests', 'core', 'test_sscanf_whitespace')
src, output = (test_path + s for s in ('.in', '.out'))
self.do_run_from_file(src, output)
def test_sscanf_other_whitespace(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sscanf.')
Settings.SAFE_HEAP = 0 # use i16s in printf
test_path = path_from_root('tests', 'core', 'test_sscanf_other_whitespace')
@@ -3865,6 +3929,7 @@ Pass: 0.000012 0.000012''')
self.do_run_from_file(src, output)
def test_sscanf_3(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sscanf.')
# i64
if not Settings.USE_TYPED_ARRAYS == 2: return self.skip('64-bit sscanf only supported in ta2')
@@ -3874,23 +3939,27 @@ Pass: 0.000012 0.000012''')
self.do_run_from_file(src, output)
def test_sscanf_4(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sscanf.')
test_path = path_from_root('tests', 'core', 'test_sscanf_4')
src, output = (test_path + s for s in ('.in', '.out'))
self.do_run_from_file(src, output)
def test_sscanf_5(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sscanf.')
test_path = path_from_root('tests', 'core', 'test_sscanf_5')
src, output = (test_path + s for s in ('.in', '.out'))
self.do_run_from_file(src, output)
def test_sscanf_6(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sscanf.')
test_path = path_from_root('tests', 'core', 'test_sscanf_6')
src, output = (test_path + s for s in ('.in', '.out'))
self.do_run_from_file(src, output)
def test_sscanf_skip(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sscanf.')
if Settings.USE_TYPED_ARRAYS != 2: return self.skip("need ta2 for full i64")
test_path = path_from_root('tests', 'core', 'test_sscanf_skip')
@@ -3899,18 +3968,23 @@ Pass: 0.000012 0.000012''')
self.do_run_from_file(src, output)
def test_sscanf_caps(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sscanf.')
test_path = path_from_root('tests', 'core', 'test_sscanf_caps')
src, output = (test_path + s for s in ('.in', '.out'))
self.do_run_from_file(src, output)
def test_sscanf_hex(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sscanf.')
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('requires ta2')
+
test_path = path_from_root('tests', 'core', 'test_sscanf_hex')
src, output = (test_path + s for s in ('.in', '.out'))
self.do_run_from_file(src, output)
def test_sscanf_float(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sscanf.')
test_path = path_from_root('tests', 'core', 'test_sscanf_float')
src, output = (test_path + s for s in ('.in', '.out'))
@@ -3922,6 +3996,7 @@ Pass: 0.000012 0.000012''')
self.do_run(src, expected, extra_emscripten_args=['-H', 'libc/langinfo.h'])
def test_files(self):
+ if self.run_name.startswith('s_'): return self.skip('This test requires linking to musl lib for sscanf.')
self.banned_js_engines = [SPIDERMONKEY_ENGINE] # closure can generate variables called 'gc', which pick up js shell stuff
if self.emcc_args is not None and '-O2' in self.emcc_args:
self.emcc_args += ['--closure', '1'] # Use closure here, to test we don't break FS stuff
@@ -4252,6 +4327,18 @@ def process(filename):
src = open(path_from_root('tests', 'fs', 'test_nodefs_rw.c'), 'r').read()
self.do_run(src, 'success', force_c=True, js_engines=[NODE_JS])
+ def test_fs_trackingdelegate(self):
+ src = path_from_root('tests', 'fs', 'test_trackingdelegate.c')
+ out = path_from_root('tests', 'fs', 'test_trackingdelegate.out')
+ self.do_run_from_file(src, out)
+
+ def test_fs_writeFile(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+ self.emcc_args += ['-s', 'DISABLE_EXCEPTION_CATCHING=1'] # see issue 2334
+ src = path_from_root('tests', 'fs', 'test_writeFile.cc')
+ out = path_from_root('tests', 'fs', 'test_writeFile.out')
+ self.do_run_from_file(src, out)
+
def test_unistd_access(self):
self.clear()
if not self.is_emscripten_abi(): return self.skip('asmjs-unknown-emscripten needed for inline js')
@@ -4594,6 +4681,7 @@ int main(void) {
### 'Medium' tests
def test_fannkuch(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('musl libc needs ta2')
try:
if self.run_name == 'slow2' or self.run_name == 'slow2asm':
old_target = os.environ.get('EMCC_LLVM_TARGET') or ''
@@ -4638,8 +4726,7 @@ int main(void) {
if self.emcc_args is None: self.emcc_args = [] # dlmalloc auto-inclusion is only done if we use emcc
self.banned_js_engines = [NODE_JS] # slower, and fail on 64-bit
- Settings.CORRECT_SIGNS = 2
- Settings.CORRECT_SIGNS_LINES = ['src.cpp:' + str(i+4) for i in [4816, 4191, 4246, 4199, 4205, 4235, 4227]]
+ Settings.CORRECT_SIGNS = 1
Settings.TOTAL_MEMORY = 128*1024*1024 # needed with typed arrays
src = open(path_from_root('system', 'lib', 'dlmalloc.c'), 'r').read() + '\n\n\n' + open(path_from_root('tests', 'dlmalloc_test.c'), 'r').read()
@@ -4805,6 +4892,15 @@ return malloc(size);
self.do_run_from_file(src, output)
+ def test_simd4(self):
+ # test_simd4 is to test phi node handling of SIMD path
+ if Settings.ASM_JS: Settings.ASM_JS = 2 # does not validate
+
+ test_path = path_from_root('tests', 'core', 'test_simd4')
+ src, output = (test_path + s for s in ('.in', '.out'))
+
+ self.do_run_from_file(src, output)
+
def test_gcc_unmangler(self):
if os.environ.get('EMCC_FAST_COMPILER') == '0': Settings.NAMED_GLOBALS = 1 # test coverage for this; fastcomp never names globals
@@ -4920,6 +5016,8 @@ def process(filename):
print "disabling inlining" # without registerize (which -g disables), we generate huge amounts of code
Settings.INLINING_LIMIT = 50
+ #Settings.OUTLINING_LIMIT = 60000
+
self.do_run(r'''
#define SQLITE_DISABLE_LFS
#define LONGDOUBLE_TYPE double
@@ -5207,8 +5305,10 @@ def process(filename):
emcc_args = self.emcc_args
+ # The following tests link to libc, and must be run with EMCC_LEAVE_INPUTS_RAW = 0
+ need_no_leave_inputs_raw = ['muli33_ta2', 'philoop_ta2']
+
try:
- os.environ['EMCC_LEAVE_INPUTS_RAW'] = '1'
Settings.CHECK_OVERFLOWS = 0
for name in glob.glob(path_from_root('tests', 'cases', '*.ll')):
@@ -5222,6 +5322,15 @@ def process(filename):
'atomicrmw_unaligned', # TODO XXX
'emptyasm_aue' # we don't support inline asm
]: continue
+
+ if os.path.basename(shortname) in need_no_leave_inputs_raw:
+ if self.run_name.startswith('s_'):
+ print self.skip('case "%s" cannot be run in mode %s, since it would require EMCC_LEAVE_INPUTS_RAW=1' % (shortname, self.run_name))
+ continue
+ if 'EMCC_LEAVE_INPUTS_RAW' in os.environ: del os.environ['EMCC_LEAVE_INPUTS_RAW']
+ else:
+ os.environ['EMCC_LEAVE_INPUTS_RAW'] = '1'
+
if '_ta2' in shortname and not Settings.USE_TYPED_ARRAYS == 2:
print self.skip('case "%s" only relevant for ta2' % shortname)
continue
@@ -5257,7 +5366,7 @@ def process(filename):
exec(open(src_checker).read())
finally:
- del os.environ['EMCC_LEAVE_INPUTS_RAW']
+ if 'EMCC_LEAVE_INPUTS_RAW' in os.environ: del os.environ['EMCC_LEAVE_INPUTS_RAW']
self.emcc_args = emcc_args
def test_fuzz(self):
@@ -5271,9 +5380,11 @@ def process(filename):
#if os.path.basename(name) != '4.c': continue
if 'newfail' in name: continue
if os.environ.get('EMCC_FAST_COMPILER') == '0' and os.path.basename(name) in [
- '18.cpp', '15.c'
- ]:
- continue # works only in fastcomp
+ '18.cpp', '15.c', '21.c'
+ ]: continue # works only in fastcomp
+ if x == 'lto' and self.run_name == 'default' and os.path.basename(name) in [
+ '19.c'
+ ]: continue # LLVM LTO bug
print name
self.do_run(open(path_from_root('tests', 'fuzz', name)).read(),
@@ -5394,9 +5505,6 @@ def process(filename):
### Integration tests
def test_ccall(self):
- if self.emcc_args is not None and '-O2' in self.emcc_args:
- self.emcc_args += ['--closure', '1'] # Use closure here, to test we export things right
-
post = '''
def process(filename):
src = \'\'\'
@@ -5440,6 +5548,11 @@ def process(filename):
self.do_run_from_file(src, output, post_build=post)
+ if self.emcc_args is not None and '-O2' in self.emcc_args:
+ print 'with closure'
+ self.emcc_args += ['--closure', '1']
+ self.do_run_from_file(src, output, post_build=post)
+
def test_pgo(self):
if Settings.ASM_JS: return self.skip('PGO does not work in asm mode')
@@ -5633,7 +5746,6 @@ def process(filename):
def test_embind(self):
if self.emcc_args is None: return self.skip('requires emcc')
- if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp')
Building.COMPILER_TEST_OPTS += ['--bind']
src = r'''
@@ -5656,7 +5768,7 @@ def process(filename):
def test_embind_2(self):
if self.emcc_args is None: return self.skip('requires emcc')
- if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp')
+ if self.run_name == 'slow2asm': return self.skip('embind/asm.js requires fastcomp')
Building.COMPILER_TEST_OPTS += ['--bind', '--post-js', 'post.js']
open('post.js', 'w').write('''
Module.print('lerp ' + Module.lerp(1, 2, 0.66) + '.');
@@ -5969,6 +6081,22 @@ def process(filename):
'''
self.do_run(src, '|hello|43|world|41|', post_build=post)
+ def test_webidl(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+
+ output = Popen([PYTHON, path_from_root('tools', 'webidl_binder.py'),
+ path_from_root('tests', 'webidl', 'test.idl'),
+ 'glue']).communicate()[0]
+ assert os.path.exists('glue.cpp')
+ assert os.path.exists('glue.js')
+
+ self.emcc_args += ['--post-js', 'glue.js',
+ '--post-js', path_from_root('tests', 'webidl', 'post.js')]
+ shutil.copyfile(path_from_root('tests', 'webidl', 'test.h'), self.in_dir('test.h'))
+ shutil.copyfile(path_from_root('tests', 'webidl', 'test.cpp'), self.in_dir('test.cpp'))
+ src = open('test.cpp').read()
+ self.do_run(src, open(path_from_root('tests', 'webidl', 'output.txt')).read())
+
def test_typeinfo(self):
if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('fastcomp does not support RUNTIME_TYPE_INFO')
@@ -6497,6 +6625,28 @@ def process(filename):
if self.emcc_args is None: return self.skip('needs emcc')
self.do_run_from_file(path_from_root('tests', 'test_locale.c'), path_from_root('tests', 'test_locale.out'))
+ def test_64bit_return_value(self):
+ # This test checks that the most significant 32 bits of a 64 bit long are correctly made available
+ # to native JavaScript applications that wish to interact with compiled code returning 64 bit longs.
+ # The MS 32 bits should be available in Runtime.getTempRet0() even when compiled with -O2 --closure 1
+ # Run with ./runner.py test_64bit_return_value
+
+ # Compile test.c and wrap it in a native JavaScript binding so we can call our compiled function from JS.
+ Popen([PYTHON, EMCC, path_from_root('tests', 'return64bit', 'test.c'), '--pre-js', path_from_root('tests', 'return64bit', 'testbindstart.js'), '--pre-js', path_from_root('tests', 'return64bit', 'testbind.js'), '--post-js', path_from_root('tests', 'return64bit', 'testbindend.js'), '-s', 'EXPORTED_FUNCTIONS=["_test"]', '-o', 'test.js', '-O2', '--closure', '1'], stdout=PIPE, stderr=PIPE).communicate()
+
+ # Simple test program to load the test.js binding library and call the binding to the
+ # C function returning the 64 bit long.
+ open(os.path.join(self.get_dir(), 'testrun.js'), 'w').write('''
+ var test = require("./test.js");
+ test.runtest();
+ ''')
+
+ # Run the test and confirm the output is as expected.
+ if NODE_JS in JS_ENGINES:
+ out = run_js('testrun.js', engine=NODE_JS, full_output=True)
+ assert "low = 5678" in out
+ assert "high = 1234" in out
+
# Generate tests for everything
def make_run(fullname, name=-1, compiler=-1, embetter=0, quantum_size=0,
typed_arrays=0, emcc_args=None, env=None):
diff --git a/tests/test_interactive.py b/tests/test_interactive.py
index aa1d96af..7c968f78 100644
--- a/tests/test_interactive.py
+++ b/tests/test_interactive.py
@@ -59,12 +59,6 @@ class interactive(BrowserCore):
Popen([PYTHON, EMCC, '-O2', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio_mix.c'), '--preload-file', 'sound.ogg', '--preload-file', 'music.ogg', '--preload-file', 'noise.ogg', '-o', 'page.html']).communicate()
self.run_browser('page.html', '', '/report_result?1')
- def test_sdl_audio_quickload(self):
- open(os.path.join(self.get_dir(), 'sdl_audio_quickload.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_audio_quickload.c')).read()))
-
- Popen([PYTHON, EMCC, '-O2', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio_quickload.c'), '-o', 'page.html', '-s', 'EXPORTED_FUNCTIONS=["_main", "_play"]']).communicate()
- self.run_browser('page.html', '', '/report_result?1')
-
def test_sdl_audio_beeps(self):
open(os.path.join(self.get_dir(), 'sdl_audio_beep.cpp'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_audio_beep.cpp')).read()))
diff --git a/tests/test_other.py b/tests/test_other.py
index cdea493a..39796b71 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -203,6 +203,12 @@ Options that are modified or new in %s include:
(['--typed-arrays', '1'], lambda generated: 'IHEAPU = ' in generated, 'typed arrays 1 selected'),
(['--typed-arrays', '2'], lambda generated: 'new Uint16Array' in generated and 'new Uint32Array' in generated, 'typed arrays 2 selected'),
(['--llvm-opts', '1'], lambda generated: '_puts(' in generated, 'llvm opts requested'),
+ ([], lambda generated: '// The Module object' in generated, 'without opts, comments in shell code'),
+ (['-O2'], lambda generated: '// The Module object' not in generated, 'with opts, no comments in shell code'),
+ (['-O2', '-g2'], lambda generated: '// The Module object' not in generated, 'with -g2, no comments in shell code'),
+ (['-O2', '-g3'], lambda generated: '// The Module object' in generated, 'with -g3, yes comments in shell code'),
+ (['-O2', '-profiling'], lambda generated: '// The Module object' in generated or os.environ.get('EMCC_FAST_COMPILER') == '0', 'with -profiling, yes comments in shell code (in fastcomp)'),
+
]:
print params, text
self.clear()
@@ -349,9 +355,10 @@ f.close()
except KeyError:
postbuild = None
- cmake_cases = ['target_js', 'target_html']
- cmake_outputs = ['test_cmake.js', 'hello_world_gles.html']
- for i in range(0, 2):
+ cmake_cases = ['target_js', 'target_html', 'target_library', 'target_library']
+ cmake_outputs = ['test_cmake.js', 'hello_world_gles.html', 'libtest_cmake.a', 'libtest_cmake.so']
+ cmake_arguments = ['', '', '-DBUILD_SHARED_LIBS=OFF', '-DBUILD_SHARED_LIBS=ON']
+ for i in range(0, len(cmake_cases)):
for configuration in ['Debug', 'Release']:
# CMake can be invoked in two ways, using 'emconfigure cmake', or by directly running 'cmake'.
# Test both methods.
@@ -369,11 +376,11 @@ f.close()
if invoke_method == 'cmake':
# Test invoking cmake directly.
cmd = ['cmake', '-DCMAKE_TOOLCHAIN_FILE='+path_from_root('cmake', 'Platform', 'Emscripten.cmake'),
- '-DCMAKE_BUILD_TYPE=' + configuration, '-G', generator, cmakelistsdir]
+ '-DCMAKE_BUILD_TYPE=' + configuration, cmake_arguments[i], '-G', generator, cmakelistsdir]
else:
# Test invoking via 'emconfigure cmake'
- cmd = [emconfigure, 'cmake', '-DCMAKE_BUILD_TYPE=' + configuration, '-G', generator, cmakelistsdir]
-
+ cmd = [emconfigure, 'cmake', '-DCMAKE_BUILD_TYPE=' + configuration, cmake_arguments[i], '-G', generator, cmakelistsdir]
+
ret = Popen(cmd, stdout=None if verbose_level >= 2 else PIPE, stderr=None if verbose_level >= 1 else PIPE).communicate()
if len(ret) > 1 and ret[1] != None and len(ret[1].strip()) > 0:
logging.error(ret[1]) # If there were any errors, print them directly to console for diagnostics.
@@ -1027,10 +1034,93 @@ This pointer might make sense in another type signature: i: 0
Building.emar('cr', lib_name, [a_name + '.o', b_name + '.o']) # libLIB.a with a and b
# a is in the lib AND in an .o, so should be ignored in the lib. We do still need b from the lib though
- Building.emcc(main_name, ['-L.', '-lLIB', a_name+'.o', c_name + '.o'], output_filename='a.out.js')
+ Building.emcc(main_name, [a_name+'.o', c_name + '.o', '-L.', '-lLIB'], output_filename='a.out.js')
self.assertContained('result: 62', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ def test_link_group_asserts(self):
+ lib_src_name = os.path.join(self.get_dir(), 'lib.c')
+ open(lib_src_name, 'w').write('int x() { return 42; }')
+
+ main_name = os.path.join(self.get_dir(), 'main.c')
+ open(main_name, 'w').write(r'''
+ #include <stdio.h>
+ int x();
+ int main() {
+ printf("result: %d\n", x());
+ return 0;
+ }
+ ''')
+
+ Building.emcc(lib_src_name) # lib.c.o
+ lib_name = os.path.join(self.get_dir(), 'libLIB.a')
+ Building.emar('cr', lib_name, [lib_src_name + '.o']) # libLIB.a with lib.c.o
+
+ def test(lib_args, err_expected):
+ output = Popen([PYTHON, EMCC, main_name, '-o', 'a.out.js'] + lib_args, stdout=PIPE, stderr=PIPE).communicate()
+ if err_expected:
+ self.assertContained(err_expected, output[1])
+ else:
+ out_js = os.path.join(self.get_dir(), 'a.out.js')
+ assert os.path.exists(out_js), '\n'.join(output)
+ self.assertContained('result: 42', run_js(out_js))
+
+ test(['-Wl,--start-group', lib_name], '--start-group without matching --end-group')
+ test(['-Wl,--start-group', lib_name, '-Wl,--start-group'], 'Nested --start-group, missing --end-group?')
+ test(['-Wl,--end-group', lib_name, '-Wl,--start-group'], '--end-group without --start-group')
+ test(['-Wl,--start-group', lib_name, '-Wl,--end-group'], None)
+
+ def test_circular_libs(self):
+ def tmp_source(name, code):
+ file_name = os.path.join(self.get_dir(), name)
+ open(file_name, 'w').write(code)
+ return file_name
+
+ a = tmp_source('a.c', 'int z(); int x() { return z(); }')
+ b = tmp_source('b.c', 'int x(); int y() { return x(); } int z() { return 42; }')
+ c = tmp_source('c.c', 'int q() { return 0; }')
+ main = tmp_source('main.c', r'''
+ #include <stdio.h>
+ int y();
+ int main() {
+ printf("result: %d\n", y());
+ return 0;
+ }
+ ''')
+
+ Building.emcc(a) # a.c.o
+ Building.emcc(b) # b.c.o
+ Building.emcc(c) # c.c.o
+ lib_a = os.path.join(self.get_dir(), 'libA.a')
+ Building.emar('cr', lib_a, [a + '.o', c + '.o']) # libA.a with a.c.o,c.c.o
+ lib_b = os.path.join(self.get_dir(), 'libB.a')
+ Building.emar('cr', lib_b, [b + '.o', c + '.o']) # libB.a with b.c.o,c.c.o
+
+ args = ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1', main, '-o', 'a.out.js']
+ libs_list = [lib_a, lib_b]
+
+ # lib_a does not satisfy any symbols from main, so it will not be included,
+ # and there will be an unresolved symbol.
+ output = Popen([PYTHON, EMCC] + args + libs_list, stdout=PIPE, stderr=PIPE).communicate()
+ self.assertContained('error: unresolved symbol: x', output[1])
+
+ # -Wl,--start-group and -Wl,--end-group around the libs will cause a rescan
+ # of lib_a after lib_b adds undefined symbol "x", so a.c.o will now be
+ # included (and the link will succeed).
+ libs = ['-Wl,--start-group'] + libs_list + ['-Wl,--end-group']
+ output = Popen([PYTHON, EMCC] + args + libs, stdout=PIPE, stderr=PIPE).communicate()
+ out_js = os.path.join(self.get_dir(), 'a.out.js')
+ assert os.path.exists(out_js), '\n'.join(output)
+ self.assertContained('result: 42', run_js(out_js))
+
+ # -( and -) should also work.
+ args = ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1', main, '-o', 'a2.out.js']
+ libs = ['-Wl,-('] + libs_list + ['-Wl,-)']
+ output = Popen([PYTHON, EMCC] + args + libs, stdout=PIPE, stderr=PIPE).communicate()
+ out_js = os.path.join(self.get_dir(), 'a2.out.js')
+ assert os.path.exists(out_js), '\n'.join(output)
+ self.assertContained('result: 42', run_js(out_js))
+
def test_redundant_link(self):
lib = "int mult() { return 1; }"
lib_name = os.path.join(self.get_dir(), 'libA.c')
@@ -1879,25 +1969,20 @@ This pointer might make sense in another type signature: i: 0
assert 'If you see this - the world is all right!' in output
def test_embind(self):
- def nonfc():
- if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp')
- for args, fail in [
- ([], True), # without --bind, we fail
- (['--bind'], False),
- (['--bind', '-O1'], False),
- (['--bind', '-O2'], False),
- (['--bind', '-O1', '-s', 'ASM_JS=0'], False),
- (['--bind', '-O2', '-s', 'ASM_JS=0'], False)
- ]:
- print args, fail
- self.clear()
- try_delete(self.in_dir('a.out.js'))
- Popen([PYTHON, EMCC, path_from_root('tests', 'embind', 'embind_test.cpp'), '--post-js', path_from_root('tests', 'embind', 'underscore-1.4.2.js'), '--post-js', path_from_root('tests', 'embind', 'imvu_test_adapter.js'), '--post-js', path_from_root('tests', 'embind', 'embind.test.js')] + args, stderr=PIPE if fail else None).communicate()
- assert os.path.exists(self.in_dir('a.out.js')) == (not fail)
- if not fail:
- output = run_js(self.in_dir('a.out.js'), stdout=PIPE, stderr=PIPE, full_output=True)
- assert "FAIL" not in output, output
- nonfastcomp(nonfc)
+ for args, fail in [
+ ([], True), # without --bind, we fail
+ (['--bind'], False),
+ (['--bind', '-O1'], False),
+ (['--bind', '-O2'], False),
+ ]:
+ print args, fail
+ self.clear()
+ try_delete(self.in_dir('a.out.js'))
+ Popen([PYTHON, EMCC, path_from_root('tests', 'embind', 'embind_test.cpp'), '--post-js', path_from_root('tests', 'embind', 'underscore-1.4.2.js'), '--post-js', path_from_root('tests', 'embind', 'imvu_test_adapter.js'), '--post-js', path_from_root('tests', 'embind', 'embind.test.js')] + args, stderr=PIPE if fail else None).communicate()
+ assert os.path.exists(self.in_dir('a.out.js')) == (not fail)
+ if not fail:
+ output = run_js(self.in_dir('a.out.js'), stdout=PIPE, stderr=PIPE, full_output=True, assert_returncode=0)
+ assert "FAIL" not in output, output
def test_llvm_nativizer(self):
try:
@@ -2140,7 +2225,7 @@ void wakaw::Cm::RasterBase<wakaw::watwat::Polocator?>(unsigned int*, unsigned in
test_js_closure_0 = open(path_from_root('tests', 'Module-exports', 'test.js')).read()
# Check that test.js compiled with --closure 0 contains "module['exports'] = Module;"
- assert "module['exports'] = Module;" in test_js_closure_0
+ assert ("module['exports'] = Module;" in test_js_closure_0) or ('module["exports"]=Module' in test_js_closure_0)
# Check that main.js (which requires test.js) completes successfully when run in node.js
# in order to check that the exports are indeed functioning correctly.
@@ -2296,15 +2381,17 @@ mergeInto(LibraryManager.library, {
self.clear()
os.mkdir(outdir)
- process = Popen([PYTHON, EMCC, '-c', path_from_root('tests', 'hello_world.c'), '-o', outdir])
- process.communicate()
- assert(os.path.isfile(outdir + 'hello_world.o'))
+ process = Popen([PYTHON, EMCC, '-c', path_from_root('tests', 'hello_world.c'), '-o', outdir], stderr=PIPE)
+ out, err = process.communicate()
+ assert not err, err
+ assert os.path.isfile(outdir + 'hello_world.o')
self.clear()
os.mkdir(outdir)
- process = Popen([PYTHON, EMCC, '-c', path_from_root('tests', 'hello_world.c'), '-o', outdir, '--default-obj-ext', 'obj'])
- process.communicate()
- assert(os.path.isfile(outdir + 'hello_world.obj'))
+ process = Popen([PYTHON, EMCC, '-c', path_from_root('tests', 'hello_world.c'), '-o', outdir, '--default-obj-ext', 'obj'], stderr=PIPE)
+ out, err = process.communicate()
+ assert not err, err
+ assert os.path.isfile(outdir + 'hello_world.obj')
def test_doublestart_bug(self):
open('code.cpp', 'w').write(r'''
@@ -2381,6 +2468,11 @@ int main() {
err = Popen([PYTHON, EMCC, 'src.cpp', '-include', 'header.h', '-Xclang', '-print-stats'], stderr=PIPE).communicate()
assert '*** PCH/Modules Loaded:\nModule: header.h.gch' not in err[1], err[1]
+ # with specified target via -o
+ try_delete('header.h.gch')
+ Popen([PYTHON, EMCC, '-xc++-header', 'header.h', '-o', 'my.gch']).communicate()
+ assert os.path.exists('my.gch')
+
def test_warn_unaligned(self):
if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('need fastcomp')
open('src.cpp', 'w').write(r'''
@@ -2710,3 +2802,103 @@ int main()
assert os.path.exists('hello_world.o')
assert os.path.exists('hello_world.bc')
+ def test_bad_function_pointer_cast(self):
+ open('src.cpp', 'w').write(r'''
+#include <stdio.h>
+
+typedef int (*callback) (int, ...);
+
+int impl(int foo) {
+ printf("Hello, world.\n");
+ return 0;
+}
+
+int main() {
+ volatile callback f = (callback) impl;
+ f(0); /* This fails with or without additional arguments. */
+ return 0;
+}
+''')
+
+ for opts in [0, 1, 2]:
+ for safe in [0, 1]:
+ cmd = [PYTHON, EMCC, 'src.cpp', '-O' + str(opts), '-s', 'SAFE_HEAP=' + str(safe)]
+ print cmd
+ Popen(cmd).communicate()
+ output = run_js('a.out.js', stderr=PIPE, full_output=True)
+ if safe:
+ assert 'Function table mask error' in output, output
+ else:
+ if opts == 0:
+ assert 'Invalid function pointer called' in output, output
+ else:
+ assert 'abort()' in output, output
+
+ def test_aliased_func_pointers(self):
+ open('src.cpp', 'w').write(r'''
+#include <stdio.h>
+
+int impl1(int foo) { return foo; }
+float impla(float foo) { return foo; }
+int impl2(int foo) { return foo+1; }
+float implb(float foo) { return foo+1; }
+int impl3(int foo) { return foo+2; }
+float implc(float foo) { return foo+2; }
+
+int main(int argc, char **argv) {
+ volatile void *f = (void*)impl1;
+ if (argc == 50) f = (void*)impla;
+ if (argc == 51) f = (void*)impl2;
+ if (argc == 52) f = (void*)implb;
+ if (argc == 53) f = (void*)impl3;
+ if (argc == 54) f = (void*)implc;
+ return (int)f;
+}
+''')
+
+ print 'aliasing'
+
+ sizes_ii = {}
+ sizes_dd = {}
+
+ for alias in [None, 0, 1]:
+ cmd = [PYTHON, EMCC, 'src.cpp', '-O1']
+ if alias is not None:
+ cmd += ['-s', 'ALIASING_FUNCTION_POINTERS=' + str(alias)]
+ else:
+ alias = -1
+ print cmd
+ Popen(cmd).communicate()
+ src = open('a.out.js').read().split('\n')
+ for line in src:
+ if line.strip().startswith('var FUNCTION_TABLE_ii = '):
+ sizes_ii[alias] = line.count(',')
+ if line.strip().startswith('var FUNCTION_TABLE_dd = '):
+ sizes_dd[alias] = line.count(',')
+
+ for sizes in [sizes_ii, sizes_dd]:
+ assert sizes[-1] == 3 # default - let them alias
+ assert sizes[0] == 7 # no aliasing, all unique, fat tables
+ assert sizes[1] == 3 # aliased once more
+
+ def test_bad_export(self):
+ for m in ['', ' ']:
+ self.clear()
+ cmd = [PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-s', 'EXPORTED_FUNCTIONS=["' + m + '_main"]']
+ print cmd
+ stdout, stderr = Popen(cmd, stderr=PIPE).communicate()
+ if m:
+ assert 'function requested to be exported, but not implemented: " _main"' in stderr, stderr
+ else:
+ self.assertContained('hello, world!', run_js('a.out.js'))
+
+ def test_no_dynamic_execution(self):
+ cmd = [PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-O1', '-s', 'NO_DYNAMIC_EXECUTION=1']
+ stdout, stderr = Popen(cmd, stderr=PIPE).communicate()
+ self.assertContained('hello, world!', run_js('a.out.js'))
+ src = open('a.out.js').read()
+ assert 'eval(' not in src
+ assert 'eval.' not in src
+ assert 'new Function' not in src
+
+
diff --git a/tests/test_sanity.py b/tests/test_sanity.py
index 3d3da523..3ebd49b6 100644
--- a/tests/test_sanity.py
+++ b/tests/test_sanity.py
@@ -240,7 +240,7 @@ class sanity(RunnerCore):
os.chmod(path_from_root('tests', 'fake', 'bin', 'llc'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
os.chmod(path_from_root('tests', 'fake', 'bin', 'clang++'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
try_delete(SANITY_FILE)
- output = self.check_working(EMCC, 'did not see a source tree above LLVM_DIR, could not verify version numbers match')
+ output = self.check_working(EMCC, 'did not see a source tree above the LLVM root directory')
VERSION_WARNING = 'Emscripten, llvm and clang versions do not match, this is dangerous'
diff --git a/tests/webidl/output.txt b/tests/webidl/output.txt
new file mode 100644
index 00000000..c029935f
--- /dev/null
+++ b/tests/webidl/output.txt
@@ -0,0 +1,58 @@
+Parent:42
+*
+84
+object
+c1
+Parent:7
+Child1:7
+7
+14
+196
+588
+14
+28
+Child1::parentFunc(90)
+c1 v2
+Parent:16
+Child1:15
+15
+30
+900
+2700
+c2
+Parent:9
+Child2:9
+9
+18
+5832
+0
+0
+1
+*static*
+*virtualf*
+*virtualf*
+*virtualf2*
+Parent:9
+Child2:9
+*js virtualf replacement*
+*js virtualf replacement*
+*js virtualf2 replacement*
+*js virtualf3 replacement 123*
+caught: a JSImplementation must implement all functions, you forgot Child2JS::virtualFunc4.
+*virtualf*
+*virtualf*
+*virtualf2*
+*ok*
+|hello|43|world|41|
+12.35
+10
+object
+10
+11
+object
+10
+11
+21.12
+198
+
+done.
diff --git a/tests/webidl/post.js b/tests/webidl/post.js
new file mode 100644
index 00000000..5376f27b
--- /dev/null
+++ b/tests/webidl/post.js
@@ -0,0 +1,120 @@
+
+// Part 1
+
+var sme = new Module.Parent(42);
+sme.mulVal(2);
+Module.print('*')
+Module.print(sme.getVal());
+sme.parentFunc(90);
+Module.print(typeof sme.getAsConst());
+
+Module.print('c1');
+
+var c1 = new Module.Child1();
+Module.print(c1.getVal());
+c1.mulVal(2);
+Module.print(c1.getVal());
+Module.print(c1.getValSqr());
+Module.print(c1.getValSqr(3));
+Module.print(c1.getValTimes()); // default argument should be 1
+Module.print(c1.getValTimes(2));
+c1.parentFunc(90);
+
+Module.print('c1 v2');
+
+c1 = new Module.Child1(8); // now with a parameter, we should handle the overloading automatically and properly and use constructor #2
+Module.print(c1.getVal());
+c1.mulVal(2);
+Module.print(c1.getVal());
+Module.print(c1.getValSqr());
+Module.print(c1.getValSqr(3));
+
+Module.print('c2')
+
+var c2 = new Module.Child2();
+Module.print(c2.getVal());
+c2.mulVal(2);
+Module.print(c2.getVal());
+Module.print(c2.getValCube());
+var succeeded;
+try {
+ succeeded = 0;
+ Module.print(c2.doSomethingSecret()); // should fail since private
+ succeeded = 1;
+} catch(e) {}
+Module.print(succeeded);
+try {
+ succeeded = 0;
+ Module.print(c2.getValSqr()); // function from the other class
+ succeeded = 1;
+} catch(e) {}
+Module.print(succeeded);
+try {
+ succeeded = 0;
+ c2.getValCube(); // sanity
+ succeeded = 1;
+} catch(e) {}
+Module.print(succeeded);
+
+Module.Child2.prototype.printStatic(); // static calls go through the prototype
+
+// virtual function
+c2.virtualFunc();
+Module.Child2.prototype.runVirtualFunc(c2);
+c2.virtualFunc2();
+
+// extend a class from JS
+var c3 = new Module.Child2JS;
+
+c3.virtualFunc = function() {
+ Module.print('*js virtualf replacement*');
+};
+c3.virtualFunc2 = function() {
+ Module.print('*js virtualf2 replacement*');
+};
+c3.virtualFunc3 = function(x) {
+ Module.print('*js virtualf3 replacement ' + x + '*');
+};
+
+c3.virtualFunc();
+Module.Child2.prototype.runVirtualFunc(c3);
+c3.virtualFunc2();
+c3.virtualFunc3(123); // this one is not replaced!
+try {
+ c3.virtualFunc4(123);
+} catch(e) {
+ Module.print('caught: ' + e);
+}
+
+c2.virtualFunc(); // original should remain the same
+Module.Child2.prototype.runVirtualFunc(c2);
+c2.virtualFunc2();
+Module.print('*ok*');
+
+// Part 2
+
+var suser = new Module.StringUser("hello", 43);
+suser.Print(41, "world");
+suser.PrintFloat(12.3456);
+
+var bv = new Module.RefUser(10);
+var bv2 = new Module.RefUser(11);
+Module.print(bv2.getValue(bv));
+
+Module.print(typeof bv2.getMe());
+Module.print(bv2.getMe().getValue(bv));
+Module.print(bv2.getMe().getValue(bv2));
+
+Module.print(typeof bv2.getCopy());
+Module.print(bv2.getCopy().getValue(bv));
+Module.print(bv2.getCopy().getValue(bv2));
+
+bv2.getAnother().PrintFloat(21.12);
+
+Module.print(new Module.Inner().get());
+new Module.Inner().mul(2);
+
+//
+
+Module.print('\ndone.')
+
diff --git a/tests/webidl/test.cpp b/tests/webidl/test.cpp
new file mode 100644
index 00000000..8a2b5c72
--- /dev/null
+++ b/tests/webidl/test.cpp
@@ -0,0 +1,8 @@
+#include "test.h"
+
+Parent::Parent(int val) : value(val) { printf("Parent:%d\n", val); }
+Parent::Parent(Parent *p, Parent *q) : value(p->value + q->value) { printf("Parent:%d\n", value); }
+void Parent::mulVal(int mul) { value *= mul; }
+
+#include "glue.cpp"
+
diff --git a/tests/webidl/test.h b/tests/webidl/test.h
new file mode 100644
index 00000000..5d13846c
--- /dev/null
+++ b/tests/webidl/test.h
@@ -0,0 +1,75 @@
+#include <stdio.h>
+
+// Part 1
+
+class Parent {
+protected:
+ int value;
+public:
+ Parent(int val);
+ Parent(Parent *p, Parent *q); // overload constructor
+ int getVal() { return value; }; // inline should work just fine here, unlike Way 1 before
+ void mulVal(int mul);
+ void parentFunc() {}
+ const Parent *getAsConst() { return NULL; }
+};
+
+class Child1 : public Parent {
+public:
+ Child1() : Parent(7) { printf("Child1:%d\n", value); };
+ Child1(int val) : Parent(val*2) { value -= 1; printf("Child1:%d\n", value); };
+ int getValSqr() { return value*value; }
+ int getValSqr(int more) { return value*value*more; }
+ int getValTimes(int times=1) { return value*times; }
+ void parentFunc(int x) { printf("Child1::parentFunc(%d)\n", x); }
+};
+
+// Child2 has vtable, parent does not. Checks we cast child->parent properly - (Parent*)child is not a no-op, must offset
+class Child2 : public Parent {
+public:
+ Child2() : Parent(9) { printf("Child2:%d\n", value); };
+ int getValCube() { return value*value*value; }
+ static void printStatic() { printf("*static*\n"); }
+
+ virtual void virtualFunc() { printf("*virtualf*\n"); }
+ virtual void virtualFunc2() { printf("*virtualf2*\n"); }
+ static void runVirtualFunc(Child2 *self) { self->virtualFunc(); };
+ virtual void virtualFunc3(int x) { printf("*virtualf3: %d*\n", x); }
+ virtual void virtualFunc4(int x) { printf("*virtualf4: %d*\n", x); }
+
+private:
+ void doSomethingSecret() { printf("security breached!\n"); }; // we should not be able to do this
+};
+
+// Part 2
+
+#include <string.h>
+
+class StringUser {
+ char *s;
+ int i;
+public:
+ StringUser(char *string="NO", int integer=99) : s(strdup(string)), i(integer) {}
+ void Print(int anotherInteger, char *anotherString) {
+ printf("|%s|%d|%s|%d|\n", s, i, anotherString, anotherInteger);
+ }
+ void PrintFloat(float f) { printf("%.2f\n", f); }
+};
+
+struct RefUser {
+ int value;
+ RefUser(int x = 77) : value(x) {}
+ int getValue(RefUser b) { return b.value; }
+ RefUser &getMe() { return *this; }
+ RefUser getCopy() { return RefUser(value*2); }
+ StringUser getAnother() { return StringUser("another", 5); }
+};
+
+namespace Space {
+ struct Inner {
+ Inner() {}
+ int get() { return 198; }
+ Inner& operator*=(float x) { return *this; }
+ };
+}
+
diff --git a/tests/webidl/test.idl b/tests/webidl/test.idl
new file mode 100644
index 00000000..8ee82b76
--- /dev/null
+++ b/tests/webidl/test.idl
@@ -0,0 +1,67 @@
+
+// Part 1
+
+interface Parent {
+ void Parent(long val);
+ long getVal();
+ void mulVal(long mul);
+ void parentFunc();
+ [Const] Parent getAsConst();
+};
+
+interface Child1 {
+ void Child1(optional long val);
+ long getValSqr(optional long more);
+ long getValTimes(optional long times=1);
+ void parentFunc(long x); // redefinition, name collides with parent
+};
+
+Child1 implements Parent;
+
+interface Child2 {
+ void Child2();
+ long getValCube();
+ static void printStatic();
+ void virtualFunc();
+ void virtualFunc2();
+ void virtualFunc3(long x);
+ void virtualFunc4(long x);
+ static void runVirtualFunc(Child2 self);
+};
+
+Child2 implements Parent;
+
+[JSImplementation="Child2"]
+interface Child2JS {
+ void Child2JS();
+ void virtualFunc();
+ void virtualFunc2();
+ void virtualFunc3(long x);
+ void virtualFunc4(long x);
+};
+
+// Part 2
+
+interface StringUser {
+ void StringUser();
+ void StringUser(DOMString str, long i);
+ void Print(long anotherInteger, DOMString anotherString);
+ void PrintFloat(float f);
+};
+
+interface RefUser {
+ void RefUser();
+ void RefUser(long value);
+ long getValue([Ref] RefUser b);
+ [Ref] RefUser getMe();
+ [Value] RefUser getCopy(); // must have zero-arg constructor
+ [Value] StringUser getAnother();
+};
+
+[Prefix="Space::"]
+interface Inner {
+ void Inner();
+ long get();
+ [Operator="*=", Ref] Inner mul(float x);
+};
+
diff --git a/third_party/WebIDL.py b/third_party/WebIDL.py
new file mode 100644
index 00000000..a94cb528
--- /dev/null
+++ b/third_party/WebIDL.py
@@ -0,0 +1,5033 @@
+# from http://mxr.mozilla.org/mozilla-central/source/dom/bindings/parser/WebIDL.py
+# rev 501baeb3a034
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+""" A WebIDL parser. """
+
+from ply import lex, yacc
+import re
+import os
+import traceback
+import math
+
+# Machinery
+
+def parseInt(literal):
+ string = literal
+ sign = 0
+ base = 0
+
+ if string[0] == '-':
+ sign = -1
+ string = string[1:]
+ else:
+ sign = 1
+
+ if string[0] == '0' and len(string) > 1:
+ if string[1] == 'x' or string[1] == 'X':
+ base = 16
+ string = string[2:]
+ else:
+ base = 8
+ string = string[1:]
+ else:
+ base = 10
+
+ value = int(string, base)
+ return value * sign
+
+# Magic for creating enums
+def M_add_class_attribs(attribs, start):
+ def foo(name, bases, dict_):
+ for v, k in enumerate(attribs):
+ dict_[k] = start + v
+ assert 'length' not in dict_
+ dict_['length'] = start + len(attribs)
+ return type(name, bases, dict_)
+ return foo
+
+def enum(*names, **kw):
+ if len(kw) == 1:
+ base = kw['base'].__class__
+ start = base.length
+ else:
+ assert len(kw) == 0
+ base = object
+ start = 0
+ class Foo(base):
+ __metaclass__ = M_add_class_attribs(names, start)
+ def __setattr__(self, name, value): # this makes it read-only
+ raise NotImplementedError
+ return Foo()
+
+class WebIDLError(Exception):
+ def __init__(self, message, locations, warning=False):
+ self.message = message
+ self.locations = [str(loc) for loc in locations]
+ self.warning = warning
+
+ def __str__(self):
+ return "%s: %s%s%s" % (self.warning and 'warning' or 'error',
+ self.message,
+ ", " if len(self.locations) != 0 else "",
+ "\n".join(self.locations))
+
+class Location(object):
+ def __init__(self, lexer, lineno, lexpos, filename):
+ self._line = None
+ self._lineno = lineno
+ self._lexpos = lexpos
+ self._lexdata = lexer.lexdata
+ self._file = filename if filename else "<unknown>"
+
+ def __eq__(self, other):
+ return self._lexpos == other._lexpos and \
+ self._file == other._file
+
+ def filename(self):
+ return self._file
+
+ def resolve(self):
+ if self._line:
+ return
+
+ startofline = self._lexdata.rfind('\n', 0, self._lexpos) + 1
+ endofline = self._lexdata.find('\n', self._lexpos, self._lexpos + 80)
+ if endofline != -1:
+ self._line = self._lexdata[startofline:endofline]
+ else:
+ self._line = self._lexdata[startofline:]
+ self._colno = self._lexpos - startofline
+
+ # Our line number seems to point to the start of self._lexdata
+ self._lineno += self._lexdata.count('\n', 0, startofline)
+
+ def get(self):
+ self.resolve()
+ return "%s line %s:%s" % (self._file, self._lineno, self._colno)
+
+ def _pointerline(self):
+ return " " * self._colno + "^"
+
+ def __str__(self):
+ self.resolve()
+ return "%s line %s:%s\n%s\n%s" % (self._file, self._lineno, self._colno,
+ self._line, self._pointerline())
+
+class BuiltinLocation(object):
+ def __init__(self, text):
+ self.msg = text + "\n"
+
+ def __eq__(self, other):
+ return isinstance(other, BuiltinLocation) and \
+ self.msg == other.msg
+
+ def filename(self):
+ return '<builtin>'
+
+ def resolve(self):
+ pass
+
+ def get(self):
+ return self.msg
+
+ def __str__(self):
+ return self.get()
+
+
+# Data Model
+
+class IDLObject(object):
+ def __init__(self, location):
+ self.location = location
+ self.userData = dict()
+
+ def filename(self):
+ return self.location.filename()
+
+ def isInterface(self):
+ return False
+
+ def isEnum(self):
+ return False
+
+ def isCallback(self):
+ return False
+
+ def isType(self):
+ return False
+
+ def isDictionary(self):
+ return False;
+
+ def isUnion(self):
+ return False
+
+ def getUserData(self, key, default):
+ return self.userData.get(key, default)
+
+ def setUserData(self, key, value):
+ self.userData[key] = value
+
+ def addExtendedAttributes(self, attrs):
+ assert False # Override me!
+
+ def handleExtendedAttribute(self, attr):
+ assert False # Override me!
+
+ def _getDependentObjects(self):
+ assert False # Override me!
+
+ def getDeps(self, visited=None):
+ """ Return a set of files that this object depends on. If any of
+ these files are changed the parser needs to be rerun to regenerate
+ a new IDLObject.
+
+ The visited argument is a set of all the objects already visited.
+ We must test to see if we are in it, and if so, do nothing. This
+ prevents infinite recursion."""
+
+ # NB: We can't use visited=set() above because the default value is
+ # evaluated when the def statement is evaluated, not when the function
+ # is executed, so there would be one set for all invocations.
+ if visited == None:
+ visited = set()
+
+ if self in visited:
+ return set()
+
+ visited.add(self)
+
+ deps = set()
+ if self.filename() != "<builtin>":
+ deps.add(self.filename())
+
+ for d in self._getDependentObjects():
+ deps = deps.union(d.getDeps(visited))
+
+ return deps
+
+class IDLScope(IDLObject):
+ def __init__(self, location, parentScope, identifier):
+ IDLObject.__init__(self, location)
+
+ self.parentScope = parentScope
+ if identifier:
+ assert isinstance(identifier, IDLIdentifier)
+ self._name = identifier
+ else:
+ self._name = None
+
+ self._dict = {}
+
+ def __str__(self):
+ return self.QName()
+
+ def QName(self):
+ if self._name:
+ return self._name.QName() + "::"
+ return "::"
+
+ def ensureUnique(self, identifier, object):
+ """
+ Ensure that there is at most one 'identifier' in scope ('self').
+ Note that object can be None. This occurs if we end up here for an
+ interface type we haven't seen yet.
+ """
+ assert isinstance(identifier, IDLUnresolvedIdentifier)
+ assert not object or isinstance(object, IDLObjectWithIdentifier)
+ assert not object or object.identifier == identifier
+
+ if identifier.name in self._dict:
+ if not object:
+ return
+
+ # ensureUnique twice with the same object is not allowed
+ assert id(object) != id(self._dict[identifier.name])
+
+ replacement = self.resolveIdentifierConflict(self, identifier,
+ self._dict[identifier.name],
+ object)
+ self._dict[identifier.name] = replacement
+ return
+
+ assert object
+
+ self._dict[identifier.name] = object
+
+ def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject):
+ if isinstance(originalObject, IDLExternalInterface) and \
+ isinstance(newObject, IDLExternalInterface) and \
+ originalObject.identifier.name == newObject.identifier.name:
+ return originalObject
+
+ if (isinstance(originalObject, IDLExternalInterface) or
+ isinstance(newObject, IDLExternalInterface)):
+ raise WebIDLError(
+ "Name collision between "
+ "interface declarations for identifier '%s' at '%s' and '%s'"
+ % (identifier.name,
+ originalObject.location, newObject.location), [])
+
+ # We do the merging of overloads here as opposed to in IDLInterface
+ # because we need to merge overloads of NamedConstructors and we need to
+ # detect conflicts in those across interfaces. See also the comment in
+ # IDLInterface.addExtendedAttributes for "NamedConstructor".
+ if originalObject.tag == IDLInterfaceMember.Tags.Method and \
+ newObject.tag == IDLInterfaceMember.Tags.Method:
+ return originalObject.addOverload(newObject)
+
+ # Default to throwing, derived classes can override.
+ conflictdesc = "\n\t%s at %s\n\t%s at %s" % \
+ (originalObject, originalObject.location, newObject, newObject.location)
+
+ raise WebIDLError(
+ "Multiple unresolvable definitions of identifier '%s' in scope '%s%s"
+ % (identifier.name, str(self), conflictdesc), [])
+
+ def _lookupIdentifier(self, identifier):
+ return self._dict[identifier.name]
+
+ def lookupIdentifier(self, identifier):
+ assert isinstance(identifier, IDLIdentifier)
+ assert identifier.scope == self
+ return self._lookupIdentifier(identifier)
+
+class IDLIdentifier(IDLObject):
+ def __init__(self, location, scope, name):
+ IDLObject.__init__(self, location)
+
+ self.name = name
+ assert isinstance(scope, IDLScope)
+ self.scope = scope
+
+ def __str__(self):
+ return self.QName()
+
+ def QName(self):
+ return self.scope.QName() + self.name
+
+ def __hash__(self):
+ return self.QName().__hash__()
+
+ def __eq__(self, other):
+ return self.QName() == other.QName()
+
+ def object(self):
+ return self.scope.lookupIdentifier(self)
+
+class IDLUnresolvedIdentifier(IDLObject):
+ def __init__(self, location, name, allowDoubleUnderscore = False,
+ allowForbidden = False):
+ IDLObject.__init__(self, location)
+
+ assert len(name) > 0
+
+ if name[:2] == "__" and name != "__content" and name != "___noSuchMethod__" and not allowDoubleUnderscore:
+ raise WebIDLError("Identifiers beginning with __ are reserved",
+ [location])
+ if name[0] == '_' and not allowDoubleUnderscore:
+ name = name[1:]
+ # TODO: Bug 872377, Restore "toJSON" to below list.
+ # We sometimes need custom serialization, so allow toJSON for now.
+ if (name in ["constructor", "toString"] and
+ not allowForbidden):
+ raise WebIDLError("Cannot use reserved identifier '%s'" % (name),
+ [location])
+
+ self.name = name
+
+ def __str__(self):
+ return self.QName()
+
+ def QName(self):
+ return "<unresolved scope>::" + self.name
+
+ def resolve(self, scope, object):
+ assert isinstance(scope, IDLScope)
+ assert not object or isinstance(object, IDLObjectWithIdentifier)
+ assert not object or object.identifier == self
+
+ scope.ensureUnique(self, object)
+
+ identifier = IDLIdentifier(self.location, scope, self.name)
+ if object:
+ object.identifier = identifier
+ return identifier
+
+ def finish(self):
+ assert False # Should replace with a resolved identifier first.
+
+class IDLObjectWithIdentifier(IDLObject):
+ def __init__(self, location, parentScope, identifier):
+ IDLObject.__init__(self, location)
+
+ assert isinstance(identifier, IDLUnresolvedIdentifier)
+
+ self.identifier = identifier
+
+ if parentScope:
+ self.resolve(parentScope)
+
+ self.treatNullAs = "Default"
+
+ def resolve(self, parentScope):
+ assert isinstance(parentScope, IDLScope)
+ assert isinstance(self.identifier, IDLUnresolvedIdentifier)
+ self.identifier.resolve(parentScope, self)
+
+ def checkForStringHandlingExtendedAttributes(self, attrs,
+ isDictionaryMember=False,
+ isOptional=False):
+ """
+ A helper function to deal with TreatNullAs. Returns the list
+ of attrs it didn't handle itself.
+ """
+ assert isinstance(self, IDLArgument) or isinstance(self, IDLAttribute)
+ unhandledAttrs = list()
+ for attr in attrs:
+ if not attr.hasValue():
+ unhandledAttrs.append(attr)
+ continue
+
+ identifier = attr.identifier()
+ value = attr.value()
+ if identifier == "TreatNullAs":
+ if not self.type.isDOMString() or self.type.nullable():
+ raise WebIDLError("[TreatNullAs] is only allowed on "
+ "arguments or attributes whose type is "
+ "DOMString",
+ [self.location])
+ if isDictionaryMember:
+ raise WebIDLError("[TreatNullAs] is not allowed for "
+ "dictionary members", [self.location])
+ if value != 'EmptyString':
+ raise WebIDLError("[TreatNullAs] must take the identifier "
+ "'EmptyString', not '%s'" % value,
+ [self.location])
+ self.treatNullAs = value
+ else:
+ unhandledAttrs.append(attr)
+
+ return unhandledAttrs
+
+class IDLObjectWithScope(IDLObjectWithIdentifier, IDLScope):
+ def __init__(self, location, parentScope, identifier):
+ assert isinstance(identifier, IDLUnresolvedIdentifier)
+
+ IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier)
+ IDLScope.__init__(self, location, parentScope, self.identifier)
+
+class IDLIdentifierPlaceholder(IDLObjectWithIdentifier):
+ def __init__(self, location, identifier):
+ assert isinstance(identifier, IDLUnresolvedIdentifier)
+ IDLObjectWithIdentifier.__init__(self, location, None, identifier)
+
+ def finish(self, scope):
+ try:
+ scope._lookupIdentifier(self.identifier)
+ except:
+ raise WebIDLError("Unresolved type '%s'." % self.identifier,
+ [self.location])
+
+ obj = self.identifier.resolve(scope, None)
+ return scope.lookupIdentifier(obj)
+
+class IDLExternalInterface(IDLObjectWithIdentifier):
+ def __init__(self, location, parentScope, identifier):
+ assert isinstance(identifier, IDLUnresolvedIdentifier)
+ assert isinstance(parentScope, IDLScope)
+ self.parent = None
+ IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier)
+ IDLObjectWithIdentifier.resolve(self, parentScope)
+
+ def finish(self, scope):
+ pass
+
+ def validate(self):
+ pass
+
+ def isExternal(self):
+ return True
+
+ def isInterface(self):
+ return True
+
+ def isConsequential(self):
+ return False
+
+ def addExtendedAttributes(self, attrs):
+ assert len(attrs) == 0
+
+ def resolve(self, parentScope):
+ pass
+
+ def getJSImplementation(self):
+ return None
+
+ def isJSImplemented(self):
+ return False
+
+ def getNavigatorProperty(self):
+ return None
+
+ def _getDependentObjects(self):
+ return set()
+
+class IDLInterface(IDLObjectWithScope):
+ def __init__(self, location, parentScope, name, parent, members,
+ isPartial):
+ assert isinstance(parentScope, IDLScope)
+ assert isinstance(name, IDLUnresolvedIdentifier)
+ assert not isPartial or not parent
+
+ self.parent = None
+ self._callback = False
+ self._finished = False
+ self.members = []
+ # namedConstructors needs deterministic ordering because bindings code
+ # outputs the constructs in the order that namedConstructors enumerates
+ # them.
+ self.namedConstructors = list()
+ self.implementedInterfaces = set()
+ self._consequential = False
+ self._isPartial = True
+ # self.interfacesBasedOnSelf is the set of interfaces that inherit from
+ # self or have self as a consequential interface, including self itself.
+ # Used for distinguishability checking.
+ self.interfacesBasedOnSelf = set([self])
+ # self.interfacesImplementingSelf is the set of interfaces that directly
+ # have self as a consequential interface
+ self.interfacesImplementingSelf = set()
+ self._hasChildInterfaces = False
+ self._isOnGlobalProtoChain = False
+ # Tracking of the number of reserved slots we need for our
+ # members and those of ancestor interfaces.
+ self.totalMembersInSlots = 0
+ # Tracking of the number of own own members we have in slots
+ self._ownMembersInSlots = 0
+
+ IDLObjectWithScope.__init__(self, location, parentScope, name)
+
+ if not isPartial:
+ self.setNonPartial(location, parent, members)
+ else:
+ # Just remember our members for now
+ self.members = members
+
+ def __str__(self):
+ return "Interface '%s'" % self.identifier.name
+
+ def ctor(self):
+ identifier = IDLUnresolvedIdentifier(self.location, "constructor",
+ allowForbidden=True)
+ try:
+ return self._lookupIdentifier(identifier)
+ except:
+ return None
+
+ def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject):
+ assert isinstance(scope, IDLScope)
+ assert isinstance(originalObject, IDLInterfaceMember)
+ assert isinstance(newObject, IDLInterfaceMember)
+
+ retval = IDLScope.resolveIdentifierConflict(self, scope, identifier,
+ originalObject, newObject)
+
+ # Might be a ctor, which isn't in self.members
+ if newObject in self.members:
+ self.members.remove(newObject)
+ return retval
+
+ def finish(self, scope):
+ if self._finished:
+ return
+
+ self._finished = True
+
+ if self._isPartial:
+ raise WebIDLError("Interface %s does not have a non-partial "
+ "declaration" % self.identifier.name,
+ [self.location])
+
+ assert not self.parent or isinstance(self.parent, IDLIdentifierPlaceholder)
+ parent = self.parent.finish(scope) if self.parent else None
+ if parent and isinstance(parent, IDLExternalInterface):
+ raise WebIDLError("%s inherits from %s which does not have "
+ "a definition" %
+ (self.identifier.name,
+ self.parent.identifier.name),
+ [self.location])
+ assert not parent or isinstance(parent, IDLInterface)
+
+ self.parent = parent
+
+ assert iter(self.members)
+
+ if self.parent:
+ self.parent.finish(scope)
+
+ self.parent._hasChildInterfaces = True
+
+ self.totalMembersInSlots = self.parent.totalMembersInSlots
+
+ # Interfaces with [Global] must not have anything inherit from them
+ if self.parent.getExtendedAttribute("Global"):
+ # Note: This is not a self.parent.isOnGlobalProtoChain() check
+ # because ancestors of a [Global] interface can have other
+ # descendants.
+ raise WebIDLError("[Global] interface has another interface "
+ "inheriting from it",
+ [self.location, self.parent.location])
+
+ # Callbacks must not inherit from non-callbacks or inherit from
+ # anything that has consequential interfaces.
+ # XXXbz Can non-callbacks inherit from callbacks? Spec issue pending.
+ # XXXbz Can callbacks have consequential interfaces? Spec issue pending
+ if self.isCallback():
+ if not self.parent.isCallback():
+ raise WebIDLError("Callback interface %s inheriting from "
+ "non-callback interface %s" %
+ (self.identifier.name,
+ self.parent.identifier.name),
+ [self.location, self.parent.location])
+ elif self.parent.isCallback():
+ raise WebIDLError("Non-callback interface %s inheriting from "
+ "callback interface %s" %
+ (self.identifier.name,
+ self.parent.identifier.name),
+ [self.location, self.parent.location])
+
+ for iface in self.implementedInterfaces:
+ iface.finish(scope)
+
+ cycleInGraph = self.findInterfaceLoopPoint(self)
+ if cycleInGraph:
+ raise WebIDLError("Interface %s has itself as ancestor or "
+ "implemented interface" % self.identifier.name,
+ [self.location, cycleInGraph.location])
+
+ if self.isCallback():
+ # "implements" should have made sure we have no
+ # consequential interfaces.
+ assert len(self.getConsequentialInterfaces()) == 0
+ # And that we're not consequential.
+ assert not self.isConsequential()
+
+ # Now resolve() and finish() our members before importing the
+ # ones from our implemented interfaces.
+
+ # resolve() will modify self.members, so we need to iterate
+ # over a copy of the member list here.
+ for member in list(self.members):
+ member.resolve(self)
+
+ for member in self.members:
+ member.finish(scope)
+
+ ctor = self.ctor()
+ if ctor is not None:
+ ctor.finish(scope)
+
+ for ctor in self.namedConstructors:
+ ctor.finish(scope)
+
+ # Make a copy of our member list, so things that implement us
+ # can get those without all the stuff we implement ourselves
+ # admixed.
+ self.originalMembers = list(self.members)
+
+ # Import everything from our consequential interfaces into
+ # self.members. Sort our consequential interfaces by name
+ # just so we have a consistent order.
+ for iface in sorted(self.getConsequentialInterfaces(),
+ cmp=cmp,
+ key=lambda x: x.identifier.name):
+ # Flag the interface as being someone's consequential interface
+ iface.setIsConsequentialInterfaceOf(self)
+ additionalMembers = iface.originalMembers;
+ for additionalMember in additionalMembers[:]:
+ for member in self.members:
+ if additionalMember.identifier.name == member.identifier.name:
+ # XXX emscripten: allow such name collisions, ignore parent
+ additionalMembers.remove(additionalMember)
+ #raise WebIDLError(
+ # "Multiple definitions of %s on %s coming from 'implements' statements" %
+ # (member.identifier.name, self),
+ # [additionalMember.location, member.location])
+ self.members.extend(additionalMembers)
+ iface.interfacesImplementingSelf.add(self)
+
+ for ancestor in self.getInheritedInterfaces():
+ ancestor.interfacesBasedOnSelf.add(self)
+ for ancestorConsequential in ancestor.getConsequentialInterfaces():
+ ancestorConsequential.interfacesBasedOnSelf.add(self)
+
+ for member in self.members:
+ if (member.isAttr() and member.isUnforgeable() and
+ not hasattr(member, "originatingInterface")):
+ member.originatingInterface = self
+
+ # Compute slot indices for our members before we pull in
+ # unforgeable members from our parent.
+ for member in self.members:
+ if (member.isAttr() and
+ (member.getExtendedAttribute("StoreInSlot") or
+ member.getExtendedAttribute("Cached"))):
+ member.slotIndex = self.totalMembersInSlots
+ self.totalMembersInSlots += 1
+ if member.getExtendedAttribute("StoreInSlot"):
+ self._ownMembersInSlots += 1
+
+ if self.parent:
+ # Make sure we don't shadow any of the [Unforgeable] attributes on
+ # our ancestor interfaces. We don't have to worry about
+ # consequential interfaces here, because those have already been
+ # imported into the relevant .members lists. And we don't have to
+ # worry about anything other than our parent, because it has already
+ # imported its ancestors unforgeable attributes into its member
+ # list.
+ for unforgeableAttr in (attr for attr in self.parent.members if
+ attr.isAttr() and not attr.isStatic() and
+ attr.isUnforgeable()):
+ shadows = [ m for m in self.members if
+ (m.isAttr() or m.isMethod()) and
+ not m.isStatic() and
+ m.identifier.name == unforgeableAttr.identifier.name ]
+ if len(shadows) != 0:
+ locs = [unforgeableAttr.location] + [ s.location for s
+ in shadows ]
+ raise WebIDLError("Interface %s shadows [Unforgeable] "
+ "members of %s" %
+ (self.identifier.name,
+ ancestor.identifier.name),
+ locs)
+ # And now just stick it in our members, since we won't be
+ # inheriting this down the proto chain. If we really cared we
+ # could try to do something where we set up the unforgeable
+ # attributes of ancestor interfaces, with their corresponding
+ # getters, on our interface, but that gets pretty complicated
+ # and seems unnecessary.
+ self.members.append(unforgeableAttr)
+
+ # Ensure that there's at most one of each {named,indexed}
+ # {getter,setter,creator,deleter}, at most one stringifier,
+ # and at most one legacycaller. Note that this last is not
+ # quite per spec, but in practice no one overloads
+ # legacycallers.
+ specialMembersSeen = {}
+ for member in self.members:
+ if not member.isMethod():
+ continue
+
+ if member.isGetter():
+ memberType = "getters"
+ elif member.isSetter():
+ memberType = "setters"
+ elif member.isCreator():
+ memberType = "creators"
+ elif member.isDeleter():
+ memberType = "deleters"
+ elif member.isStringifier():
+ memberType = "stringifiers"
+ elif member.isJsonifier():
+ memberType = "jsonifiers"
+ elif member.isLegacycaller():
+ memberType = "legacycallers"
+ else:
+ continue
+
+ if (memberType != "stringifiers" and memberType != "legacycallers" and
+ memberType != "jsonifiers"):
+ if member.isNamed():
+ memberType = "named " + memberType
+ else:
+ assert member.isIndexed()
+ memberType = "indexed " + memberType
+
+ if memberType in specialMembersSeen:
+ raise WebIDLError("Multiple " + memberType + " on %s" % (self),
+ [self.location,
+ specialMembersSeen[memberType].location,
+ member.location])
+
+ specialMembersSeen[memberType] = member
+
+ if self._isOnGlobalProtoChain:
+ # Make sure we have no named setters, creators, or deleters
+ for memberType in ["setter", "creator", "deleter"]:
+ memberId = "named " + memberType + "s"
+ if memberId in specialMembersSeen:
+ raise WebIDLError("Interface with [Global] has a named %s" %
+ memberType,
+ [self.location,
+ specialMembersSeen[memberId].location])
+ # Make sure we're not [OverrideBuiltins]
+ if self.getExtendedAttribute("OverrideBuiltins"):
+ raise WebIDLError("Interface with [Global] also has "
+ "[OverrideBuiltins]",
+ [self.location])
+ # Mark all of our ancestors as being on the global's proto chain too
+ parent = self.parent
+ while parent:
+ # Must not inherit from an interface with [OverrideBuiltins]
+ if parent.getExtendedAttribute("OverrideBuiltins"):
+ raise WebIDLError("Interface with [Global] inherits from "
+ "interface with [OverrideBuiltins]",
+ [self.location, parent.location])
+ parent._isOnGlobalProtoChain = True
+ parent = parent.parent
+
+ def validate(self):
+ for member in self.members:
+ member.validate()
+
+ # Check that PutForwards refers to another attribute and that no
+ # cycles exist in forwarded assignments.
+ if member.isAttr():
+ iface = self
+ attr = member
+ putForwards = attr.getExtendedAttribute("PutForwards")
+ if putForwards and self.isCallback():
+ raise WebIDLError("[PutForwards] used on an attribute "
+ "on interface %s which is a callback "
+ "interface" % self.identifier.name,
+ [self.location, member.location])
+
+ while putForwards is not None:
+ forwardIface = attr.type.unroll().inner
+ fowardAttr = None
+
+ for forwardedMember in forwardIface.members:
+ if (not forwardedMember.isAttr() or
+ forwardedMember.identifier.name != putForwards[0]):
+ continue
+ if forwardedMember == member:
+ raise WebIDLError("Cycle detected in forwarded "
+ "assignments for attribute %s on "
+ "%s" %
+ (member.identifier.name, self),
+ [member.location])
+ fowardAttr = forwardedMember
+ break
+
+ if fowardAttr is None:
+ raise WebIDLError("Attribute %s on %s forwards to "
+ "missing attribute %s" %
+ (attr.identifier.name, iface, putForwards),
+ [attr.location])
+
+ iface = forwardIface
+ attr = fowardAttr
+ putForwards = attr.getExtendedAttribute("PutForwards")
+
+
+ def isInterface(self):
+ return True
+
+ def isExternal(self):
+ return False
+
+ def setIsConsequentialInterfaceOf(self, other):
+ self._consequential = True
+ self.interfacesBasedOnSelf.add(other)
+
+ def isConsequential(self):
+ return self._consequential
+
+ def setCallback(self, value):
+ self._callback = value
+
+ def isCallback(self):
+ return self._callback
+
+ def isSingleOperationInterface(self):
+ assert self.isCallback() or self.isJSImplemented()
+ return (
+ # JS-implemented things should never need the
+ # this-handling weirdness of single-operation interfaces.
+ not self.isJSImplemented() and
+ # Not inheriting from another interface
+ not self.parent and
+ # No consequential interfaces
+ len(self.getConsequentialInterfaces()) == 0 and
+ # No attributes of any kinds
+ not any(m.isAttr() for m in self.members) and
+ # There is at least one regular operation, and all regular
+ # operations have the same identifier
+ len(set(m.identifier.name for m in self.members if
+ m.isMethod() and not m.isStatic())) == 1)
+
+ def inheritanceDepth(self):
+ depth = 0
+ parent = self.parent
+ while parent:
+ depth = depth + 1
+ parent = parent.parent
+ return depth
+
+ def hasConstants(self):
+ return any(m.isConst() for m in self.members)
+
+ def hasInterfaceObject(self):
+ if self.isCallback():
+ return self.hasConstants()
+ return not hasattr(self, "_noInterfaceObject")
+
+ def hasInterfacePrototypeObject(self):
+ return not self.isCallback() and self.getUserData('hasConcreteDescendant', False)
+
+ def addExtendedAttributes(self, attrs):
+ self._extendedAttrDict = {}
+ for attr in attrs:
+ identifier = attr.identifier()
+
+ # Special cased attrs
+ if identifier == "TreatNonCallableAsNull":
+ raise WebIDLError("TreatNonCallableAsNull cannot be specified on interfaces",
+ [attr.location, self.location])
+ if identifier == "TreatNonObjectAsNull":
+ raise WebIDLError("TreatNonObjectAsNull cannot be specified on interfaces",
+ [attr.location, self.location])
+ elif identifier == "NoInterfaceObject":
+ if not attr.noArguments():
+ raise WebIDLError("[NoInterfaceObject] must take no arguments",
+ [attr.location])
+
+ if self.ctor():
+ raise WebIDLError("Constructor and NoInterfaceObject are incompatible",
+ [self.location])
+
+ self._noInterfaceObject = True
+ elif identifier == "Constructor" or identifier == "NamedConstructor" or identifier == "ChromeConstructor":
+ if identifier == "Constructor" and not self.hasInterfaceObject():
+ raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
+ [self.location])
+
+ if identifier == "NamedConstructor" and not attr.hasValue():
+ raise WebIDLError("NamedConstructor must either take an identifier or take a named argument list",
+ [attr.location])
+
+ if identifier == "ChromeConstructor" and not self.hasInterfaceObject():
+ raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
+ [self.location])
+
+ args = attr.args() if attr.hasArgs() else []
+
+ retType = IDLWrapperType(self.location, self)
+
+ if identifier == "Constructor" or identifier == "ChromeConstructor":
+ name = "constructor"
+ allowForbidden = True
+ else:
+ name = attr.value()
+ allowForbidden = False
+
+ methodIdentifier = IDLUnresolvedIdentifier(self.location, name,
+ allowForbidden=allowForbidden)
+
+ method = IDLMethod(self.location, methodIdentifier, retType,
+ args, static=True)
+ # Constructors are always NewObject and are always
+ # assumed to be able to throw (since there's no way to
+ # indicate otherwise) and never have any other
+ # extended attributes.
+ method.addExtendedAttributes(
+ [IDLExtendedAttribute(self.location, ("NewObject",)),
+ IDLExtendedAttribute(self.location, ("Throws",))])
+ if identifier == "ChromeConstructor":
+ method.addExtendedAttributes(
+ [IDLExtendedAttribute(self.location, ("ChromeOnly",))])
+
+ if identifier == "Constructor" or identifier == "ChromeConstructor":
+ method.resolve(self)
+ else:
+ # We need to detect conflicts for NamedConstructors across
+ # interfaces. We first call resolve on the parentScope,
+ # which will merge all NamedConstructors with the same
+ # identifier accross interfaces as overloads.
+ method.resolve(self.parentScope)
+
+ # Then we look up the identifier on the parentScope. If the
+ # result is the same as the method we're adding then it
+ # hasn't been added as an overload and it's the first time
+ # we've encountered a NamedConstructor with that identifier.
+ # If the result is not the same as the method we're adding
+ # then it has been added as an overload and we need to check
+ # whether the result is actually one of our existing
+ # NamedConstructors.
+ newMethod = self.parentScope.lookupIdentifier(method.identifier)
+ if newMethod == method:
+ self.namedConstructors.append(method)
+ elif not newMethod in self.namedConstructors:
+ raise WebIDLError("NamedConstructor conflicts with a NamedConstructor of a different interface",
+ [method.location, newMethod.location])
+ elif (identifier == "ArrayClass"):
+ if not attr.noArguments():
+ raise WebIDLError("[ArrayClass] must take no arguments",
+ [attr.location])
+ if self.parent:
+ raise WebIDLError("[ArrayClass] must not be specified on "
+ "an interface with inherited interfaces",
+ [attr.location, self.location])
+ elif identifier == "Global":
+ if not attr.noArguments():
+ raise WebIDLError("[Global] must take no arguments",
+ [attr.location])
+ self._isOnGlobalProtoChain = True
+ elif (identifier == "NeedNewResolve" or
+ identifier == "OverrideBuiltins" or
+ identifier == "NoDelete" or
+ identifier == "ChromeOnly"):
+ # Known extended attributes that do not take values
+ if not attr.noArguments():
+ raise WebIDLError("[%s] must take no arguments" % identifier,
+ [attr.location])
+ elif (identifier == "Pref" or
+ identifier == "JSImplementation" or
+ identifier == "HeaderFile" or
+ identifier == "NavigatorProperty" or
+ identifier == "AvailableIn" or
+ identifier == "Prefix" or
+ identifier == "Func"):
+ # Known extended attributes that take a string value
+ if not attr.hasValue():
+ raise WebIDLError("[%s] must have a value" % identifier,
+ [attr.location])
+ else:
+ raise WebIDLError("Unknown extended attribute %s on interface" % identifier,
+ [attr.location])
+
+ attrlist = attr.listValue()
+ self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
+
+ def addImplementedInterface(self, implementedInterface):
+ assert(isinstance(implementedInterface, IDLInterface))
+ self.implementedInterfaces.add(implementedInterface)
+
+ def getInheritedInterfaces(self):
+ """
+ Returns a list of the interfaces this interface inherits from
+ (not including this interface itself). The list is in order
+ from most derived to least derived.
+ """
+ assert(self._finished)
+ if not self.parent:
+ return []
+ parentInterfaces = self.parent.getInheritedInterfaces()
+ parentInterfaces.insert(0, self.parent)
+ return parentInterfaces
+
+ def getConsequentialInterfaces(self):
+ assert(self._finished)
+ # The interfaces we implement directly
+ consequentialInterfaces = set(self.implementedInterfaces)
+
+ # And their inherited interfaces
+ for iface in self.implementedInterfaces:
+ consequentialInterfaces |= set(iface.getInheritedInterfaces())
+
+ # And now collect up the consequential interfaces of all of those
+ temp = set()
+ for iface in consequentialInterfaces:
+ temp |= iface.getConsequentialInterfaces()
+
+ return consequentialInterfaces | temp
+
+ def findInterfaceLoopPoint(self, otherInterface):
+ """
+ Finds an interface, amongst our ancestors and consequential interfaces,
+ that inherits from otherInterface or implements otherInterface
+ directly. If there is no such interface, returns None.
+ """
+ if self.parent:
+ if self.parent == otherInterface:
+ return self
+ loopPoint = self.parent.findInterfaceLoopPoint(otherInterface)
+ if loopPoint:
+ return loopPoint
+ if otherInterface in self.implementedInterfaces:
+ return self
+ for iface in self.implementedInterfaces:
+ loopPoint = iface.findInterfaceLoopPoint(otherInterface)
+ if loopPoint:
+ return loopPoint
+ return None
+
+ def getExtendedAttribute(self, name):
+ return self._extendedAttrDict.get(name, None)
+
+ def setNonPartial(self, location, parent, members):
+ assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
+ if not self._isPartial:
+ raise WebIDLError("Two non-partial definitions for the "
+ "same interface",
+ [location, self.location])
+ self._isPartial = False
+ # Now make it look like we were parsed at this new location, since
+ # that's the place where the interface is "really" defined
+ self.location = location
+ assert not self.parent
+ self.parent = parent
+ # Put the new members at the beginning
+ self.members = members + self.members
+
+ def getJSImplementation(self):
+ classId = self.getExtendedAttribute("JSImplementation")
+ if not classId:
+ return classId
+ assert isinstance(classId, list)
+ assert len(classId) == 1
+ return classId[0]
+
+ def isJSImplemented(self):
+ return bool(self.getJSImplementation())
+
+ def getNavigatorProperty(self):
+ naviProp = self.getExtendedAttribute("NavigatorProperty")
+ if not naviProp:
+ return None
+ assert len(naviProp) == 1
+ assert isinstance(naviProp, list)
+ assert len(naviProp[0]) != 0
+ return naviProp[0]
+
+ def hasChildInterfaces(self):
+ return self._hasChildInterfaces
+
+ def isOnGlobalProtoChain(self):
+ return self._isOnGlobalProtoChain
+
+ def _getDependentObjects(self):
+ deps = set(self.members)
+ deps.union(self.implementedInterfaces)
+ if self.parent:
+ deps.add(self.parent)
+ return deps
+
+ def hasMembersInSlots(self):
+ return self._ownMembersInSlots != 0
+
+class IDLDictionary(IDLObjectWithScope):
+ def __init__(self, location, parentScope, name, parent, members):
+ assert isinstance(parentScope, IDLScope)
+ assert isinstance(name, IDLUnresolvedIdentifier)
+ assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
+
+ self.parent = parent
+ self._finished = False
+ self.members = list(members)
+
+ IDLObjectWithScope.__init__(self, location, parentScope, name)
+
+ def __str__(self):
+ return "Dictionary '%s'" % self.identifier.name
+
+ def isDictionary(self):
+ return True;
+
+ def finish(self, scope):
+ if self._finished:
+ return
+
+ self._finished = True
+
+ if self.parent:
+ assert isinstance(self.parent, IDLIdentifierPlaceholder)
+ oldParent = self.parent
+ self.parent = self.parent.finish(scope)
+ if not isinstance(self.parent, IDLDictionary):
+ raise WebIDLError("Dictionary %s has parent that is not a dictionary" %
+ self.identifier.name,
+ [oldParent.location, self.parent.location])
+
+ # Make sure the parent resolves all its members before we start
+ # looking at them.
+ self.parent.finish(scope)
+
+ for member in self.members:
+ member.resolve(self)
+ if not member.isComplete():
+ member.complete(scope)
+ assert member.type.isComplete()
+
+ # Members of a dictionary are sorted in lexicographic order
+ self.members.sort(cmp=cmp, key=lambda x: x.identifier.name)
+
+ inheritedMembers = []
+ ancestor = self.parent
+ while ancestor:
+ if ancestor == self:
+ raise WebIDLError("Dictionary %s has itself as an ancestor" %
+ self.identifier.name,
+ [self.identifier.location])
+ inheritedMembers.extend(ancestor.members)
+ ancestor = ancestor.parent
+
+ # Catch name duplication
+ for inheritedMember in inheritedMembers:
+ for member in self.members:
+ if member.identifier.name == inheritedMember.identifier.name:
+ raise WebIDLError("Dictionary %s has two members with name %s" %
+ (self.identifier.name, member.identifier.name),
+ [member.location, inheritedMember.location])
+
+ def validate(self):
+ def typeContainsDictionary(memberType, dictionary):
+ """
+ Returns a tuple whose:
+
+ - First element is a Boolean value indicating whether
+ memberType contains dictionary.
+
+ - Second element is:
+ A list of locations that leads from the type that was passed in
+ the memberType argument, to the dictionary being validated,
+ if the boolean value in the first element is True.
+
+ None, if the boolean value in the first element is False.
+ """
+
+ if memberType.nullable() or \
+ memberType.isArray() or \
+ memberType.isSequence():
+ return typeContainsDictionary(memberType.inner, dictionary)
+
+ if memberType.isDictionary():
+ if memberType.inner == dictionary:
+ return (True, [memberType.location])
+
+ (contains, locations) = dictionaryContainsDictionary(memberType.inner, \
+ dictionary)
+ if contains:
+ return (True, [memberType.location] + locations)
+
+ if memberType.isUnion():
+ for member in memberType.flatMemberTypes:
+ (contains, locations) = typeContainsDictionary(member, dictionary)
+ if contains:
+ return (True, locations)
+
+ return (False, None)
+
+ def dictionaryContainsDictionary(dictMember, dictionary):
+ for member in dictMember.members:
+ (contains, locations) = typeContainsDictionary(member.type, dictionary)
+ if contains:
+ return (True, [member.location] + locations)
+
+ if dictMember.parent:
+ if dictMember.parent == dictionary:
+ return (True, [dictMember.location])
+ else:
+ (contains, locations) = dictionaryContainsDictionary(dictMember.parent, dictionary)
+ if contains:
+ return (True, [dictMember.location] + locations)
+
+ return (False, None)
+
+ for member in self.members:
+ if member.type.isDictionary() and member.type.nullable():
+ raise WebIDLError("Dictionary %s has member with nullable "
+ "dictionary type" % self.identifier.name,
+ [member.location])
+ (contains, locations) = typeContainsDictionary(member.type, self)
+ if contains:
+ raise WebIDLError("Dictionary %s has member with itself as type." %
+ self.identifier.name,
+ [member.location] + locations)
+
+ def addExtendedAttributes(self, attrs):
+ assert len(attrs) == 0
+
+ def _getDependentObjects(self):
+ deps = set(self.members)
+ if (self.parent):
+ deps.add(self.parent)
+ return deps
+
+class IDLEnum(IDLObjectWithIdentifier):
+ def __init__(self, location, parentScope, name, values):
+ assert isinstance(parentScope, IDLScope)
+ assert isinstance(name, IDLUnresolvedIdentifier)
+
+ if len(values) != len(set(values)):
+ raise WebIDLError("Enum %s has multiple identical strings" % name.name,
+ [location])
+
+ IDLObjectWithIdentifier.__init__(self, location, parentScope, name)
+ self._values = values
+
+ def values(self):
+ return self._values
+
+ def finish(self, scope):
+ pass
+
+ def validate(self):
+ pass
+
+ def isEnum(self):
+ return True
+
+ def addExtendedAttributes(self, attrs):
+ assert len(attrs) == 0
+
+ def _getDependentObjects(self):
+ return set()
+
+class IDLType(IDLObject):
+ Tags = enum(
+ # The integer types
+ 'int8',
+ 'uint8',
+ 'int16',
+ 'uint16',
+ 'int32',
+ 'uint32',
+ 'int64',
+ 'uint64',
+ # Additional primitive types
+ 'bool',
+ 'unrestricted_float',
+ 'float',
+ 'unrestricted_double',
+ # "double" last primitive type to match IDLBuiltinType
+ 'double',
+ # Other types
+ 'any',
+ 'domstring',
+ 'bytestring',
+ 'object',
+ 'date',
+ 'void',
+ # Funny stuff
+ 'interface',
+ 'dictionary',
+ 'enum',
+ 'callback',
+ 'union',
+ 'sequence',
+ 'array'
+ )
+
+ def __init__(self, location, name):
+ IDLObject.__init__(self, location)
+ self.name = name
+ self.builtin = False
+
+ def __eq__(self, other):
+ return other and self.builtin == other.builtin and self.name == other.name
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __str__(self):
+ return str(self.name)
+
+ def isType(self):
+ return True
+
+ def nullable(self):
+ return False
+
+ def isPrimitive(self):
+ return False
+
+ def isBoolean(self):
+ return False
+
+ def isNumeric(self):
+ return False
+
+ def isString(self):
+ return False
+
+ def isByteString(self):
+ return False
+
+ def isDOMString(self):
+ return False
+
+ def isVoid(self):
+ return self.name == "Void"
+
+ def isSequence(self):
+ return False
+
+ def isArray(self):
+ return False
+
+ def isArrayBuffer(self):
+ return False
+
+ def isArrayBufferView(self):
+ return False
+
+ def isTypedArray(self):
+ return False
+
+ def isCallbackInterface(self):
+ return False
+
+ def isNonCallbackInterface(self):
+ return False
+
+ def isGeckoInterface(self):
+ """ Returns a boolean indicating whether this type is an 'interface'
+ type that is implemented in Gecko. At the moment, this returns
+ true for all interface types that are not types from the TypedArray
+ spec."""
+ return self.isInterface() and not self.isSpiderMonkeyInterface()
+
+ def isSpiderMonkeyInterface(self):
+ """ Returns a boolean indicating whether this type is an 'interface'
+ type that is implemented in Spidermonkey. At the moment, this
+ only returns true for the types from the TypedArray spec. """
+ return self.isInterface() and (self.isArrayBuffer() or \
+ self.isArrayBufferView() or \
+ self.isTypedArray())
+
+ def isDictionary(self):
+ return False
+
+ def isInterface(self):
+ return False
+
+ def isAny(self):
+ return self.tag() == IDLType.Tags.any
+
+ def isDate(self):
+ return self.tag() == IDLType.Tags.date
+
+ def isObject(self):
+ return self.tag() == IDLType.Tags.object
+
+ def isPromise(self):
+ return False
+
+ def isComplete(self):
+ return True
+
+ def includesRestrictedFloat(self):
+ return False
+
+ def isFloat(self):
+ return False
+
+ def isUnrestricted(self):
+ # Should only call this on float types
+ assert self.isFloat()
+
+ def isSerializable(self):
+ return False
+
+ def tag(self):
+ assert False # Override me!
+
+ def treatNonCallableAsNull(self):
+ assert self.tag() == IDLType.Tags.callback
+ return self.nullable() and self.inner._treatNonCallableAsNull
+
+ def treatNonObjectAsNull(self):
+ assert self.tag() == IDLType.Tags.callback
+ return self.nullable() and self.inner._treatNonObjectAsNull
+
+ def addExtendedAttributes(self, attrs):
+ assert len(attrs) == 0
+
+ def resolveType(self, parentScope):
+ pass
+
+ def unroll(self):
+ return self
+
+ def isDistinguishableFrom(self, other):
+ raise TypeError("Can't tell whether a generic type is or is not "
+ "distinguishable from other things")
+
+class IDLUnresolvedType(IDLType):
+ """
+ Unresolved types are interface types
+ """
+
+ def __init__(self, location, name):
+ IDLType.__init__(self, location, name)
+
+ def isComplete(self):
+ return False
+
+ def complete(self, scope):
+ obj = None
+ try:
+ obj = scope._lookupIdentifier(self.name)
+ except:
+ raise WebIDLError("Unresolved type '%s'." % self.name,
+ [self.location])
+
+ assert obj
+ if obj.isType():
+ # obj itself might not be complete; deal with that.
+ assert obj != self
+ if not obj.isComplete():
+ obj = obj.complete(scope)
+ return obj
+
+ name = self.name.resolve(scope, None)
+ return IDLWrapperType(self.location, obj)
+
+ def isDistinguishableFrom(self, other):
+ raise TypeError("Can't tell whether an unresolved type is or is not "
+ "distinguishable from other things")
+
+class IDLNullableType(IDLType):
+ def __init__(self, location, innerType):
+ assert not innerType.isVoid()
+ assert not innerType == BuiltinTypes[IDLBuiltinType.Types.any]
+
+ IDLType.__init__(self, location, innerType.name)
+ self.inner = innerType
+ self.builtin = False
+
+ def __eq__(self, other):
+ return isinstance(other, IDLNullableType) and self.inner == other.inner
+
+ def __str__(self):
+ return self.inner.__str__() + "OrNull"
+
+ def nullable(self):
+ return True
+
+ def isCallback(self):
+ return self.inner.isCallback()
+
+ def isPrimitive(self):
+ return self.inner.isPrimitive()
+
+ def isBoolean(self):
+ return self.inner.isBoolean()
+
+ def isNumeric(self):
+ return self.inner.isNumeric()
+
+ def isString(self):
+ return self.inner.isString()
+
+ def isByteString(self):
+ return self.inner.isByteString()
+
+ def isDOMString(self):
+ return self.inner.isDOMString()
+
+ def isFloat(self):
+ return self.inner.isFloat()
+
+ def isUnrestricted(self):
+ return self.inner.isUnrestricted()
+
+ def includesRestrictedFloat(self):
+ return self.inner.includesRestrictedFloat()
+
+ def isInteger(self):
+ return self.inner.isInteger()
+
+ def isVoid(self):
+ return False
+
+ def isSequence(self):
+ return self.inner.isSequence()
+
+ def isArray(self):
+ return self.inner.isArray()
+
+ def isArrayBuffer(self):
+ return self.inner.isArrayBuffer()
+
+ def isArrayBufferView(self):
+ return self.inner.isArrayBufferView()
+
+ def isTypedArray(self):
+ return self.inner.isTypedArray()
+
+ def isDictionary(self):
+ return self.inner.isDictionary()
+
+ def isInterface(self):
+ return self.inner.isInterface()
+
+ def isCallbackInterface(self):
+ return self.inner.isCallbackInterface()
+
+ def isNonCallbackInterface(self):
+ return self.inner.isNonCallbackInterface()
+
+ def isEnum(self):
+ return self.inner.isEnum()
+
+ def isUnion(self):
+ return self.inner.isUnion()
+
+ def isSerializable(self):
+ return self.inner.isSerializable()
+
+ def tag(self):
+ return self.inner.tag()
+
+ def resolveType(self, parentScope):
+ assert isinstance(parentScope, IDLScope)
+ self.inner.resolveType(parentScope)
+
+ def isComplete(self):
+ return self.inner.isComplete()
+
+ def complete(self, scope):
+ self.inner = self.inner.complete(scope)
+ if self.inner.nullable():
+ raise WebIDLError("The inner type of a nullable type must not be "
+ "a nullable type",
+ [self.location, self.inner.location])
+ if self.inner.isUnion():
+ if self.inner.hasNullableType:
+ raise WebIDLError("The inner type of a nullable type must not "
+ "be a union type that itself has a nullable "
+ "type as a member type", [self.location])
+
+ self.name = self.inner.name
+ return self
+
+ def unroll(self):
+ return self.inner.unroll()
+
+ def isDistinguishableFrom(self, other):
+ if (other.nullable() or (other.isUnion() and other.hasNullableType) or
+ other.isDictionary()):
+ # Can't tell which type null should become
+ return False
+ return self.inner.isDistinguishableFrom(other)
+
+ def _getDependentObjects(self):
+ return self.inner._getDependentObjects()
+
+class IDLSequenceType(IDLType):
+ def __init__(self, location, parameterType):
+ assert not parameterType.isVoid()
+
+ IDLType.__init__(self, location, parameterType.name)
+ self.inner = parameterType
+ self.builtin = False
+
+ def __eq__(self, other):
+ return isinstance(other, IDLSequenceType) and self.inner == other.inner
+
+ def __str__(self):
+ return self.inner.__str__() + "Sequence"
+
+ def nullable(self):
+ return False
+
+ def isPrimitive(self):
+ return False;
+
+ def isString(self):
+ return False;
+
+ def isByteString(self):
+ return False
+
+ def isDOMString(self):
+ return False
+
+ def isVoid(self):
+ return False
+
+ def isSequence(self):
+ return True
+
+ def isArray(self):
+ return False
+
+ def isDictionary(self):
+ return False
+
+ def isInterface(self):
+ return False
+
+ def isEnum(self):
+ return False
+
+ def isSerializable(self):
+ return self.inner.isSerializable()
+
+ def includesRestrictedFloat(self):
+ return self.inner.includesRestrictedFloat()
+
+ def tag(self):
+ return IDLType.Tags.sequence
+
+ def resolveType(self, parentScope):
+ assert isinstance(parentScope, IDLScope)
+ self.inner.resolveType(parentScope)
+
+ def isComplete(self):
+ return self.inner.isComplete()
+
+ def complete(self, scope):
+ self.inner = self.inner.complete(scope)
+ self.name = self.inner.name
+ return self
+
+ def unroll(self):
+ return self.inner.unroll()
+
+ def isDistinguishableFrom(self, other):
+ if other.isUnion():
+ # Just forward to the union; it'll deal
+ return other.isDistinguishableFrom(self)
+ return (other.isPrimitive() or other.isString() or other.isEnum() or
+ other.isDate() or other.isNonCallbackInterface())
+
+ def _getDependentObjects(self):
+ return self.inner._getDependentObjects()
+
+class IDLUnionType(IDLType):
+ def __init__(self, location, memberTypes):
+ IDLType.__init__(self, location, "")
+ self.memberTypes = memberTypes
+ self.hasNullableType = False
+ self.hasDictionaryType = False
+ self.flatMemberTypes = None
+ self.builtin = False
+
+ def __eq__(self, other):
+ return isinstance(other, IDLUnionType) and self.memberTypes == other.memberTypes
+
+ def isVoid(self):
+ return False
+
+ def isUnion(self):
+ return True
+
+ def isSerializable(self):
+ return all(m.isSerializable() for m in self.memberTypes)
+
+ def includesRestrictedFloat(self):
+ return any(t.includesRestrictedFloat() for t in self.memberTypes)
+
+ def tag(self):
+ return IDLType.Tags.union
+
+ def resolveType(self, parentScope):
+ assert isinstance(parentScope, IDLScope)
+ for t in self.memberTypes:
+ t.resolveType(parentScope)
+
+ def isComplete(self):
+ return self.flatMemberTypes is not None
+
+ def complete(self, scope):
+ def typeName(type):
+ if isinstance(type, IDLNullableType):
+ return typeName(type.inner) + "OrNull"
+ if isinstance(type, IDLWrapperType):
+ return typeName(type._identifier.object())
+ if isinstance(type, IDLObjectWithIdentifier):
+ return typeName(type.identifier)
+ if isinstance(type, IDLType) and (type.isArray() or type.isSequence()):
+ return str(type)
+ return type.name
+
+ for (i, type) in enumerate(self.memberTypes):
+ if not type.isComplete():
+ self.memberTypes[i] = type.complete(scope)
+
+ self.name = "Or".join(typeName(type) for type in self.memberTypes)
+ self.flatMemberTypes = list(self.memberTypes)
+ i = 0
+ while i < len(self.flatMemberTypes):
+ if self.flatMemberTypes[i].nullable():
+ if self.hasNullableType:
+ raise WebIDLError("Can't have more than one nullable types in a union",
+ [nullableType.location, self.flatMemberTypes[i].location])
+ if self.hasDictionaryType:
+ raise WebIDLError("Can't have a nullable type and a "
+ "dictionary type in a union",
+ [dictionaryType.location,
+ self.flatMemberTypes[i].location])
+ self.hasNullableType = True
+ nullableType = self.flatMemberTypes[i]
+ self.flatMemberTypes[i] = self.flatMemberTypes[i].inner
+ continue
+ if self.flatMemberTypes[i].isDictionary():
+ if self.hasNullableType:
+ raise WebIDLError("Can't have a nullable type and a "
+ "dictionary type in a union",
+ [nullableType.location,
+ self.flatMemberTypes[i].location])
+ self.hasDictionaryType = True
+ dictionaryType = self.flatMemberTypes[i]
+ elif self.flatMemberTypes[i].isUnion():
+ self.flatMemberTypes[i:i + 1] = self.flatMemberTypes[i].memberTypes
+ continue
+ i += 1
+
+ for (i, t) in enumerate(self.flatMemberTypes[:-1]):
+ for u in self.flatMemberTypes[i + 1:]:
+ if not t.isDistinguishableFrom(u):
+ raise WebIDLError("Flat member types of a union should be "
+ "distinguishable, " + str(t) + " is not "
+ "distinguishable from " + str(u),
+ [self.location, t.location, u.location])
+
+ return self
+
+ def isDistinguishableFrom(self, other):
+ if self.hasNullableType and other.nullable():
+ # Can't tell which type null should become
+ return False
+ if other.isUnion():
+ otherTypes = other.unroll().memberTypes
+ else:
+ otherTypes = [other]
+ # For every type in otherTypes, check that it's distinguishable from
+ # every type in our types
+ for u in otherTypes:
+ if any(not t.isDistinguishableFrom(u) for t in self.memberTypes):
+ return False
+ return True
+
+ def _getDependentObjects(self):
+ return set(self.memberTypes)
+
+class IDLArrayType(IDLType):
+ def __init__(self, location, parameterType):
+ assert not parameterType.isVoid()
+ if parameterType.isSequence():
+ raise WebIDLError("Array type cannot parameterize over a sequence type",
+ [location])
+ if parameterType.isDictionary():
+ raise WebIDLError("Array type cannot parameterize over a dictionary type",
+ [location])
+
+ IDLType.__init__(self, location, parameterType.name)
+ self.inner = parameterType
+ self.builtin = False
+
+ def __eq__(self, other):
+ return isinstance(other, IDLArrayType) and self.inner == other.inner
+
+ def __str__(self):
+ return self.inner.__str__() + "Array"
+
+ def nullable(self):
+ return False
+
+ def isPrimitive(self):
+ return False
+
+ def isString(self):
+ return False
+
+ def isByteString(self):
+ return False
+
+ def isDOMString(self):
+ return False
+
+ def isVoid(self):
+ return False
+
+ def isSequence(self):
+ assert not self.inner.isSequence()
+ return False
+
+ def isArray(self):
+ return True
+
+ def isDictionary(self):
+ assert not self.inner.isDictionary()
+ return False
+
+ def isInterface(self):
+ return False
+
+ def isEnum(self):
+ return False
+
+ def tag(self):
+ return IDLType.Tags.array
+
+ def resolveType(self, parentScope):
+ assert isinstance(parentScope, IDLScope)
+ self.inner.resolveType(parentScope)
+
+ def isComplete(self):
+ return self.inner.isComplete()
+
+ def complete(self, scope):
+ self.inner = self.inner.complete(scope)
+ self.name = self.inner.name
+
+ if self.inner.isDictionary():
+ raise WebIDLError("Array type must not contain "
+ "dictionary as element type.",
+ [self.inner.location])
+
+ assert not self.inner.isSequence()
+
+ return self
+
+ def unroll(self):
+ return self.inner.unroll()
+
+ def isDistinguishableFrom(self, other):
+ if other.isUnion():
+ # Just forward to the union; it'll deal
+ return other.isDistinguishableFrom(self)
+ return (other.isPrimitive() or other.isString() or other.isEnum() or
+ other.isDate() or other.isNonCallbackInterface())
+
+ def _getDependentObjects(self):
+ return self.inner._getDependentObjects()
+
+class IDLTypedefType(IDLType, IDLObjectWithIdentifier):
+ def __init__(self, location, innerType, name):
+ IDLType.__init__(self, location, innerType.name)
+
+ identifier = IDLUnresolvedIdentifier(location, name)
+
+ IDLObjectWithIdentifier.__init__(self, location, None, identifier)
+
+ self.inner = innerType
+ self.name = name
+ self.builtin = False
+
+ def __eq__(self, other):
+ return isinstance(other, IDLTypedefType) and self.inner == other.inner
+
+ def __str__(self):
+ return self.identifier.name
+
+ def nullable(self):
+ return self.inner.nullable()
+
+ def isPrimitive(self):
+ return self.inner.isPrimitive()
+
+ def isBoolean(self):
+ return self.inner.isBoolean()
+
+ def isNumeric(self):
+ return self.inner.isNumeric()
+
+ def isString(self):
+ return self.inner.isString()
+
+ def isByteString(self):
+ return self.inner.isByteString()
+
+ def isDOMString(self):
+ return self.inner.isDOMString()
+
+ def isVoid(self):
+ return self.inner.isVoid()
+
+ def isSequence(self):
+ return self.inner.isSequence()
+
+ def isArray(self):
+ return self.inner.isArray()
+
+ def isDictionary(self):
+ return self.inner.isDictionary()
+
+ def isArrayBuffer(self):
+ return self.inner.isArrayBuffer()
+
+ def isArrayBufferView(self):
+ return self.inner.isArrayBufferView()
+
+ def isTypedArray(self):
+ return self.inner.isTypedArray()
+
+ def isInterface(self):
+ return self.inner.isInterface()
+
+ def isCallbackInterface(self):
+ return self.inner.isCallbackInterface()
+
+ def isNonCallbackInterface(self):
+ return self.inner.isNonCallbackInterface()
+
+ def isComplete(self):
+ return False
+
+ def complete(self, parentScope):
+ if not self.inner.isComplete():
+ self.inner = self.inner.complete(parentScope)
+ assert self.inner.isComplete()
+ return self.inner
+
+ def finish(self, parentScope):
+ # Maybe the IDLObjectWithIdentifier for the typedef should be
+ # a separate thing from the type? If that happens, we can
+ # remove some hackery around avoiding isInterface() in
+ # Configuration.py.
+ self.complete(parentScope)
+
+ def validate(self):
+ pass
+
+ # Do we need a resolveType impl? I don't think it's particularly useful....
+
+ def tag(self):
+ return self.inner.tag()
+
+ def unroll(self):
+ return self.inner.unroll()
+
+ def isDistinguishableFrom(self, other):
+ return self.inner.isDistinguishableFrom(other)
+
+ def _getDependentObjects(self):
+ return self.inner._getDependentObjects()
+
+class IDLWrapperType(IDLType):
+ def __init__(self, location, inner):
+ IDLType.__init__(self, location, inner.identifier.name)
+ self.inner = inner
+ self._identifier = inner.identifier
+ self.builtin = False
+
+ def __eq__(self, other):
+ return isinstance(other, IDLWrapperType) and \
+ self._identifier == other._identifier and \
+ self.builtin == other.builtin
+
+ def __str__(self):
+ return str(self.name) + " (Wrapper)"
+
+ def nullable(self):
+ return False
+
+ def isPrimitive(self):
+ return False
+
+ def isString(self):
+ return False
+
+ def isByteString(self):
+ return False
+
+ def isDOMString(self):
+ return False
+
+ def isVoid(self):
+ return False
+
+ def isSequence(self):
+ return False
+
+ def isArray(self):
+ return False
+
+ def isDictionary(self):
+ return isinstance(self.inner, IDLDictionary)
+
+ def isInterface(self):
+ return isinstance(self.inner, IDLInterface) or \
+ isinstance(self.inner, IDLExternalInterface)
+
+ def isCallbackInterface(self):
+ return self.isInterface() and self.inner.isCallback()
+
+ def isNonCallbackInterface(self):
+ return self.isInterface() and not self.inner.isCallback()
+
+ def isEnum(self):
+ return isinstance(self.inner, IDLEnum)
+
+ def isPromise(self):
+ return isinstance(self.inner, IDLInterface) and \
+ self.inner.identifier.name == "Promise"
+
+ def isSerializable(self):
+ if self.isInterface():
+ if self.inner.isExternal():
+ return False
+ return any(m.isMethod() and m.isJsonifier() for m in self.inner.members)
+ elif self.isEnum():
+ return True
+ elif self.isDictionary():
+ return all(m.type.isSerializable() for m in self.inner.members)
+ else:
+ raise WebIDLError("IDLWrapperType wraps type %s that we don't know if "
+ "is serializable" % type(self.inner), [self.location])
+
+ def resolveType(self, parentScope):
+ assert isinstance(parentScope, IDLScope)
+ self.inner.resolve(parentScope)
+
+ def isComplete(self):
+ return True
+
+ def tag(self):
+ if self.isInterface():
+ return IDLType.Tags.interface
+ elif self.isEnum():
+ return IDLType.Tags.enum
+ elif self.isDictionary():
+ return IDLType.Tags.dictionary
+ else:
+ assert False
+
+ def isDistinguishableFrom(self, other):
+ if other.isUnion():
+ # Just forward to the union; it'll deal
+ return other.isDistinguishableFrom(self)
+ assert self.isInterface() or self.isEnum() or self.isDictionary()
+ if self.isEnum():
+ return (other.isPrimitive() or other.isInterface() or other.isObject() or
+ other.isCallback() or other.isDictionary() or
+ other.isSequence() or other.isArray() or
+ other.isDate())
+ if self.isDictionary() and other.nullable():
+ return False
+ if other.isPrimitive() or other.isString() or other.isEnum() or other.isDate():
+ return True
+ if self.isDictionary():
+ return other.isNonCallbackInterface()
+
+ assert self.isInterface()
+ if other.isInterface():
+ if other.isSpiderMonkeyInterface():
+ # Just let |other| handle things
+ return other.isDistinguishableFrom(self)
+ assert self.isGeckoInterface() and other.isGeckoInterface()
+ if self.inner.isExternal() or other.unroll().inner.isExternal():
+ return self != other
+ return (len(self.inner.interfacesBasedOnSelf &
+ other.unroll().inner.interfacesBasedOnSelf) == 0 and
+ (self.isNonCallbackInterface() or
+ other.isNonCallbackInterface()))
+ if (other.isDictionary() or other.isCallback() or
+ other.isSequence() or other.isArray()):
+ return self.isNonCallbackInterface()
+
+ # Not much else |other| can be
+ assert other.isObject()
+ return False
+
+ def _getDependentObjects(self):
+ # NB: The codegen for an interface type depends on
+ # a) That the identifier is in fact an interface (as opposed to
+ # a dictionary or something else).
+ # b) The native type of the interface.
+ # If we depend on the interface object we will also depend on
+ # anything the interface depends on which is undesirable. We
+ # considered implementing a dependency just on the interface type
+ # file, but then every modification to an interface would cause this
+ # to be regenerated which is still undesirable. We decided not to
+ # depend on anything, reasoning that:
+ # 1) Changing the concrete type of the interface requires modifying
+ # Bindings.conf, which is still a global dependency.
+ # 2) Changing an interface to a dictionary (or vice versa) with the
+ # same identifier should be incredibly rare.
+ return set()
+
+class IDLBuiltinType(IDLType):
+
+ Types = enum(
+ # The integer types
+ 'byte',
+ 'octet',
+ 'short',
+ 'unsigned_short',
+ 'long',
+ 'unsigned_long',
+ 'long_long',
+ 'unsigned_long_long',
+ # Additional primitive types
+ 'boolean',
+ 'unrestricted_float',
+ 'float',
+ 'unrestricted_double',
+ # IMPORTANT: "double" must be the last primitive type listed
+ 'double',
+ # Other types
+ 'any',
+ 'domstring',
+ 'bytestring',
+ 'object',
+ 'date',
+ 'void',
+ # Funny stuff
+ 'ArrayBuffer',
+ 'ArrayBufferView',
+ 'Int8Array',
+ 'Uint8Array',
+ 'Uint8ClampedArray',
+ 'Int16Array',
+ 'Uint16Array',
+ 'Int32Array',
+ 'Uint32Array',
+ 'Float32Array',
+ 'Float64Array'
+ )
+
+ TagLookup = {
+ Types.byte: IDLType.Tags.int8,
+ Types.octet: IDLType.Tags.uint8,
+ Types.short: IDLType.Tags.int16,
+ Types.unsigned_short: IDLType.Tags.uint16,
+ Types.long: IDLType.Tags.int32,
+ Types.unsigned_long: IDLType.Tags.uint32,
+ Types.long_long: IDLType.Tags.int64,
+ Types.unsigned_long_long: IDLType.Tags.uint64,
+ Types.boolean: IDLType.Tags.bool,
+ Types.unrestricted_float: IDLType.Tags.unrestricted_float,
+ Types.float: IDLType.Tags.float,
+ Types.unrestricted_double: IDLType.Tags.unrestricted_double,
+ Types.double: IDLType.Tags.double,
+ Types.any: IDLType.Tags.any,
+ Types.domstring: IDLType.Tags.domstring,
+ Types.bytestring: IDLType.Tags.bytestring,
+ Types.object: IDLType.Tags.object,
+ Types.date: IDLType.Tags.date,
+ Types.void: IDLType.Tags.void,
+ Types.ArrayBuffer: IDLType.Tags.interface,
+ Types.ArrayBufferView: IDLType.Tags.interface,
+ Types.Int8Array: IDLType.Tags.interface,
+ Types.Uint8Array: IDLType.Tags.interface,
+ Types.Uint8ClampedArray: IDLType.Tags.interface,
+ Types.Int16Array: IDLType.Tags.interface,
+ Types.Uint16Array: IDLType.Tags.interface,
+ Types.Int32Array: IDLType.Tags.interface,
+ Types.Uint32Array: IDLType.Tags.interface,
+ Types.Float32Array: IDLType.Tags.interface,
+ Types.Float64Array: IDLType.Tags.interface
+ }
+
+ def __init__(self, location, name, type):
+ IDLType.__init__(self, location, name)
+ self.builtin = True
+ self._typeTag = type
+
+ def isPrimitive(self):
+ return self._typeTag <= IDLBuiltinType.Types.double
+
+ def isBoolean(self):
+ return self._typeTag == IDLBuiltinType.Types.boolean
+
+ def isNumeric(self):
+ return self.isPrimitive() and not self.isBoolean()
+
+ def isString(self):
+ return self._typeTag == IDLBuiltinType.Types.domstring or \
+ self._typeTag == IDLBuiltinType.Types.bytestring
+
+ def isByteString(self):
+ return self._typeTag == IDLBuiltinType.Types.bytestring
+
+ def isDOMString(self):
+ return self._typeTag == IDLBuiltinType.Types.domstring
+
+ def isInteger(self):
+ return self._typeTag <= IDLBuiltinType.Types.unsigned_long_long
+
+ def isArrayBuffer(self):
+ return self._typeTag == IDLBuiltinType.Types.ArrayBuffer
+
+ def isArrayBufferView(self):
+ return self._typeTag == IDLBuiltinType.Types.ArrayBufferView
+
+ def isTypedArray(self):
+ return self._typeTag >= IDLBuiltinType.Types.Int8Array and \
+ self._typeTag <= IDLBuiltinType.Types.Float64Array
+
+ def isInterface(self):
+ # TypedArray things are interface types per the TypedArray spec,
+ # but we handle them as builtins because SpiderMonkey implements
+ # all of it internally.
+ return self.isArrayBuffer() or \
+ self.isArrayBufferView() or \
+ self.isTypedArray()
+
+ def isNonCallbackInterface(self):
+ # All the interfaces we can be are non-callback
+ return self.isInterface()
+
+ def isFloat(self):
+ return self._typeTag == IDLBuiltinType.Types.float or \
+ self._typeTag == IDLBuiltinType.Types.double or \
+ self._typeTag == IDLBuiltinType.Types.unrestricted_float or \
+ self._typeTag == IDLBuiltinType.Types.unrestricted_double
+
+ def isUnrestricted(self):
+ assert self.isFloat()
+ return self._typeTag == IDLBuiltinType.Types.unrestricted_float or \
+ self._typeTag == IDLBuiltinType.Types.unrestricted_double
+
+ def isSerializable(self):
+ return self.isPrimitive() or self.isDOMString() or self.isDate()
+
+ def includesRestrictedFloat(self):
+ return self.isFloat() and not self.isUnrestricted()
+
+ def tag(self):
+ return IDLBuiltinType.TagLookup[self._typeTag]
+
+ def isDistinguishableFrom(self, other):
+ if other.isUnion():
+ # Just forward to the union; it'll deal
+ return other.isDistinguishableFrom(self)
+ if self.isBoolean():
+ return (other.isNumeric() or other.isString() or other.isEnum() or
+ other.isInterface() or other.isObject() or
+ other.isCallback() or other.isDictionary() or
+ other.isSequence() or other.isArray() or
+ other.isDate())
+ if self.isNumeric():
+ return (other.isBoolean() or other.isString() or other.isEnum() or
+ other.isInterface() or other.isObject() or
+ other.isCallback() or other.isDictionary() or
+ other.isSequence() or other.isArray() or
+ other.isDate())
+ if self.isString():
+ return (other.isPrimitive() or other.isInterface() or
+ other.isObject() or
+ other.isCallback() or other.isDictionary() or
+ other.isSequence() or other.isArray() or
+ other.isDate())
+ if self.isAny():
+ # Can't tell "any" apart from anything
+ return False
+ if self.isObject():
+ return other.isPrimitive() or other.isString() or other.isEnum()
+ if self.isDate():
+ return (other.isPrimitive() or other.isString() or other.isEnum() or
+ other.isInterface() or other.isCallback() or
+ other.isDictionary() or other.isSequence() or
+ other.isArray())
+ if self.isVoid():
+ return not other.isVoid()
+ # Not much else we could be!
+ assert self.isSpiderMonkeyInterface()
+ # Like interfaces, but we know we're not a callback
+ return (other.isPrimitive() or other.isString() or other.isEnum() or
+ other.isCallback() or other.isDictionary() or
+ other.isSequence() or other.isArray() or other.isDate() or
+ (other.isInterface() and (
+ # ArrayBuffer is distinguishable from everything
+ # that's not an ArrayBuffer or a callback interface
+ (self.isArrayBuffer() and not other.isArrayBuffer()) or
+ # ArrayBufferView is distinguishable from everything
+ # that's not an ArrayBufferView or typed array.
+ (self.isArrayBufferView() and not other.isArrayBufferView() and
+ not other.isTypedArray()) or
+ # Typed arrays are distinguishable from everything
+ # except ArrayBufferView and the same type of typed
+ # array
+ (self.isTypedArray() and not other.isArrayBufferView() and not
+ (other.isTypedArray() and other.name == self.name)))))
+
+ def _getDependentObjects(self):
+ return set()
+
+BuiltinTypes = {
+ IDLBuiltinType.Types.byte:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Byte",
+ IDLBuiltinType.Types.byte),
+ IDLBuiltinType.Types.octet:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Octet",
+ IDLBuiltinType.Types.octet),
+ IDLBuiltinType.Types.short:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Short",
+ IDLBuiltinType.Types.short),
+ IDLBuiltinType.Types.unsigned_short:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnsignedShort",
+ IDLBuiltinType.Types.unsigned_short),
+ IDLBuiltinType.Types.long:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Long",
+ IDLBuiltinType.Types.long),
+ IDLBuiltinType.Types.unsigned_long:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnsignedLong",
+ IDLBuiltinType.Types.unsigned_long),
+ IDLBuiltinType.Types.long_long:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "LongLong",
+ IDLBuiltinType.Types.long_long),
+ IDLBuiltinType.Types.unsigned_long_long:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnsignedLongLong",
+ IDLBuiltinType.Types.unsigned_long_long),
+ IDLBuiltinType.Types.boolean:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Boolean",
+ IDLBuiltinType.Types.boolean),
+ IDLBuiltinType.Types.float:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float",
+ IDLBuiltinType.Types.float),
+ IDLBuiltinType.Types.unrestricted_float:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnrestrictedFloat",
+ IDLBuiltinType.Types.unrestricted_float),
+ IDLBuiltinType.Types.double:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Double",
+ IDLBuiltinType.Types.double),
+ IDLBuiltinType.Types.unrestricted_double:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnrestrictedDouble",
+ IDLBuiltinType.Types.unrestricted_double),
+ IDLBuiltinType.Types.any:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Any",
+ IDLBuiltinType.Types.any),
+ IDLBuiltinType.Types.domstring:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "String",
+ IDLBuiltinType.Types.domstring),
+ IDLBuiltinType.Types.bytestring:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "ByteString",
+ IDLBuiltinType.Types.bytestring),
+ IDLBuiltinType.Types.object:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Object",
+ IDLBuiltinType.Types.object),
+ IDLBuiltinType.Types.date:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Date",
+ IDLBuiltinType.Types.date),
+ IDLBuiltinType.Types.void:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Void",
+ IDLBuiltinType.Types.void),
+ IDLBuiltinType.Types.ArrayBuffer:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "ArrayBuffer",
+ IDLBuiltinType.Types.ArrayBuffer),
+ IDLBuiltinType.Types.ArrayBufferView:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "ArrayBufferView",
+ IDLBuiltinType.Types.ArrayBufferView),
+ IDLBuiltinType.Types.Int8Array:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int8Array",
+ IDLBuiltinType.Types.Int8Array),
+ IDLBuiltinType.Types.Uint8Array:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint8Array",
+ IDLBuiltinType.Types.Uint8Array),
+ IDLBuiltinType.Types.Uint8ClampedArray:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint8ClampedArray",
+ IDLBuiltinType.Types.Uint8ClampedArray),
+ IDLBuiltinType.Types.Int16Array:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int16Array",
+ IDLBuiltinType.Types.Int16Array),
+ IDLBuiltinType.Types.Uint16Array:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint16Array",
+ IDLBuiltinType.Types.Uint16Array),
+ IDLBuiltinType.Types.Int32Array:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int32Array",
+ IDLBuiltinType.Types.Int32Array),
+ IDLBuiltinType.Types.Uint32Array:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint32Array",
+ IDLBuiltinType.Types.Uint32Array),
+ IDLBuiltinType.Types.Float32Array:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float32Array",
+ IDLBuiltinType.Types.Float32Array),
+ IDLBuiltinType.Types.Float64Array:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float64Array",
+ IDLBuiltinType.Types.Float64Array)
+ }
+
+
+integerTypeSizes = {
+ IDLBuiltinType.Types.byte: (-128, 127),
+ IDLBuiltinType.Types.octet: (0, 255),
+ IDLBuiltinType.Types.short: (-32768, 32767),
+ IDLBuiltinType.Types.unsigned_short: (0, 65535),
+ IDLBuiltinType.Types.long: (-2147483648, 2147483647),
+ IDLBuiltinType.Types.unsigned_long: (0, 4294967295),
+ IDLBuiltinType.Types.long_long: (-9223372036854775808,
+ 9223372036854775807),
+ IDLBuiltinType.Types.unsigned_long_long: (0, 18446744073709551615)
+ }
+
+def matchIntegerValueToType(value):
+ for type, extremes in integerTypeSizes.items():
+ (min, max) = extremes
+ if value <= max and value >= min:
+ return BuiltinTypes[type]
+
+ return None
+
+class IDLValue(IDLObject):
+ def __init__(self, location, type, value):
+ IDLObject.__init__(self, location)
+ self.type = type
+ assert isinstance(type, IDLType)
+
+ self.value = value
+
+ def coerceToType(self, type, location):
+ if type == self.type:
+ return self # Nothing to do
+
+ # We first check for unions to ensure that even if the union is nullable
+ # we end up with the right flat member type, not the union's type.
+ if type.isUnion():
+ # We use the flat member types here, because if we have a nullable
+ # member type, or a nested union, we want the type the value
+ # actually coerces to, not the nullable or nested union type.
+ for subtype in type.unroll().flatMemberTypes:
+ try:
+ coercedValue = self.coerceToType(subtype, location)
+ # Create a new IDLValue to make sure that we have the
+ # correct float/double type. This is necessary because we
+ # use the value's type when it is a default value of a
+ # union, and the union cares about the exact float type.
+ return IDLValue(self.location, subtype, coercedValue.value)
+ except:
+ pass
+ # If the type allows null, rerun this matching on the inner type, except
+ # nullable enums. We handle those specially, because we want our
+ # default string values to stay strings even when assigned to a nullable
+ # enum.
+ elif type.nullable() and not type.isEnum():
+ innerValue = self.coerceToType(type.inner, location)
+ return IDLValue(self.location, type, innerValue.value)
+
+ elif self.type.isInteger() and type.isInteger():
+ # We're both integer types. See if we fit.
+
+ (min, max) = integerTypeSizes[type._typeTag]
+ if self.value <= max and self.value >= min:
+ # Promote
+ return IDLValue(self.location, type, self.value)
+ else:
+ raise WebIDLError("Value %s is out of range for type %s." %
+ (self.value, type), [location])
+ elif self.type.isInteger() and type.isFloat():
+ # Convert an integer literal into float
+ if -2**24 <= self.value <= 2**24:
+ floatType = BuiltinTypes[IDLBuiltinType.Types.float]
+ return IDLValue(self.location, floatType, float(self.value))
+ else:
+ raise WebIDLError("Converting value %s to %s will lose precision." %
+ (self.value, type), [location])
+ elif self.type.isString() and type.isEnum():
+ # Just keep our string, but make sure it's a valid value for this enum
+ enum = type.unroll().inner
+ if self.value not in enum.values():
+ raise WebIDLError("'%s' is not a valid default value for enum %s"
+ % (self.value, enum.identifier.name),
+ [location, enum.location])
+ return self
+ elif self.type.isFloat() and type.isFloat():
+ if (not type.isUnrestricted() and
+ (self.value == float("inf") or self.value == float("-inf") or
+ math.isnan(self.value))):
+ raise WebIDLError("Trying to convert unrestricted value %s to non-unrestricted"
+ % self.value, [location]);
+ return self
+ raise WebIDLError("Cannot coerce type %s to type %s." %
+ (self.type, type), [location])
+
+ def _getDependentObjects(self):
+ return set()
+
+class IDLNullValue(IDLObject):
+ def __init__(self, location):
+ IDLObject.__init__(self, location)
+ self.type = None
+ self.value = None
+
+ def coerceToType(self, type, location):
+ if (not isinstance(type, IDLNullableType) and
+ not (type.isUnion() and type.hasNullableType) and
+ not (type.isUnion() and type.hasDictionaryType) and
+ not type.isDictionary() and
+ not type.isAny()):
+ raise WebIDLError("Cannot coerce null value to type %s." % type,
+ [location])
+
+ nullValue = IDLNullValue(self.location)
+ if type.isUnion() and not type.nullable() and type.hasDictionaryType:
+ # We're actually a default value for the union's dictionary member.
+ # Use its type.
+ for t in type.flatMemberTypes:
+ if t.isDictionary():
+ nullValue.type = t
+ return nullValue
+ nullValue.type = type
+ return nullValue
+
+ def _getDependentObjects(self):
+ return set()
+
+class IDLUndefinedValue(IDLObject):
+ def __init__(self, location):
+ IDLObject.__init__(self, location)
+ self.type = None
+ self.value = None
+
+ def coerceToType(self, type, location):
+ if not type.isAny():
+ raise WebIDLError("Cannot coerce undefined value to type %s." % type,
+ [location])
+
+ undefinedValue = IDLUndefinedValue(self.location)
+ undefinedValue.type = type
+ return undefinedValue
+
+ def _getDependentObjects(self):
+ return set()
+
+class IDLInterfaceMember(IDLObjectWithIdentifier):
+
+ Tags = enum(
+ 'Const',
+ 'Attr',
+ 'Method'
+ )
+
+ Special = enum(
+ 'Static',
+ 'Stringifier'
+ )
+
+ def __init__(self, location, identifier, tag):
+ IDLObjectWithIdentifier.__init__(self, location, None, identifier)
+ self.tag = tag
+ self._extendedAttrDict = {}
+
+ def isMethod(self):
+ return self.tag == IDLInterfaceMember.Tags.Method
+
+ def isAttr(self):
+ return self.tag == IDLInterfaceMember.Tags.Attr
+
+ def isConst(self):
+ return self.tag == IDLInterfaceMember.Tags.Const
+
+ def addExtendedAttributes(self, attrs):
+ for attr in attrs:
+ self.handleExtendedAttribute(attr)
+ attrlist = attr.listValue()
+ self._extendedAttrDict[attr.identifier()] = attrlist if len(attrlist) else True
+
+ def handleExtendedAttribute(self, attr):
+ pass
+
+ def getExtendedAttribute(self, name):
+ return self._extendedAttrDict.get(name, None)
+
+class IDLConst(IDLInterfaceMember):
+ def __init__(self, location, identifier, type, value):
+ IDLInterfaceMember.__init__(self, location, identifier,
+ IDLInterfaceMember.Tags.Const)
+
+ assert isinstance(type, IDLType)
+ if type.isDictionary():
+ raise WebIDLError("A constant cannot be of a dictionary type",
+ [self.location])
+ self.type = type
+ self.value = value
+
+ if identifier.name == "prototype":
+ raise WebIDLError("The identifier of a constant must not be 'prototype'",
+ [location])
+
+ def __str__(self):
+ return "'%s' const '%s'" % (self.type, self.identifier)
+
+ def finish(self, scope):
+ if not self.type.isComplete():
+ type = self.type.complete(scope)
+ if not type.isPrimitive() and not type.isString():
+ locations = [self.type.location, type.location]
+ try:
+ locations.append(type.inner.location)
+ except:
+ pass
+ raise WebIDLError("Incorrect type for constant", locations)
+ self.type = type
+
+ # The value might not match the type
+ coercedValue = self.value.coerceToType(self.type, self.location)
+ assert coercedValue
+
+ self.value = coercedValue
+
+ def validate(self):
+ pass
+
+ def _getDependentObjects(self):
+ return set([self.type, self.value])
+
+class IDLAttribute(IDLInterfaceMember):
+ def __init__(self, location, identifier, type, readonly, inherit=False,
+ static=False, stringifier=False):
+ IDLInterfaceMember.__init__(self, location, identifier,
+ IDLInterfaceMember.Tags.Attr)
+
+ assert isinstance(type, IDLType)
+ self.type = type
+ self.readonly = readonly
+ self.inherit = inherit
+ self.static = static
+ self.lenientThis = False
+ self._unforgeable = False
+ self.stringifier = stringifier
+ self.enforceRange = False
+ self.clamp = False
+ self.slotIndex = None
+
+ if static and identifier.name == "prototype":
+ raise WebIDLError("The identifier of a static attribute must not be 'prototype'",
+ [location])
+
+ if readonly and inherit:
+ raise WebIDLError("An attribute cannot be both 'readonly' and 'inherit'",
+ [self.location])
+
+ def isStatic(self):
+ return self.static
+
+ def __str__(self):
+ return "'%s' attribute '%s'" % (self.type, self.identifier)
+
+ def finish(self, scope):
+ if not self.type.isComplete():
+ t = self.type.complete(scope)
+
+ assert not isinstance(t, IDLUnresolvedType)
+ assert not isinstance(t, IDLTypedefType)
+ assert not isinstance(t.name, IDLUnresolvedIdentifier)
+ self.type = t
+
+ if self.type.isDictionary() and not self.getExtendedAttribute("Cached"):
+ raise WebIDLError("An attribute cannot be of a dictionary type",
+ [self.location])
+ if self.type.isSequence() and not self.getExtendedAttribute("Cached"):
+ raise WebIDLError("A non-cached attribute cannot be of a sequence "
+ "type", [self.location])
+ if self.type.isUnion():
+ for f in self.type.unroll().flatMemberTypes:
+ if f.isDictionary():
+ raise WebIDLError("An attribute cannot be of a union "
+ "type if one of its member types (or "
+ "one of its member types's member "
+ "types, and so on) is a dictionary "
+ "type", [self.location, f.location])
+ if f.isSequence():
+ raise WebIDLError("An attribute cannot be of a union "
+ "type if one of its member types (or "
+ "one of its member types's member "
+ "types, and so on) is a sequence "
+ "type", [self.location, f.location])
+ if not self.type.isInterface() and self.getExtendedAttribute("PutForwards"):
+ raise WebIDLError("An attribute with [PutForwards] must have an "
+ "interface type as its type", [self.location])
+
+ if not self.type.isInterface() and self.getExtendedAttribute("SameObject"):
+ raise WebIDLError("An attribute with [SameObject] must have an "
+ "interface type as its type", [self.location])
+
+ def validate(self):
+ if ((self.getExtendedAttribute("Cached") or
+ self.getExtendedAttribute("StoreInSlot")) and
+ not self.getExtendedAttribute("Constant") and
+ not self.getExtendedAttribute("Pure")):
+ raise WebIDLError("Cached attributes and attributes stored in "
+ "slots must be constant or pure, since the "
+ "getter won't always be called.",
+ [self.location])
+ if self.getExtendedAttribute("Frozen"):
+ if not self.type.isSequence() and not self.type.isDictionary():
+ raise WebIDLError("[Frozen] is only allowed on sequence-valued "
+ "and dictionary-valued attributes",
+ [self.location])
+
+ def handleExtendedAttribute(self, attr):
+ identifier = attr.identifier()
+ if identifier == "SetterThrows" and self.readonly:
+ raise WebIDLError("Readonly attributes must not be flagged as "
+ "[SetterThrows]",
+ [self.location])
+ elif (((identifier == "Throws" or identifier == "GetterThrows") and
+ self.getExtendedAttribute("StoreInSlot")) or
+ (identifier == "StoreInSlot" and
+ (self.getExtendedAttribute("Throws") or
+ self.getExtendedAttribute("GetterThrows")))):
+ raise WebIDLError("Throwing things can't be [Pure] or [Constant] "
+ "or [SameObject] or [StoreInSlot]",
+ [attr.location])
+ elif identifier == "LenientThis":
+ if not attr.noArguments():
+ raise WebIDLError("[LenientThis] must take no arguments",
+ [attr.location])
+ if self.isStatic():
+ raise WebIDLError("[LenientThis] is only allowed on non-static "
+ "attributes", [attr.location, self.location])
+ if self.getExtendedAttribute("CrossOriginReadable"):
+ raise WebIDLError("[LenientThis] is not allowed in combination "
+ "with [CrossOriginReadable]",
+ [attr.location, self.location])
+ if self.getExtendedAttribute("CrossOriginWritable"):
+ raise WebIDLError("[LenientThis] is not allowed in combination "
+ "with [CrossOriginWritable]",
+ [attr.location, self.location])
+ self.lenientThis = True
+ elif identifier == "Unforgeable":
+ if not self.readonly:
+ raise WebIDLError("[Unforgeable] is only allowed on readonly "
+ "attributes", [attr.location, self.location])
+ if self.isStatic():
+ raise WebIDLError("[Unforgeable] is only allowed on non-static "
+ "attributes", [attr.location, self.location])
+ self._unforgeable = True
+ elif identifier == "SameObject" and not self.readonly:
+ raise WebIDLError("[SameObject] only allowed on readonly attributes",
+ [attr.location, self.location])
+ elif identifier == "Constant" and not self.readonly:
+ raise WebIDLError("[Constant] only allowed on readonly attributes",
+ [attr.location, self.location])
+ elif identifier == "PutForwards":
+ if not self.readonly:
+ raise WebIDLError("[PutForwards] is only allowed on readonly "
+ "attributes", [attr.location, self.location])
+ if self.isStatic():
+ raise WebIDLError("[PutForwards] is only allowed on non-static "
+ "attributes", [attr.location, self.location])
+ if self.getExtendedAttribute("Replaceable") is not None:
+ raise WebIDLError("[PutForwards] and [Replaceable] can't both "
+ "appear on the same attribute",
+ [attr.location, self.location])
+ if not attr.hasValue():
+ raise WebIDLError("[PutForwards] takes an identifier",
+ [attr.location, self.location])
+ elif identifier == "Replaceable":
+ if self.getExtendedAttribute("PutForwards") is not None:
+ raise WebIDLError("[PutForwards] and [Replaceable] can't both "
+ "appear on the same attribute",
+ [attr.location, self.location])
+ elif identifier == "LenientFloat":
+ if self.readonly:
+ raise WebIDLError("[LenientFloat] used on a readonly attribute",
+ [attr.location, self.location])
+ if not self.type.includesRestrictedFloat():
+ raise WebIDLError("[LenientFloat] used on an attribute with a "
+ "non-restricted-float type",
+ [attr.location, self.location])
+ elif identifier == "EnforceRange":
+ if self.readonly:
+ raise WebIDLError("[EnforceRange] used on a readonly attribute",
+ [attr.location, self.location])
+ self.enforceRange = True
+ elif identifier == "Clamp":
+ if self.readonly:
+ raise WebIDLError("[Clamp] used on a readonly attribute",
+ [attr.location, self.location])
+ self.clamp = True
+ elif identifier == "StoreInSlot":
+ if self.getExtendedAttribute("Cached"):
+ raise WebIDLError("[StoreInSlot] and [Cached] must not be "
+ "specified on the same attribute",
+ [attr.location, self.location])
+ elif identifier == "Cached":
+ if self.getExtendedAttribute("StoreInSlot"):
+ raise WebIDLError("[Cached] and [StoreInSlot] must not be "
+ "specified on the same attribute",
+ [attr.location, self.location])
+ elif (identifier == "CrossOriginReadable" or
+ identifier == "CrossOriginWritable"):
+ if not attr.noArguments():
+ raise WebIDLError("[%s] must take no arguments" % identifier,
+ [attr.location])
+ if self.isStatic():
+ raise WebIDLError("[%s] is only allowed on non-static "
+ "attributes" % identifier,
+ [attr.location, self.location])
+ if self.getExtendedAttribute("LenientThis"):
+ raise WebIDLError("[LenientThis] is not allowed in combination "
+ "with [%s]" % identifier,
+ [attr.location, self.location])
+ elif (identifier == "Pref" or
+ identifier == "SetterThrows" or
+ identifier == "Pure" or
+ identifier == "Throws" or
+ identifier == "GetterThrows" or
+ identifier == "ChromeOnly" or
+ identifier == "SameObject" or
+ identifier == "Constant" or
+ identifier == "Func" or
+ identifier == "Frozen" or
+ identifier == "AvailableIn" or
+ identifier == "Const" or
+ identifier == "Value" or
+ identifier == "NewObject"):
+ # Known attributes that we don't need to do anything with here
+ pass
+ else:
+ raise WebIDLError("Unknown extended attribute %s on attribute" % identifier,
+ [attr.location])
+ IDLInterfaceMember.handleExtendedAttribute(self, attr)
+
+ def resolve(self, parentScope):
+ assert isinstance(parentScope, IDLScope)
+ self.type.resolveType(parentScope)
+ IDLObjectWithIdentifier.resolve(self, parentScope)
+
+ def addExtendedAttributes(self, attrs):
+ attrs = self.checkForStringHandlingExtendedAttributes(attrs)
+ IDLInterfaceMember.addExtendedAttributes(self, attrs)
+
+ def hasLenientThis(self):
+ return self.lenientThis
+
+ def isUnforgeable(self):
+ return self._unforgeable
+
+ def _getDependentObjects(self):
+ return set([self.type])
+
+class IDLArgument(IDLObjectWithIdentifier):
+ def __init__(self, location, identifier, type, optional=False, defaultValue=None, variadic=False, dictionaryMember=False):
+ IDLObjectWithIdentifier.__init__(self, location, None, identifier)
+
+ assert isinstance(type, IDLType)
+ self.type = type
+
+ self.optional = optional
+ self.defaultValue = defaultValue
+ self.variadic = variadic
+ self.dictionaryMember = dictionaryMember
+ self._isComplete = False
+ self.enforceRange = False
+ self.clamp = False
+ self._allowTreatNonCallableAsNull = False
+
+ self._extraAttributes = {}
+
+ assert not variadic or optional
+
+ def getExtendedAttribute(self, name):
+ return self._extraAttributes.get(name)
+
+ def addExtendedAttributes(self, attrs):
+ attrs = self.checkForStringHandlingExtendedAttributes(
+ attrs,
+ isDictionaryMember=self.dictionaryMember,
+ isOptional=self.optional)
+ for attribute in attrs:
+ identifier = attribute.identifier()
+ if identifier == "Clamp":
+ if not attribute.noArguments():
+ raise WebIDLError("[Clamp] must take no arguments",
+ [attribute.location])
+ if self.enforceRange:
+ raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
+ [self.location]);
+ self.clamp = True
+ elif identifier == "EnforceRange":
+ if not attribute.noArguments():
+ raise WebIDLError("[EnforceRange] must take no arguments",
+ [attribute.location])
+ if self.clamp:
+ raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
+ [self.location]);
+ self.enforceRange = True
+ elif identifier == "TreatNonCallableAsNull":
+ self._allowTreatNonCallableAsNull = True
+ elif identifier in ['Ref', 'Const']:
+ # ok in emscripten
+ self._extraAttributes[identifier] = True
+ else:
+ raise WebIDLError("Unhandled extended attribute on an argument",
+ [attribute.location])
+
+ def isComplete(self):
+ return self._isComplete
+
+ def complete(self, scope):
+ if self._isComplete:
+ return
+
+ self._isComplete = True
+
+ if not self.type.isComplete():
+ type = self.type.complete(scope)
+ assert not isinstance(type, IDLUnresolvedType)
+ assert not isinstance(type, IDLTypedefType)
+ assert not isinstance(type.name, IDLUnresolvedIdentifier)
+ self.type = type
+
+ if ((self.type.isDictionary() or
+ self.type.isUnion() and self.type.unroll().hasDictionaryType) and
+ self.optional and not self.defaultValue):
+ # Default optional dictionaries to null, for simplicity,
+ # so the codegen doesn't have to special-case this.
+ self.defaultValue = IDLNullValue(self.location)
+ elif self.type.isAny():
+ assert (self.defaultValue is None or
+ isinstance(self.defaultValue, IDLNullValue))
+ # optional 'any' values always have a default value
+ if self.optional and not self.defaultValue and not self.variadic:
+ # Set the default value to undefined, for simplicity, so the
+ # codegen doesn't have to special-case this.
+ self.defaultValue = IDLUndefinedValue(self.location)
+
+ # Now do the coercing thing; this needs to happen after the
+ # above creation of a default value.
+ if self.defaultValue:
+ self.defaultValue = self.defaultValue.coerceToType(self.type,
+ self.location)
+ assert self.defaultValue
+
+ def allowTreatNonCallableAsNull(self):
+ return self._allowTreatNonCallableAsNull
+
+ def _getDependentObjects(self):
+ deps = set([self.type])
+ if self.defaultValue:
+ deps.add(self.defaultValue)
+ return deps
+
+class IDLCallbackType(IDLType, IDLObjectWithScope):
+ def __init__(self, location, parentScope, identifier, returnType, arguments):
+ assert isinstance(returnType, IDLType)
+
+ IDLType.__init__(self, location, identifier.name)
+
+ self._returnType = returnType
+ # Clone the list
+ self._arguments = list(arguments)
+
+ IDLObjectWithScope.__init__(self, location, parentScope, identifier)
+
+ for (returnType, arguments) in self.signatures():
+ for argument in arguments:
+ argument.resolve(self)
+
+ self._treatNonCallableAsNull = False
+ self._treatNonObjectAsNull = False
+
+ def isCallback(self):
+ return True
+
+ def signatures(self):
+ return [(self._returnType, self._arguments)]
+
+ def tag(self):
+ return IDLType.Tags.callback
+
+ def finish(self, scope):
+ if not self._returnType.isComplete():
+ type = self._returnType.complete(scope)
+
+ assert not isinstance(type, IDLUnresolvedType)
+ assert not isinstance(type, IDLTypedefType)
+ assert not isinstance(type.name, IDLUnresolvedIdentifier)
+ self._returnType = type
+
+ for argument in self._arguments:
+ if argument.type.isComplete():
+ continue
+
+ type = argument.type.complete(scope)
+
+ assert not isinstance(type, IDLUnresolvedType)
+ assert not isinstance(type, IDLTypedefType)
+ assert not isinstance(type.name, IDLUnresolvedIdentifier)
+ argument.type = type
+
+ def validate(self):
+ pass
+
+ def isDistinguishableFrom(self, other):
+ if other.isUnion():
+ # Just forward to the union; it'll deal
+ return other.isDistinguishableFrom(self)
+ return (other.isPrimitive() or other.isString() or other.isEnum() or
+ other.isNonCallbackInterface() or other.isDate())
+
+ def addExtendedAttributes(self, attrs):
+ unhandledAttrs = []
+ for attr in attrs:
+ if attr.identifier() == "TreatNonCallableAsNull":
+ self._treatNonCallableAsNull = True
+ elif attr.identifier() == "TreatNonObjectAsNull":
+ self._treatNonObjectAsNull = True
+ else:
+ unhandledAttrs.append(attr)
+ if self._treatNonCallableAsNull and self._treatNonObjectAsNull:
+ raise WebIDLError("Cannot specify both [TreatNonCallableAsNull] "
+ "and [TreatNonObjectAsNull]", [self.location])
+ if len(unhandledAttrs) != 0:
+ IDLType.addExtendedAttributes(self, unhandledAttrs)
+
+ def _getDependentObjects(self):
+ return set([self._returnType] + self._arguments)
+
+class IDLMethodOverload:
+ """
+ A class that represents a single overload of a WebIDL method. This is not
+ quite the same as an element of the "effective overload set" in the spec,
+ because separate IDLMethodOverloads are not created based on arguments being
+ optional. Rather, when multiple methods have the same name, there is an
+ IDLMethodOverload for each one, all hanging off an IDLMethod representing
+ the full set of overloads.
+ """
+ def __init__(self, returnType, arguments, location):
+ self.returnType = returnType
+ # Clone the list of arguments, just in case
+ self.arguments = list(arguments)
+ self.location = location
+
+ def _getDependentObjects(self):
+ deps = set(self.arguments)
+ deps.add(self.returnType)
+ return deps
+
+class IDLMethod(IDLInterfaceMember, IDLScope):
+
+ Special = enum(
+ 'Getter',
+ 'Setter',
+ 'Creator',
+ 'Deleter',
+ 'LegacyCaller',
+ base=IDLInterfaceMember.Special
+ )
+
+ TypeSuffixModifier = enum(
+ 'None',
+ 'QMark',
+ 'Brackets'
+ )
+
+ NamedOrIndexed = enum(
+ 'Neither',
+ 'Named',
+ 'Indexed'
+ )
+
+ def __init__(self, location, identifier, returnType, arguments,
+ static=False, getter=False, setter=False, creator=False,
+ deleter=False, specialType=NamedOrIndexed.Neither,
+ legacycaller=False, stringifier=False, jsonifier=False):
+ # REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
+ IDLInterfaceMember.__init__(self, location, identifier,
+ IDLInterfaceMember.Tags.Method)
+
+ self._hasOverloads = False
+
+ assert isinstance(returnType, IDLType)
+
+ # self._overloads is a list of IDLMethodOverloads
+ self._overloads = [IDLMethodOverload(returnType, arguments, location)]
+
+ assert isinstance(static, bool)
+ self._static = static
+ assert isinstance(getter, bool)
+ self._getter = getter
+ assert isinstance(setter, bool)
+ self._setter = setter
+ assert isinstance(creator, bool)
+ self._creator = creator
+ assert isinstance(deleter, bool)
+ self._deleter = deleter
+ assert isinstance(legacycaller, bool)
+ self._legacycaller = legacycaller
+ assert isinstance(stringifier, bool)
+ self._stringifier = stringifier
+ assert isinstance(jsonifier, bool)
+ self._jsonifier = jsonifier
+ self._specialType = specialType
+
+ if static and identifier.name == "prototype":
+ raise WebIDLError("The identifier of a static operation must not be 'prototype'",
+ [location])
+
+ self.assertSignatureConstraints()
+
+ def __str__(self):
+ return "Method '%s'" % self.identifier
+
+ def assertSignatureConstraints(self):
+ if self._getter or self._deleter:
+ assert len(self._overloads) == 1
+ overload = self._overloads[0]
+ arguments = overload.arguments
+ assert len(arguments) == 1
+ assert arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.domstring] or \
+ arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]
+ assert not arguments[0].optional and not arguments[0].variadic
+ assert not self._getter or not overload.returnType.isVoid()
+
+ if self._setter or self._creator:
+ assert len(self._overloads) == 1
+ arguments = self._overloads[0].arguments
+ assert len(arguments) == 2
+ assert arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.domstring] or \
+ arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]
+ assert not arguments[0].optional and not arguments[0].variadic
+ assert not arguments[1].optional and not arguments[1].variadic
+
+ if self._stringifier:
+ assert len(self._overloads) == 1
+ overload = self._overloads[0]
+ assert len(overload.arguments) == 0
+ assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.domstring]
+
+ if self._jsonifier:
+ assert len(self._overloads) == 1
+ overload = self._overloads[0]
+ assert len(overload.arguments) == 0
+ assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.object]
+
+ def isStatic(self):
+ return self._static
+
+ def isGetter(self):
+ return self._getter
+
+ def isSetter(self):
+ return self._setter
+
+ def isCreator(self):
+ return self._creator
+
+ def isDeleter(self):
+ return self._deleter
+
+ def isNamed(self):
+ assert self._specialType == IDLMethod.NamedOrIndexed.Named or \
+ self._specialType == IDLMethod.NamedOrIndexed.Indexed
+ return self._specialType == IDLMethod.NamedOrIndexed.Named
+
+ def isIndexed(self):
+ assert self._specialType == IDLMethod.NamedOrIndexed.Named or \
+ self._specialType == IDLMethod.NamedOrIndexed.Indexed
+ return self._specialType == IDLMethod.NamedOrIndexed.Indexed
+
+ def isLegacycaller(self):
+ return self._legacycaller
+
+ def isStringifier(self):
+ return self._stringifier
+
+ def isJsonifier(self):
+ return self._jsonifier
+
+ def hasOverloads(self):
+ return self._hasOverloads
+
+ def isIdentifierLess(self):
+ return self.identifier.name[:2] == "__" and self.identifier.name != "__noSuchMethod__"
+
+ def resolve(self, parentScope):
+ assert isinstance(parentScope, IDLScope)
+ IDLObjectWithIdentifier.resolve(self, parentScope)
+ IDLScope.__init__(self, self.location, parentScope, self.identifier)
+ for (returnType, arguments) in self.signatures():
+ for argument in arguments:
+ argument.resolve(self)
+
+ def addOverload(self, method):
+ assert len(method._overloads) == 1
+
+ if self._extendedAttrDict != method ._extendedAttrDict:
+ raise WebIDLError("Extended attributes differ on different "
+ "overloads of %s" % method.identifier,
+ [self.location, method.location])
+
+ self._overloads.extend(method._overloads)
+
+ self._hasOverloads = True
+
+ if self.isStatic() != method.isStatic():
+ raise WebIDLError("Overloaded identifier %s appears with different values of the 'static' attribute" % method.identifier,
+ [method.location])
+
+ if self.isLegacycaller() != method.isLegacycaller():
+ raise WebIDLError("Overloaded identifier %s appears with different values of the 'legacycaller' attribute" % method.identifier,
+ [method.location])
+
+ # Can't overload special things!
+ assert not self.isGetter()
+ assert not method.isGetter()
+ assert not self.isSetter()
+ assert not method.isSetter()
+ assert not self.isCreator()
+ assert not method.isCreator()
+ assert not self.isDeleter()
+ assert not method.isDeleter()
+ assert not self.isStringifier()
+ assert not method.isStringifier()
+ assert not self.isJsonifier()
+ assert not method.isJsonifier()
+
+ return self
+
+ def signatures(self):
+ return [(overload.returnType, overload.arguments) for overload in
+ self._overloads]
+
+ def finish(self, scope):
+ overloadWithPromiseReturnType = None
+ overloadWithoutPromiseReturnType = None
+ for overload in self._overloads:
+ variadicArgument = None
+
+ arguments = overload.arguments
+ for (idx, argument) in enumerate(arguments):
+ if not argument.isComplete():
+ argument.complete(scope)
+ assert argument.type.isComplete()
+
+ if (argument.type.isDictionary() or
+ (argument.type.isUnion() and
+ argument.type.unroll().hasDictionaryType)):
+ # Dictionaries and unions containing dictionaries at the
+ # end of the list or followed by optional arguments must be
+ # optional.
+ if (not argument.optional and
+ all(arg.optional for arg in arguments[idx+1:])):
+ raise WebIDLError("Dictionary argument or union "
+ "argument containing a dictionary "
+ "not followed by a required argument "
+ "must be optional",
+ [argument.location])
+
+ # An argument cannot be a Nullable Dictionary
+ if argument.type.nullable():
+ raise WebIDLError("An argument cannot be a nullable "
+ "dictionary or nullable union "
+ "containing a dictionary",
+ [argument.location])
+
+ # Only the last argument can be variadic
+ if variadicArgument:
+ raise WebIDLError("Variadic argument is not last argument",
+ [variadicArgument.location])
+ if argument.variadic:
+ variadicArgument = argument
+
+ returnType = overload.returnType
+ if not returnType.isComplete():
+ returnType = returnType.complete(scope)
+ assert not isinstance(returnType, IDLUnresolvedType)
+ assert not isinstance(returnType, IDLTypedefType)
+ assert not isinstance(returnType.name, IDLUnresolvedIdentifier)
+ overload.returnType = returnType
+
+ if returnType.isPromise():
+ overloadWithPromiseReturnType = overload
+ else:
+ overloadWithoutPromiseReturnType = overload
+
+ # Make sure either all our overloads return Promises or none do
+ if overloadWithPromiseReturnType and overloadWithoutPromiseReturnType:
+ raise WebIDLError("We have overloads with both Promise and "
+ "non-Promise return types",
+ [overloadWithPromiseReturnType.location,
+ overloadWithoutPromiseReturnType.location])
+
+ if overloadWithPromiseReturnType and self._legacycaller:
+ raise WebIDLError("May not have a Promise return type for a "
+ "legacycaller.",
+ [overloadWithPromiseReturnType.location])
+
+ # Now compute various information that will be used by the
+ # WebIDL overload resolution algorithm.
+ self.maxArgCount = max(len(s[1]) for s in self.signatures())
+ self.allowedArgCounts = [ i for i in range(self.maxArgCount+1)
+ if len(self.signaturesForArgCount(i)) != 0 ]
+
+ def validate(self):
+ # Make sure our overloads are properly distinguishable and don't have
+ # different argument types before the distinguishing args.
+ for argCount in self.allowedArgCounts:
+ possibleOverloads = self.overloadsForArgCount(argCount)
+ if len(possibleOverloads) == 1:
+ continue
+ distinguishingIndex = self.distinguishingIndexForArgCount(argCount)
+ for idx in range(distinguishingIndex):
+ firstSigType = possibleOverloads[0].arguments[idx].type
+ for overload in possibleOverloads[1:]:
+ if overload.arguments[idx].type != firstSigType:
+ raise WebIDLError(
+ "Signatures for method '%s' with %d arguments have "
+ "different types of arguments at index %d, which "
+ "is before distinguishing index %d" %
+ (self.identifier.name, argCount, idx,
+ distinguishingIndex),
+ [self.location, overload.location])
+
+ def overloadsForArgCount(self, argc):
+ return [overload for overload in self._overloads if
+ len(overload.arguments) == argc or
+ (len(overload.arguments) > argc and
+ all(arg.optional for arg in overload.arguments[argc:])) or
+ (len(overload.arguments) < argc and
+ len(overload.arguments) > 0 and
+ overload.arguments[-1].variadic)]
+
+ def signaturesForArgCount(self, argc):
+ return [(overload.returnType, overload.arguments) for overload
+ in self.overloadsForArgCount(argc)]
+
+ def locationsForArgCount(self, argc):
+ return [overload.location for overload in self.overloadsForArgCount(argc)]
+
+ def distinguishingIndexForArgCount(self, argc):
+ def isValidDistinguishingIndex(idx, signatures):
+ for (firstSigIndex, (firstRetval, firstArgs)) in enumerate(signatures[:-1]):
+ for (secondRetval, secondArgs) in signatures[firstSigIndex+1:]:
+ if idx < len(firstArgs):
+ firstType = firstArgs[idx].type
+ else:
+ assert(firstArgs[-1].variadic)
+ firstType = firstArgs[-1].type
+ if idx < len(secondArgs):
+ secondType = secondArgs[idx].type
+ else:
+ assert(secondArgs[-1].variadic)
+ secondType = secondArgs[-1].type
+ if not firstType.isDistinguishableFrom(secondType):
+ return False
+ return True
+ signatures = self.signaturesForArgCount(argc)
+ for idx in range(argc):
+ if isValidDistinguishingIndex(idx, signatures):
+ return idx
+ # No valid distinguishing index. Time to throw
+ locations = self.locationsForArgCount(argc)
+ raise WebIDLError("Signatures with %d arguments for method '%s' are not "
+ "distinguishable" % (argc, self.identifier.name),
+ locations)
+
+ def handleExtendedAttribute(self, attr):
+ identifier = attr.identifier()
+ if identifier == "GetterThrows":
+ raise WebIDLError("Methods must not be flagged as "
+ "[GetterThrows]",
+ [attr.location, self.location])
+ elif identifier == "SetterThrows":
+ raise WebIDLError("Methods must not be flagged as "
+ "[SetterThrows]",
+ [attr.location, self.location])
+ elif identifier == "Unforgeable":
+ raise WebIDLError("Methods must not be flagged as "
+ "[Unforgeable]",
+ [attr.location, self.location])
+ elif identifier == "SameObject":
+ raise WebIDLError("Methods must not be flagged as [SameObject]",
+ [attr.location, self.location]);
+ elif identifier == "Constant":
+ raise WebIDLError("Methods must not be flagged as [Constant]",
+ [attr.location, self.location]);
+ elif identifier == "PutForwards":
+ raise WebIDLError("Only attributes support [PutForwards]",
+ [attr.location, self.location])
+ elif identifier == "LenientFloat":
+ # This is called before we've done overload resolution
+ assert len(self.signatures()) == 1
+ sig = self.signatures()[0]
+ if not sig[0].isVoid():
+ raise WebIDLError("[LenientFloat] used on a non-void method",
+ [attr.location, self.location])
+ if not any(arg.type.includesRestrictedFloat() for arg in sig[1]):
+ raise WebIDLError("[LenientFloat] used on an operation with no "
+ "restricted float type arguments",
+ [attr.location, self.location])
+ elif (identifier == "Throws" or
+ identifier == "NewObject" or
+ identifier == "ChromeOnly" or
+ identifier == "Pref" or
+ identifier == "Func" or
+ identifier == "AvailableIn" or
+ identifier == "Pure" or
+ identifier == "CrossOriginCallable" or
+ identifier == "Ref" or
+ identifier == "Value" or
+ identifier == "Operator" or
+ identifier == "Const" or
+ identifier == "WebGLHandlesContextLoss"):
+ # Known attributes that we don't need to do anything with here
+ pass
+ else:
+ raise WebIDLError("Unknown extended attribute %s on method" % identifier,
+ [attr.location])
+ IDLInterfaceMember.handleExtendedAttribute(self, attr)
+
+ def returnsPromise(self):
+ return self._overloads[0].returnType.isPromise()
+
+ def _getDependentObjects(self):
+ deps = set()
+ for overload in self._overloads:
+ deps.union(overload._getDependentObjects())
+ return deps
+
+class IDLImplementsStatement(IDLObject):
+ def __init__(self, location, implementor, implementee):
+ IDLObject.__init__(self, location)
+ self.implementor = implementor;
+ self.implementee = implementee
+
+ def finish(self, scope):
+ assert(isinstance(self.implementor, IDLIdentifierPlaceholder))
+ assert(isinstance(self.implementee, IDLIdentifierPlaceholder))
+ implementor = self.implementor.finish(scope)
+ implementee = self.implementee.finish(scope)
+ # NOTE: we depend on not setting self.implementor and
+ # self.implementee here to keep track of the original
+ # locations.
+ if not isinstance(implementor, IDLInterface):
+ raise WebIDLError("Left-hand side of 'implements' is not an "
+ "interface",
+ [self.implementor.location])
+ if implementor.isCallback():
+ raise WebIDLError("Left-hand side of 'implements' is a callback "
+ "interface",
+ [self.implementor.location])
+ if not isinstance(implementee, IDLInterface):
+ raise WebIDLError("Right-hand side of 'implements' is not an "
+ "interface",
+ [self.implementee.location])
+ if implementee.isCallback():
+ raise WebIDLError("Right-hand side of 'implements' is a callback "
+ "interface",
+ [self.implementee.location])
+ implementor.addImplementedInterface(implementee)
+
+ def validate(self):
+ pass
+
+ def addExtendedAttributes(self, attrs):
+ assert len(attrs) == 0
+
+class IDLExtendedAttribute(IDLObject):
+ """
+ A class to represent IDL extended attributes so we can give them locations
+ """
+ def __init__(self, location, tuple):
+ IDLObject.__init__(self, location)
+ self._tuple = tuple
+
+ def identifier(self):
+ return self._tuple[0]
+
+ def noArguments(self):
+ return len(self._tuple) == 1
+
+ def hasValue(self):
+ return len(self._tuple) >= 2 and isinstance(self._tuple[1], str)
+
+ def value(self):
+ assert(self.hasValue())
+ return self._tuple[1]
+
+ def hasArgs(self):
+ return (len(self._tuple) == 2 and isinstance(self._tuple[1], list) or
+ len(self._tuple) == 3)
+
+ def args(self):
+ assert(self.hasArgs())
+ # Our args are our last element
+ return self._tuple[-1]
+
+ def listValue(self):
+ """
+ Backdoor for storing random data in _extendedAttrDict
+ """
+ return list(self._tuple)[1:]
+
+# Parser
+
+class Tokenizer(object):
+ tokens = [
+ "INTEGER",
+ "FLOATLITERAL",
+ "IDENTIFIER",
+ "STRING",
+ "WHITESPACE",
+ "OTHER"
+ ]
+
+ def t_FLOATLITERAL(self, t):
+ r'(-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+|Infinity))|NaN'
+ t.value = float(t.value)
+ return t
+
+ def t_INTEGER(self, t):
+ r'-?(0([0-7]+|[Xx][0-9A-Fa-f]+)?|[1-9][0-9]*)'
+ try:
+ # Can't use int(), because that doesn't handle octal properly.
+ t.value = parseInt(t.value)
+ except:
+ raise WebIDLError("Invalid integer literal",
+ [Location(lexer=self.lexer,
+ lineno=self.lexer.lineno,
+ lexpos=self.lexer.lexpos,
+ filename=self._filename)])
+ return t
+
+ def t_IDENTIFIER(self, t):
+ r'[A-Z_a-z][0-9A-Z_a-z]*'
+ t.type = self.keywords.get(t.value, 'IDENTIFIER')
+ return t
+
+ def t_STRING(self, t):
+ r'"[^"]*"'
+ t.value = t.value[1:-1]
+ return t
+
+ def t_WHITESPACE(self, t):
+ r'[\t\n\r ]+|[\t\n\r ]*((//[^\n]*|/\*.*?\*/)[\t\n\r ]*)+'
+ pass
+
+ def t_ELLIPSIS(self, t):
+ r'\.\.\.'
+ t.type = self.keywords.get(t.value)
+ return t
+
+ def t_OTHER(self, t):
+ r'[^\t\n\r 0-9A-Z_a-z]'
+ t.type = self.keywords.get(t.value, 'OTHER')
+ return t
+
+ keywords = {
+ "module": "MODULE",
+ "interface": "INTERFACE",
+ "partial": "PARTIAL",
+ "dictionary": "DICTIONARY",
+ "exception": "EXCEPTION",
+ "enum": "ENUM",
+ "callback": "CALLBACK",
+ "typedef": "TYPEDEF",
+ "implements": "IMPLEMENTS",
+ "const": "CONST",
+ "null": "NULL",
+ "true": "TRUE",
+ "false": "FALSE",
+ "serializer": "SERIALIZER",
+ "stringifier": "STRINGIFIER",
+ "jsonifier": "JSONIFIER",
+ "unrestricted": "UNRESTRICTED",
+ "attribute": "ATTRIBUTE",
+ "readonly": "READONLY",
+ "inherit": "INHERIT",
+ "static": "STATIC",
+ "getter": "GETTER",
+ "setter": "SETTER",
+ "creator": "CREATOR",
+ "deleter": "DELETER",
+ "legacycaller": "LEGACYCALLER",
+ "optional": "OPTIONAL",
+ "...": "ELLIPSIS",
+ "::": "SCOPE",
+ "Date": "DATE",
+ "DOMString": "DOMSTRING",
+ "ByteString": "BYTESTRING",
+ "any": "ANY",
+ "boolean": "BOOLEAN",
+ "byte": "BYTE",
+ "double": "DOUBLE",
+ "float": "FLOAT",
+ "long": "LONG",
+ "object": "OBJECT",
+ "octet": "OCTET",
+ "optional": "OPTIONAL",
+ "sequence": "SEQUENCE",
+ "short": "SHORT",
+ "unsigned": "UNSIGNED",
+ "void": "VOID",
+ ":": "COLON",
+ ";": "SEMICOLON",
+ "{": "LBRACE",
+ "}": "RBRACE",
+ "(": "LPAREN",
+ ")": "RPAREN",
+ "[": "LBRACKET",
+ "]": "RBRACKET",
+ "?": "QUESTIONMARK",
+ ",": "COMMA",
+ "=": "EQUALS",
+ "<": "LT",
+ ">": "GT",
+ "ArrayBuffer": "ARRAYBUFFER",
+ "or": "OR"
+ }
+
+ tokens.extend(keywords.values())
+
+ def t_error(self, t):
+ raise WebIDLError("Unrecognized Input",
+ [Location(lexer=self.lexer,
+ lineno=self.lexer.lineno,
+ lexpos=self.lexer.lexpos,
+ filename = self.filename)])
+
+ def __init__(self, outputdir, lexer=None):
+ if lexer:
+ self.lexer = lexer
+ else:
+ self.lexer = lex.lex(object=self,
+ outputdir=outputdir,
+ lextab='webidllex',
+ reflags=re.DOTALL)
+
+class Parser(Tokenizer):
+ def getLocation(self, p, i):
+ return Location(self.lexer, p.lineno(i), p.lexpos(i), self._filename)
+
+ def globalScope(self):
+ return self._globalScope
+
+ # The p_Foo functions here must match the WebIDL spec's grammar.
+ # It's acceptable to split things at '|' boundaries.
+ def p_Definitions(self, p):
+ """
+ Definitions : ExtendedAttributeList Definition Definitions
+ """
+ if p[2]:
+ p[0] = [p[2]]
+ p[2].addExtendedAttributes(p[1])
+ else:
+ assert not p[1]
+ p[0] = []
+
+ p[0].extend(p[3])
+
+ def p_DefinitionsEmpty(self, p):
+ """
+ Definitions :
+ """
+ p[0] = []
+
+ def p_Definition(self, p):
+ """
+ Definition : CallbackOrInterface
+ | PartialInterface
+ | Dictionary
+ | Exception
+ | Enum
+ | Typedef
+ | ImplementsStatement
+ """
+ p[0] = p[1]
+ assert p[1] # We might not have implemented something ...
+
+ def p_CallbackOrInterfaceCallback(self, p):
+ """
+ CallbackOrInterface : CALLBACK CallbackRestOrInterface
+ """
+ if p[2].isInterface():
+ assert isinstance(p[2], IDLInterface)
+ p[2].setCallback(True)
+
+ p[0] = p[2]
+
+ def p_CallbackOrInterfaceInterface(self, p):
+ """
+ CallbackOrInterface : Interface
+ """
+ p[0] = p[1]
+
+ def p_CallbackRestOrInterface(self, p):
+ """
+ CallbackRestOrInterface : CallbackRest
+ | Interface
+ """
+ assert p[1]
+ p[0] = p[1]
+
+ def p_Interface(self, p):
+ """
+ Interface : INTERFACE IDENTIFIER Inheritance LBRACE InterfaceMembers RBRACE SEMICOLON
+ """
+ location = self.getLocation(p, 1)
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
+ members = p[5]
+ parent = p[3]
+
+ try:
+ if self.globalScope()._lookupIdentifier(identifier):
+ p[0] = self.globalScope()._lookupIdentifier(identifier)
+ if not isinstance(p[0], IDLInterface):
+ raise WebIDLError("Partial interface has the same name as "
+ "non-interface object",
+ [location, p[0].location])
+ p[0].setNonPartial(location, parent, members)
+ return
+ except Exception, ex:
+ if isinstance(ex, WebIDLError):
+ raise ex
+ pass
+
+ p[0] = IDLInterface(location, self.globalScope(), identifier, parent,
+ members, isPartial=False)
+
+ def p_InterfaceForwardDecl(self, p):
+ """
+ Interface : INTERFACE IDENTIFIER SEMICOLON
+ """
+ location = self.getLocation(p, 1)
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
+
+ try:
+ if self.globalScope()._lookupIdentifier(identifier):
+ p[0] = self.globalScope()._lookupIdentifier(identifier)
+ if not isinstance(p[0], IDLExternalInterface):
+ raise WebIDLError("Name collision between external "
+ "interface declaration for identifier "
+ "%s and %s" % (identifier.name, p[0]),
+ [location, p[0].location])
+ return
+ except Exception, ex:
+ if isinstance(ex, WebIDLError):
+ raise ex
+ pass
+
+ p[0] = IDLExternalInterface(location, self.globalScope(), identifier)
+
+ def p_PartialInterface(self, p):
+ """
+ PartialInterface : PARTIAL INTERFACE IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON
+ """
+ location = self.getLocation(p, 2)
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
+ members = p[5]
+
+ try:
+ if self.globalScope()._lookupIdentifier(identifier):
+ p[0] = self.globalScope()._lookupIdentifier(identifier)
+ if not isinstance(p[0], IDLInterface):
+ raise WebIDLError("Partial interface has the same name as "
+ "non-interface object",
+ [location, p[0].location])
+ # Just throw our members into the existing IDLInterface. If we
+ # have extended attributes, those will get added to it
+ # automatically.
+ p[0].members.extend(members)
+ return
+ except Exception, ex:
+ if isinstance(ex, WebIDLError):
+ raise ex
+ pass
+
+ p[0] = IDLInterface(location, self.globalScope(), identifier, None,
+ members, isPartial=True)
+ pass
+
+ def p_Inheritance(self, p):
+ """
+ Inheritance : COLON ScopedName
+ """
+ p[0] = IDLIdentifierPlaceholder(self.getLocation(p, 2), p[2])
+
+ def p_InheritanceEmpty(self, p):
+ """
+ Inheritance :
+ """
+ pass
+
+ def p_InterfaceMembers(self, p):
+ """
+ InterfaceMembers : ExtendedAttributeList InterfaceMember InterfaceMembers
+ """
+ p[0] = [p[2]] if p[2] else []
+
+ assert not p[1] or p[2]
+ p[2].addExtendedAttributes(p[1])
+
+ p[0].extend(p[3])
+
+ def p_InterfaceMembersEmpty(self, p):
+ """
+ InterfaceMembers :
+ """
+ p[0] = []
+
+ def p_InterfaceMember(self, p):
+ """
+ InterfaceMember : Const
+ | AttributeOrOperation
+ """
+ p[0] = p[1]
+
+ def p_Dictionary(self, p):
+ """
+ Dictionary : DICTIONARY IDENTIFIER Inheritance LBRACE DictionaryMembers RBRACE SEMICOLON
+ """
+ location = self.getLocation(p, 1)
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
+ members = p[5]
+ p[0] = IDLDictionary(location, self.globalScope(), identifier, p[3], members)
+
+ def p_DictionaryMembers(self, p):
+ """
+ DictionaryMembers : ExtendedAttributeList DictionaryMember DictionaryMembers
+ |
+ """
+ if len(p) == 1:
+ # We're at the end of the list
+ p[0] = []
+ return
+ # Add our extended attributes
+ p[2].addExtendedAttributes(p[1])
+ p[0] = [p[2]]
+ p[0].extend(p[3])
+
+ def p_DictionaryMember(self, p):
+ """
+ DictionaryMember : Type IDENTIFIER DefaultValue SEMICOLON
+ """
+ # These quack a lot like optional arguments, so just treat them that way.
+ t = p[1]
+ assert isinstance(t, IDLType)
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
+ defaultValue = p[3]
+
+ p[0] = IDLArgument(self.getLocation(p, 2), identifier, t, optional=True,
+ defaultValue=defaultValue, variadic=False,
+ dictionaryMember=True)
+
+ def p_DefaultValue(self, p):
+ """
+ DefaultValue : EQUALS ConstValue
+ |
+ """
+ if len(p) > 1:
+ p[0] = p[2]
+ else:
+ p[0] = None
+
+ def p_Exception(self, p):
+ """
+ Exception : EXCEPTION IDENTIFIER Inheritance LBRACE ExceptionMembers RBRACE SEMICOLON
+ """
+ pass
+
+ def p_Enum(self, p):
+ """
+ Enum : ENUM IDENTIFIER LBRACE EnumValueList RBRACE SEMICOLON
+ """
+ location = self.getLocation(p, 1)
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
+
+ values = p[4]
+ assert values
+ p[0] = IDLEnum(location, self.globalScope(), identifier, values)
+
+ def p_EnumValueList(self, p):
+ """
+ EnumValueList : STRING EnumValueListComma
+ """
+ p[0] = [p[1]]
+ p[0].extend(p[2])
+
+ def p_EnumValueListComma(self, p):
+ """
+ EnumValueListComma : COMMA EnumValueListString
+ """
+ p[0] = p[2]
+
+ def p_EnumValueListCommaEmpty(self, p):
+ """
+ EnumValueListComma :
+ """
+ p[0] = []
+
+ def p_EnumValueListString(self, p):
+ """
+ EnumValueListString : STRING EnumValueListComma
+ """
+ p[0] = [p[1]]
+ p[0].extend(p[2])
+
+ def p_EnumValueListStringEmpty(self, p):
+ """
+ EnumValueListString :
+ """
+ p[0] = []
+
+ def p_CallbackRest(self, p):
+ """
+ CallbackRest : IDENTIFIER EQUALS ReturnType LPAREN ArgumentList RPAREN SEMICOLON
+ """
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
+ p[0] = IDLCallbackType(self.getLocation(p, 1), self.globalScope(),
+ identifier, p[3], p[5])
+
+ def p_ExceptionMembers(self, p):
+ """
+ ExceptionMembers : ExtendedAttributeList ExceptionMember ExceptionMembers
+ |
+ """
+ pass
+
+ def p_Typedef(self, p):
+ """
+ Typedef : TYPEDEF Type IDENTIFIER SEMICOLON
+ """
+ typedef = IDLTypedefType(self.getLocation(p, 1), p[2], p[3])
+ typedef.resolve(self.globalScope())
+ p[0] = typedef
+
+ def p_ImplementsStatement(self, p):
+ """
+ ImplementsStatement : ScopedName IMPLEMENTS ScopedName SEMICOLON
+ """
+ assert(p[2] == "implements")
+ implementor = IDLIdentifierPlaceholder(self.getLocation(p, 1), p[1])
+ implementee = IDLIdentifierPlaceholder(self.getLocation(p, 3), p[3])
+ p[0] = IDLImplementsStatement(self.getLocation(p, 1), implementor,
+ implementee)
+
+ def p_Const(self, p):
+ """
+ Const : CONST ConstType IDENTIFIER EQUALS ConstValue SEMICOLON
+ """
+ location = self.getLocation(p, 1)
+ type = p[2]
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
+ value = p[5]
+ p[0] = IDLConst(location, identifier, type, value)
+
+ def p_ConstValueBoolean(self, p):
+ """
+ ConstValue : BooleanLiteral
+ """
+ location = self.getLocation(p, 1)
+ booleanType = BuiltinTypes[IDLBuiltinType.Types.boolean]
+ p[0] = IDLValue(location, booleanType, p[1])
+
+ def p_ConstValueInteger(self, p):
+ """
+ ConstValue : INTEGER
+ """
+ location = self.getLocation(p, 1)
+
+ # We don't know ahead of time what type the integer literal is.
+ # Determine the smallest type it could possibly fit in and use that.
+ integerType = matchIntegerValueToType(p[1])
+ if integerType == None:
+ raise WebIDLError("Integer literal out of range", [location])
+
+ p[0] = IDLValue(location, integerType, p[1])
+
+ def p_ConstValueFloat(self, p):
+ """
+ ConstValue : FLOATLITERAL
+ """
+ location = self.getLocation(p, 1)
+ p[0] = IDLValue(location, BuiltinTypes[IDLBuiltinType.Types.unrestricted_float], p[1])
+
+ def p_ConstValueString(self, p):
+ """
+ ConstValue : STRING
+ """
+ location = self.getLocation(p, 1)
+ stringType = BuiltinTypes[IDLBuiltinType.Types.domstring]
+ p[0] = IDLValue(location, stringType, p[1])
+
+ def p_ConstValueNull(self, p):
+ """
+ ConstValue : NULL
+ """
+ p[0] = IDLNullValue(self.getLocation(p, 1))
+
+ def p_BooleanLiteralTrue(self, p):
+ """
+ BooleanLiteral : TRUE
+ """
+ p[0] = True
+
+ def p_BooleanLiteralFalse(self, p):
+ """
+ BooleanLiteral : FALSE
+ """
+ p[0] = False
+
+ def p_AttributeOrOperation(self, p):
+ """
+ AttributeOrOperation : Attribute
+ | Operation
+ """
+ p[0] = p[1]
+
+ def p_AttributeWithQualifier(self, p):
+ """
+ Attribute : Qualifier AttributeRest
+ """
+ static = IDLInterfaceMember.Special.Static in p[1]
+ stringifier = IDLInterfaceMember.Special.Stringifier in p[1]
+ (location, identifier, type, readonly) = p[2]
+ p[0] = IDLAttribute(location, identifier, type, readonly, static=static,
+ stringifier=stringifier)
+
+ def p_Attribute(self, p):
+ """
+ Attribute : Inherit AttributeRest
+ """
+ (location, identifier, type, readonly) = p[2]
+ p[0] = IDLAttribute(location, identifier, type, readonly, inherit=p[1])
+
+ def p_AttributeRest(self, p):
+ """
+ AttributeRest : ReadOnly ATTRIBUTE Type IDENTIFIER SEMICOLON
+ """
+ location = self.getLocation(p, 2)
+ readonly = p[1]
+ t = p[3]
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 4), p[4])
+ p[0] = (location, identifier, t, readonly)
+
+ def p_ReadOnly(self, p):
+ """
+ ReadOnly : READONLY
+ """
+ p[0] = True
+
+ def p_ReadOnlyEmpty(self, p):
+ """
+ ReadOnly :
+ """
+ p[0] = False
+
+ def p_Inherit(self, p):
+ """
+ Inherit : INHERIT
+ """
+ p[0] = True
+
+ def p_InheritEmpty(self, p):
+ """
+ Inherit :
+ """
+ p[0] = False
+
+ def p_Operation(self, p):
+ """
+ Operation : Qualifiers OperationRest
+ """
+ qualifiers = p[1]
+
+ # Disallow duplicates in the qualifier set
+ if not len(set(qualifiers)) == len(qualifiers):
+ raise WebIDLError("Duplicate qualifiers are not allowed",
+ [self.getLocation(p, 1)])
+
+ static = IDLInterfaceMember.Special.Static in p[1]
+ # If static is there that's all that's allowed. This is disallowed
+ # by the parser, so we can assert here.
+ assert not static or len(qualifiers) == 1
+
+ stringifier = IDLInterfaceMember.Special.Stringifier in p[1]
+ # If stringifier is there that's all that's allowed. This is disallowed
+ # by the parser, so we can assert here.
+ assert not stringifier or len(qualifiers) == 1
+
+ getter = True if IDLMethod.Special.Getter in p[1] else False
+ setter = True if IDLMethod.Special.Setter in p[1] else False
+ creator = True if IDLMethod.Special.Creator in p[1] else False
+ deleter = True if IDLMethod.Special.Deleter in p[1] else False
+ legacycaller = True if IDLMethod.Special.LegacyCaller in p[1] else False
+
+ if getter or deleter:
+ if setter or creator:
+ raise WebIDLError("getter and deleter are incompatible with setter and creator",
+ [self.getLocation(p, 1)])
+
+ (returnType, identifier, arguments) = p[2]
+
+ assert isinstance(returnType, IDLType)
+
+ specialType = IDLMethod.NamedOrIndexed.Neither
+
+ if getter or deleter:
+ if len(arguments) != 1:
+ raise WebIDLError("%s has wrong number of arguments" %
+ ("getter" if getter else "deleter"),
+ [self.getLocation(p, 2)])
+ argType = arguments[0].type
+ if argType == BuiltinTypes[IDLBuiltinType.Types.domstring]:
+ specialType = IDLMethod.NamedOrIndexed.Named
+ elif argType == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]:
+ specialType = IDLMethod.NamedOrIndexed.Indexed
+ else:
+ raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" %
+ ("getter" if getter else "deleter"),
+ [arguments[0].location])
+ if arguments[0].optional or arguments[0].variadic:
+ raise WebIDLError("%s cannot have %s argument" %
+ ("getter" if getter else "deleter",
+ "optional" if arguments[0].optional else "variadic"),
+ [arguments[0].location])
+ if getter:
+ if returnType.isVoid():
+ raise WebIDLError("getter cannot have void return type",
+ [self.getLocation(p, 2)])
+ if setter or creator:
+ if len(arguments) != 2:
+ raise WebIDLError("%s has wrong number of arguments" %
+ ("setter" if setter else "creator"),
+ [self.getLocation(p, 2)])
+ argType = arguments[0].type
+ if argType == BuiltinTypes[IDLBuiltinType.Types.domstring]:
+ specialType = IDLMethod.NamedOrIndexed.Named
+ elif argType == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]:
+ specialType = IDLMethod.NamedOrIndexed.Indexed
+ else:
+ raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" %
+ ("setter" if setter else "creator"),
+ [arguments[0].location])
+ if arguments[0].optional or arguments[0].variadic:
+ raise WebIDLError("%s cannot have %s argument" %
+ ("setter" if setter else "creator",
+ "optional" if arguments[0].optional else "variadic"),
+ [arguments[0].location])
+ if arguments[1].optional or arguments[1].variadic:
+ raise WebIDLError("%s cannot have %s argument" %
+ ("setter" if setter else "creator",
+ "optional" if arguments[1].optional else "variadic"),
+ [arguments[1].location])
+
+ if stringifier:
+ if len(arguments) != 0:
+ raise WebIDLError("stringifier has wrong number of arguments",
+ [self.getLocation(p, 2)])
+ if not returnType.isDOMString():
+ raise WebIDLError("stringifier must have DOMString return type",
+ [self.getLocation(p, 2)])
+
+ # identifier might be None. This is only permitted for special methods.
+ if not identifier:
+ if not getter and not setter and not creator and \
+ not deleter and not legacycaller and not stringifier:
+ raise WebIDLError("Identifier required for non-special methods",
+ [self.getLocation(p, 2)])
+
+ location = BuiltinLocation("<auto-generated-identifier>")
+ identifier = IDLUnresolvedIdentifier(location, "__%s%s%s%s%s%s%s" %
+ ("named" if specialType == IDLMethod.NamedOrIndexed.Named else \
+ "indexed" if specialType == IDLMethod.NamedOrIndexed.Indexed else "",
+ "getter" if getter else "",
+ "setter" if setter else "",
+ "deleter" if deleter else "",
+ "creator" if creator else "",
+ "legacycaller" if legacycaller else "",
+ "stringifier" if stringifier else ""), allowDoubleUnderscore=True)
+
+ method = IDLMethod(self.getLocation(p, 2), identifier, returnType, arguments,
+ static=static, getter=getter, setter=setter, creator=creator,
+ deleter=deleter, specialType=specialType,
+ legacycaller=legacycaller, stringifier=stringifier)
+ p[0] = method
+
+ def p_Stringifier(self, p):
+ """
+ Operation : STRINGIFIER SEMICOLON
+ """
+ identifier = IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
+ "__stringifier",
+ allowDoubleUnderscore=True)
+ method = IDLMethod(self.getLocation(p, 1),
+ identifier,
+ returnType=BuiltinTypes[IDLBuiltinType.Types.domstring],
+ arguments=[],
+ stringifier=True)
+ p[0] = method
+
+ def p_Jsonifier(self, p):
+ """
+ Operation : JSONIFIER SEMICOLON
+ """
+ identifier = IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
+ "__jsonifier", allowDoubleUnderscore=True)
+ method = IDLMethod(self.getLocation(p, 1),
+ identifier,
+ returnType=BuiltinTypes[IDLBuiltinType.Types.object],
+ arguments=[],
+ jsonifier=True)
+ p[0] = method
+
+ def p_QualifierStatic(self, p):
+ """
+ Qualifier : STATIC
+ """
+ p[0] = [IDLInterfaceMember.Special.Static]
+
+ def p_QualifierStringifier(self, p):
+ """
+ Qualifier : STRINGIFIER
+ """
+ p[0] = [IDLInterfaceMember.Special.Stringifier]
+
+ def p_Qualifiers(self, p):
+ """
+ Qualifiers : Qualifier
+ | Specials
+ """
+ p[0] = p[1]
+
+ def p_Specials(self, p):
+ """
+ Specials : Special Specials
+ """
+ p[0] = [p[1]]
+ p[0].extend(p[2])
+
+ def p_SpecialsEmpty(self, p):
+ """
+ Specials :
+ """
+ p[0] = []
+
+ def p_SpecialGetter(self, p):
+ """
+ Special : GETTER
+ """
+ p[0] = IDLMethod.Special.Getter
+
+ def p_SpecialSetter(self, p):
+ """
+ Special : SETTER
+ """
+ p[0] = IDLMethod.Special.Setter
+
+ def p_SpecialCreator(self, p):
+ """
+ Special : CREATOR
+ """
+ p[0] = IDLMethod.Special.Creator
+
+ def p_SpecialDeleter(self, p):
+ """
+ Special : DELETER
+ """
+ p[0] = IDLMethod.Special.Deleter
+
+ def p_SpecialLegacyCaller(self, p):
+ """
+ Special : LEGACYCALLER
+ """
+ p[0] = IDLMethod.Special.LegacyCaller
+
+ def p_OperationRest(self, p):
+ """
+ OperationRest : ReturnType OptionalIdentifier LPAREN ArgumentList RPAREN SEMICOLON
+ """
+ p[0] = (p[1], p[2], p[4])
+
+ def p_OptionalIdentifier(self, p):
+ """
+ OptionalIdentifier : IDENTIFIER
+ """
+ p[0] = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
+
+ def p_OptionalIdentifierEmpty(self, p):
+ """
+ OptionalIdentifier :
+ """
+ pass
+
+ def p_ArgumentList(self, p):
+ """
+ ArgumentList : Argument Arguments
+ """
+ p[0] = [p[1]] if p[1] else []
+ p[0].extend(p[2])
+
+ def p_ArgumentListEmpty(self, p):
+ """
+ ArgumentList :
+ """
+ p[0] = []
+
+ def p_Arguments(self, p):
+ """
+ Arguments : COMMA Argument Arguments
+ """
+ p[0] = [p[2]] if p[2] else []
+ p[0].extend(p[3])
+
+ def p_ArgumentsEmpty(self, p):
+ """
+ Arguments :
+ """
+ p[0] = []
+
+ def p_Argument(self, p):
+ """
+ Argument : ExtendedAttributeList Optional Type Ellipsis ArgumentName DefaultValue
+ """
+ t = p[3]
+ assert isinstance(t, IDLType)
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 5), p[5])
+
+ optional = p[2]
+ variadic = p[4]
+ defaultValue = p[6]
+
+ if not optional and defaultValue:
+ raise WebIDLError("Mandatory arguments can't have a default value.",
+ [self.getLocation(p, 6)])
+
+ # We can't test t.isAny() here and give it a default value as needed,
+ # since at this point t is not a fully resolved type yet (e.g. it might
+ # be a typedef). We'll handle the 'any' case in IDLArgument.complete.
+
+ if variadic:
+ if optional:
+ raise WebIDLError("Variadic arguments should not be marked optional.",
+ [self.getLocation(p, 2)])
+ optional = variadic
+
+ p[0] = IDLArgument(self.getLocation(p, 5), identifier, t, optional, defaultValue, variadic)
+ p[0].addExtendedAttributes(p[1])
+
+ def p_ArgumentName(self, p):
+ """
+ ArgumentName : IDENTIFIER
+ | ATTRIBUTE
+ | CALLBACK
+ | CONST
+ | CREATOR
+ | DELETER
+ | DICTIONARY
+ | ENUM
+ | EXCEPTION
+ | GETTER
+ | IMPLEMENTS
+ | INHERIT
+ | INTERFACE
+ | LEGACYCALLER
+ | PARTIAL
+ | SERIALIZER
+ | SETTER
+ | STATIC
+ | STRINGIFIER
+ | JSONIFIER
+ | TYPEDEF
+ | UNRESTRICTED
+ """
+ p[0] = p[1]
+
+ def p_Optional(self, p):
+ """
+ Optional : OPTIONAL
+ """
+ p[0] = True
+
+ def p_OptionalEmpty(self, p):
+ """
+ Optional :
+ """
+ p[0] = False
+
+ def p_Ellipsis(self, p):
+ """
+ Ellipsis : ELLIPSIS
+ """
+ p[0] = True
+
+ def p_EllipsisEmpty(self, p):
+ """
+ Ellipsis :
+ """
+ p[0] = False
+
+ def p_ExceptionMember(self, p):
+ """
+ ExceptionMember : Const
+ | ExceptionField
+ """
+ pass
+
+ def p_ExceptionField(self, p):
+ """
+ ExceptionField : Type IDENTIFIER SEMICOLON
+ """
+ pass
+
+ def p_ExtendedAttributeList(self, p):
+ """
+ ExtendedAttributeList : LBRACKET ExtendedAttribute ExtendedAttributes RBRACKET
+ """
+ p[0] = [p[2]]
+ if p[3]:
+ p[0].extend(p[3])
+
+ def p_ExtendedAttributeListEmpty(self, p):
+ """
+ ExtendedAttributeList :
+ """
+ p[0] = []
+
+ def p_ExtendedAttribute(self, p):
+ """
+ ExtendedAttribute : ExtendedAttributeNoArgs
+ | ExtendedAttributeArgList
+ | ExtendedAttributeIdent
+ | ExtendedAttributeNamedArgList
+ """
+ p[0] = IDLExtendedAttribute(self.getLocation(p, 1), p[1])
+
+ def p_ExtendedAttributeEmpty(self, p):
+ """
+ ExtendedAttribute :
+ """
+ pass
+
+ def p_ExtendedAttributes(self, p):
+ """
+ ExtendedAttributes : COMMA ExtendedAttribute ExtendedAttributes
+ """
+ p[0] = [p[2]] if p[2] else []
+ p[0].extend(p[3])
+
+ def p_ExtendedAttributesEmpty(self, p):
+ """
+ ExtendedAttributes :
+ """
+ p[0] = []
+
+ def p_Other(self, p):
+ """
+ Other : INTEGER
+ | FLOATLITERAL
+ | IDENTIFIER
+ | STRING
+ | OTHER
+ | ELLIPSIS
+ | COLON
+ | SCOPE
+ | SEMICOLON
+ | LT
+ | EQUALS
+ | GT
+ | QUESTIONMARK
+ | DATE
+ | DOMSTRING
+ | BYTESTRING
+ | ANY
+ | ATTRIBUTE
+ | BOOLEAN
+ | BYTE
+ | LEGACYCALLER
+ | CONST
+ | CREATOR
+ | DELETER
+ | DOUBLE
+ | EXCEPTION
+ | FALSE
+ | FLOAT
+ | GETTER
+ | IMPLEMENTS
+ | INHERIT
+ | INTERFACE
+ | LONG
+ | MODULE
+ | NULL
+ | OBJECT
+ | OCTET
+ | OPTIONAL
+ | SEQUENCE
+ | SETTER
+ | SHORT
+ | STATIC
+ | STRINGIFIER
+ | JSONIFIER
+ | TRUE
+ | TYPEDEF
+ | UNSIGNED
+ | VOID
+ """
+ pass
+
+ def p_OtherOrComma(self, p):
+ """
+ OtherOrComma : Other
+ | COMMA
+ """
+ pass
+
+ def p_TypeSingleType(self, p):
+ """
+ Type : SingleType
+ """
+ p[0] = p[1]
+
+ def p_TypeUnionType(self, p):
+ """
+ Type : UnionType TypeSuffix
+ """
+ p[0] = self.handleModifiers(p[1], p[2])
+
+ def p_SingleTypeNonAnyType(self, p):
+ """
+ SingleType : NonAnyType
+ """
+ p[0] = p[1]
+
+ def p_SingleTypeAnyType(self, p):
+ """
+ SingleType : ANY TypeSuffixStartingWithArray
+ """
+ p[0] = self.handleModifiers(BuiltinTypes[IDLBuiltinType.Types.any], p[2])
+
+ def p_UnionType(self, p):
+ """
+ UnionType : LPAREN UnionMemberType OR UnionMemberType UnionMemberTypes RPAREN
+ """
+ types = [p[2], p[4]]
+ types.extend(p[5])
+ p[0] = IDLUnionType(self.getLocation(p, 1), types)
+
+ def p_UnionMemberTypeNonAnyType(self, p):
+ """
+ UnionMemberType : NonAnyType
+ """
+ p[0] = p[1]
+
+ def p_UnionMemberTypeArrayOfAny(self, p):
+ """
+ UnionMemberTypeArrayOfAny : ANY LBRACKET RBRACKET
+ """
+ p[0] = IDLArrayType(self.getLocation(p, 2),
+ BuiltinTypes[IDLBuiltinType.Types.any])
+
+ def p_UnionMemberType(self, p):
+ """
+ UnionMemberType : UnionType TypeSuffix
+ | UnionMemberTypeArrayOfAny TypeSuffix
+ """
+ p[0] = self.handleModifiers(p[1], p[2])
+
+ def p_UnionMemberTypes(self, p):
+ """
+ UnionMemberTypes : OR UnionMemberType UnionMemberTypes
+ """
+ p[0] = [p[2]]
+ p[0].extend(p[3])
+
+ def p_UnionMemberTypesEmpty(self, p):
+ """
+ UnionMemberTypes :
+ """
+ p[0] = []
+
+ def p_NonAnyType(self, p):
+ """
+ NonAnyType : PrimitiveOrStringType TypeSuffix
+ | ARRAYBUFFER TypeSuffix
+ | OBJECT TypeSuffix
+ """
+ if p[1] == "object":
+ type = BuiltinTypes[IDLBuiltinType.Types.object]
+ elif p[1] == "ArrayBuffer":
+ type = BuiltinTypes[IDLBuiltinType.Types.ArrayBuffer]
+ else:
+ type = BuiltinTypes[p[1]]
+
+ p[0] = self.handleModifiers(type, p[2])
+
+ def p_NonAnyTypeSequenceType(self, p):
+ """
+ NonAnyType : SEQUENCE LT Type GT Null
+ """
+ innerType = p[3]
+ type = IDLSequenceType(self.getLocation(p, 1), innerType)
+ if p[5]:
+ type = IDLNullableType(self.getLocation(p, 5), type)
+ p[0] = type
+
+ def p_NonAnyTypeScopedName(self, p):
+ """
+ NonAnyType : ScopedName TypeSuffix
+ """
+ assert isinstance(p[1], IDLUnresolvedIdentifier)
+
+ type = None
+
+ try:
+ if self.globalScope()._lookupIdentifier(p[1]):
+ obj = self.globalScope()._lookupIdentifier(p[1])
+ if obj.isType():
+ type = obj
+ else:
+ type = IDLWrapperType(self.getLocation(p, 1), p[1])
+ p[0] = self.handleModifiers(type, p[2])
+ return
+ except:
+ pass
+
+ type = IDLUnresolvedType(self.getLocation(p, 1), p[1])
+ p[0] = self.handleModifiers(type, p[2])
+
+ def p_NonAnyTypeDate(self, p):
+ """
+ NonAnyType : DATE TypeSuffix
+ """
+ p[0] = self.handleModifiers(BuiltinTypes[IDLBuiltinType.Types.date],
+ p[2])
+
+ def p_ConstType(self, p):
+ """
+ ConstType : PrimitiveOrStringType Null
+ """
+ type = BuiltinTypes[p[1]]
+ if p[2]:
+ type = IDLNullableType(self.getLocation(p, 1), type)
+ p[0] = type
+
+ def p_ConstTypeIdentifier(self, p):
+ """
+ ConstType : IDENTIFIER Null
+ """
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
+
+ type = IDLUnresolvedType(self.getLocation(p, 1), identifier)
+ if p[2]:
+ type = IDLNullableType(self.getLocation(p, 1), type)
+ p[0] = type
+
+ def p_PrimitiveOrStringTypeUint(self, p):
+ """
+ PrimitiveOrStringType : UnsignedIntegerType
+ """
+ p[0] = p[1]
+
+ def p_PrimitiveOrStringTypeBoolean(self, p):
+ """
+ PrimitiveOrStringType : BOOLEAN
+ """
+ p[0] = IDLBuiltinType.Types.boolean
+
+ def p_PrimitiveOrStringTypeByte(self, p):
+ """
+ PrimitiveOrStringType : BYTE
+ """
+ p[0] = IDLBuiltinType.Types.byte
+
+ def p_PrimitiveOrStringTypeOctet(self, p):
+ """
+ PrimitiveOrStringType : OCTET
+ """
+ p[0] = IDLBuiltinType.Types.octet
+
+ def p_PrimitiveOrStringTypeFloat(self, p):
+ """
+ PrimitiveOrStringType : FLOAT
+ """
+ p[0] = IDLBuiltinType.Types.float
+
+ def p_PrimitiveOrStringTypeUnrestictedFloat(self, p):
+ """
+ PrimitiveOrStringType : UNRESTRICTED FLOAT
+ """
+ p[0] = IDLBuiltinType.Types.unrestricted_float
+
+ def p_PrimitiveOrStringTypeDouble(self, p):
+ """
+ PrimitiveOrStringType : DOUBLE
+ """
+ p[0] = IDLBuiltinType.Types.double
+
+ def p_PrimitiveOrStringTypeUnrestictedDouble(self, p):
+ """
+ PrimitiveOrStringType : UNRESTRICTED DOUBLE
+ """
+ p[0] = IDLBuiltinType.Types.unrestricted_double
+
+ def p_PrimitiveOrStringTypeDOMString(self, p):
+ """
+ PrimitiveOrStringType : DOMSTRING
+ """
+ p[0] = IDLBuiltinType.Types.domstring
+
+ def p_PrimitiveOrStringTypeBytestring(self, p):
+ """
+ PrimitiveOrStringType : BYTESTRING
+ """
+ p[0] = IDLBuiltinType.Types.bytestring
+
+ def p_UnsignedIntegerTypeUnsigned(self, p):
+ """
+ UnsignedIntegerType : UNSIGNED IntegerType
+ """
+ p[0] = p[2] + 1 # Adding one to a given signed integer type
+ # gets you the unsigned type.
+
+ def p_UnsignedIntegerType(self, p):
+ """
+ UnsignedIntegerType : IntegerType
+ """
+ p[0] = p[1]
+
+ def p_IntegerTypeShort(self, p):
+ """
+ IntegerType : SHORT
+ """
+ p[0] = IDLBuiltinType.Types.short
+
+ def p_IntegerTypeLong(self, p):
+ """
+ IntegerType : LONG OptionalLong
+ """
+ if p[2]:
+ p[0] = IDLBuiltinType.Types.long_long
+ else:
+ p[0] = IDLBuiltinType.Types.long
+
+ def p_OptionalLong(self, p):
+ """
+ OptionalLong : LONG
+ """
+ p[0] = True
+
+ def p_OptionalLongEmpty(self, p):
+ """
+ OptionalLong :
+ """
+ p[0] = False
+
+ def p_TypeSuffixBrackets(self, p):
+ """
+ TypeSuffix : LBRACKET RBRACKET TypeSuffix
+ """
+ p[0] = [(IDLMethod.TypeSuffixModifier.Brackets, self.getLocation(p, 1))]
+ p[0].extend(p[3])
+
+ def p_TypeSuffixQMark(self, p):
+ """
+ TypeSuffix : QUESTIONMARK TypeSuffixStartingWithArray
+ """
+ p[0] = [(IDLMethod.TypeSuffixModifier.QMark, self.getLocation(p, 1))]
+ p[0].extend(p[2])
+
+ def p_TypeSuffixEmpty(self, p):
+ """
+ TypeSuffix :
+ """
+ p[0] = []
+
+ def p_TypeSuffixStartingWithArray(self, p):
+ """
+ TypeSuffixStartingWithArray : LBRACKET RBRACKET TypeSuffix
+ """
+ p[0] = [(IDLMethod.TypeSuffixModifier.Brackets, self.getLocation(p, 1))]
+ p[0].extend(p[3])
+
+ def p_TypeSuffixStartingWithArrayEmpty(self, p):
+ """
+ TypeSuffixStartingWithArray :
+ """
+ p[0] = []
+
+ def p_Null(self, p):
+ """
+ Null : QUESTIONMARK
+ |
+ """
+ if len(p) > 1:
+ p[0] = True
+ else:
+ p[0] = False
+
+ def p_ReturnTypeType(self, p):
+ """
+ ReturnType : Type
+ """
+ p[0] = p[1]
+
+ def p_ReturnTypeVoid(self, p):
+ """
+ ReturnType : VOID
+ """
+ p[0] = BuiltinTypes[IDLBuiltinType.Types.void]
+
+ def p_ScopedName(self, p):
+ """
+ ScopedName : AbsoluteScopedName
+ | RelativeScopedName
+ """
+ p[0] = p[1]
+
+ def p_AbsoluteScopedName(self, p):
+ """
+ AbsoluteScopedName : SCOPE IDENTIFIER ScopedNameParts
+ """
+ assert False
+ pass
+
+ def p_RelativeScopedName(self, p):
+ """
+ RelativeScopedName : IDENTIFIER ScopedNameParts
+ """
+ assert not p[2] # Not implemented!
+
+ p[0] = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
+
+ def p_ScopedNameParts(self, p):
+ """
+ ScopedNameParts : SCOPE IDENTIFIER ScopedNameParts
+ """
+ assert False
+ pass
+
+ def p_ScopedNamePartsEmpty(self, p):
+ """
+ ScopedNameParts :
+ """
+ p[0] = None
+
+ def p_ExtendedAttributeNoArgs(self, p):
+ """
+ ExtendedAttributeNoArgs : IDENTIFIER
+ """
+ p[0] = (p[1],)
+
+ def p_ExtendedAttributeArgList(self, p):
+ """
+ ExtendedAttributeArgList : IDENTIFIER LPAREN ArgumentList RPAREN
+ """
+ p[0] = (p[1], p[3])
+
+ def p_ExtendedAttributeIdent(self, p):
+ """
+ ExtendedAttributeIdent : IDENTIFIER EQUALS STRING
+ | IDENTIFIER EQUALS IDENTIFIER
+ """
+ p[0] = (p[1], p[3])
+
+ def p_ExtendedAttributeNamedArgList(self, p):
+ """
+ ExtendedAttributeNamedArgList : IDENTIFIER EQUALS IDENTIFIER LPAREN ArgumentList RPAREN
+ """
+ p[0] = (p[1], p[3], p[5])
+
+ def p_error(self, p):
+ if not p:
+ raise WebIDLError("Syntax Error at end of file. Possibly due to missing semicolon(;), braces(}) or both",
+ [self._filename])
+ else:
+ raise WebIDLError("invalid syntax", [Location(self.lexer, p.lineno, p.lexpos, self._filename)])
+
+ def __init__(self, outputdir='', lexer=None):
+ Tokenizer.__init__(self, outputdir, lexer)
+ self.parser = yacc.yacc(module=self,
+ outputdir=outputdir,
+ tabmodule='webidlyacc',
+ errorlog=yacc.NullLogger(),
+ picklefile='WebIDLGrammar.pkl')
+ self._globalScope = IDLScope(BuiltinLocation("<Global Scope>"), None, None)
+ self._installBuiltins(self._globalScope)
+ self._productions = []
+
+ self._filename = "<builtin>"
+ self.lexer.input(Parser._builtins)
+ self._filename = None
+
+ self.parser.parse(lexer=self.lexer,tracking=True)
+
+ def _installBuiltins(self, scope):
+ assert isinstance(scope, IDLScope)
+
+ # xrange omits the last value.
+ for x in xrange(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.Float64Array + 1):
+ builtin = BuiltinTypes[x]
+ name = builtin.name
+
+ typedef = IDLTypedefType(BuiltinLocation("<builtin type>"), builtin, name)
+ typedef.resolve(scope)
+
+ @ staticmethod
+ def handleModifiers(type, modifiers):
+ for (modifier, modifierLocation) in modifiers:
+ assert modifier == IDLMethod.TypeSuffixModifier.QMark or \
+ modifier == IDLMethod.TypeSuffixModifier.Brackets
+
+ if modifier == IDLMethod.TypeSuffixModifier.QMark:
+ type = IDLNullableType(modifierLocation, type)
+ elif modifier == IDLMethod.TypeSuffixModifier.Brackets:
+ type = IDLArrayType(modifierLocation, type)
+
+ return type
+
+ def parse(self, t, filename=None):
+ self.lexer.input(t)
+
+ #for tok in iter(self.lexer.token, None):
+ # print tok
+
+ self._filename = filename
+ self._productions.extend(self.parser.parse(lexer=self.lexer,tracking=True))
+ self._filename = None
+
+ def finish(self):
+ # First, finish all the IDLImplementsStatements. In particular, we
+ # have to make sure we do those before we do the IDLInterfaces.
+ # XXX khuey hates this bit and wants to nuke it from orbit.
+ implementsStatements = [ p for p in self._productions if
+ isinstance(p, IDLImplementsStatement)]
+ otherStatements = [ p for p in self._productions if
+ not isinstance(p, IDLImplementsStatement)]
+ for production in implementsStatements:
+ production.finish(self.globalScope())
+ for production in otherStatements:
+ production.finish(self.globalScope())
+
+ # Do any post-finish validation we need to do
+ for production in self._productions:
+ production.validate()
+
+ # De-duplicate self._productions, without modifying its order.
+ seen = set()
+ result = []
+ for p in self._productions:
+ if p not in seen:
+ seen.add(p)
+ result.append(p)
+ return result
+
+ def reset(self):
+ return Parser(lexer=self.lexer)
+
+ # Builtin IDL defined by WebIDL
+ _builtins = """
+ typedef unsigned long long DOMTimeStamp;
+ """
+
+def main():
+ # Parse arguments.
+ from optparse import OptionParser
+ usageString = "usage: %prog [options] files"
+ o = OptionParser(usage=usageString)
+ o.add_option("--cachedir", dest='cachedir', default=None,
+ help="Directory in which to cache lex/parse tables.")
+ o.add_option("--verbose-errors", action='store_true', default=False,
+ help="When an error happens, display the Python traceback.")
+ (options, args) = o.parse_args()
+
+ if len(args) < 1:
+ o.error(usageString)
+
+ fileList = args
+ baseDir = os.getcwd()
+
+ # Parse the WebIDL.
+ parser = Parser(options.cachedir)
+ try:
+ for filename in fileList:
+ fullPath = os.path.normpath(os.path.join(baseDir, filename))
+ f = open(fullPath, 'rb')
+ lines = f.readlines()
+ f.close()
+ print fullPath
+ parser.parse(''.join(lines), fullPath)
+ parser.finish()
+ except WebIDLError, e:
+ if options.verbose_errors:
+ traceback.print_exc()
+ else:
+ print e
+
+if __name__ == '__main__':
+ main()
+
diff --git a/third_party/__init__.py b/third_party/__init__.py
new file mode 100644
index 00000000..8fa2136f
--- /dev/null
+++ b/third_party/__init__.py
@@ -0,0 +1,2 @@
+#
+
diff --git a/tools/bindings_generator.py b/tools/bindings_generator.py
index 5bf0996e..9bc8b929 100755
--- a/tools/bindings_generator.py
+++ b/tools/bindings_generator.py
@@ -1,6 +1,61 @@
#!/usr/bin/env python2
'''
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+XXX THIS IS DEPRECATED, see webidl_binder.py XXX
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Use CppHeaderParser to parse some C++ headers, and generate binding code for them.
Usage:
diff --git a/tools/bisect_pair_lines.py b/tools/bisect_pair_lines.py
new file mode 100644
index 00000000..f698ef2a
--- /dev/null
+++ b/tools/bisect_pair_lines.py
@@ -0,0 +1,63 @@
+'''
+Given two similar files, for example one with an additional optimization pass,
+and with different results, will bisect between them to find the smallest
+diff that makes the outputs different.
+Unlike bisect_pairs, this uses lines instead of diffs. We replace line by line. This assumes
+the programs differ on each line but lines have not been added or removed
+'''
+
+import os, sys, shutil
+from subprocess import Popen, PIPE, STDOUT
+
+__rootpath__ = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
+def path_from_root(*pathelems):
+ return os.path.join(__rootpath__, *pathelems)
+exec(open(path_from_root('tools', 'shared.py'), 'r').read())
+
+file1 = open(sys.argv[1]).read()
+file2 = open(sys.argv[2]).read()
+
+leftf = open('left', 'w')
+leftf.write(file1)
+leftf.close()
+
+rightf = open('right', 'w')
+rightf.write(file2)
+rightf.close()
+
+def run_code(name):
+ ret = run_js(name, stderr=PIPE, full_output=True)
+ # fix stack traces
+ ret = filter(lambda line: not line.startswith(' at ') and not name in line, ret.split('\n'))
+ return '\n'.join(ret)
+
+print 'running files'
+left_result = run_code('left')
+right_result = run_code('right') # right as in left-right, not as in correct
+assert left_result != right_result
+
+low = 0
+high = file1.count('\n')
+
+print 'beginning bisection, %d lines' % high
+
+left_lines = file1.split('\n')
+right_lines = file2.split('\n')
+
+while True:
+ mid = int((low + high)/2)
+ print low, high, ' current: %d' % mid,
+ open('middle', 'w').write('\n'.join(left_lines[:mid] + right_lines[mid:]))
+ shutil.copyfile('middle', 'middle' + str(mid))
+ result = run_code('middle')
+ print result == left_result, result == right_result#, 'XXX', left_result, 'YYY', result, 'ZZZ', right_result
+ if mid == low or mid == high: break
+ if result == right_result:
+ low = mid
+ elif result == left_result:
+ high = mid
+ else:
+ raise Exception('new result!?!?')
+
+print 'middle%d is like left, middle%d is like right' % (mid+1, mid)
+
diff --git a/tools/eliminator/asm-eliminator-test-output.js b/tools/eliminator/asm-eliminator-test-output.js
index 9caf99d0..ab4c13cc 100644
--- a/tools/eliminator/asm-eliminator-test-output.js
+++ b/tools/eliminator/asm-eliminator-test-output.js
@@ -24,7 +24,7 @@ function __Z11printResultPiS_j($needle, $haystack, $len) {
}
function _segment_holding($addr) {
$addr = $addr | 0;
- var $sp_0 = 0, $3 = 0, $12 = 0, $_0 = 0, label = 0;
+ var $sp_0 = 0, $3 = 0, $_0 = 0, label = 0;
$sp_0 = __gm_ + 444 | 0;
while (1) {
$3 = HEAP32[(($sp_0 | 0) & 16777215) >> 2] | 0;
@@ -35,13 +35,11 @@ function _segment_holding($addr) {
break;
}
}
- $12 = HEAP32[(($sp_0 + 8 | 0) & 16777215) >> 2] | 0;
- if (($12 | 0) == 0) {
+ $sp_0 = HEAP32[(($sp_0 + 8 | 0) & 16777215) >> 2] | 0;
+ if (($sp_0 | 0) == 0) {
$_0 = 0;
label = 1659;
break;
- } else {
- $sp_0 = $12;
}
}
if (label == 1659) {
@@ -147,27 +145,25 @@ function looop3() {
}
}
function looop4() {
- var i = 0, helper = 0;
+ var i = 0, i$looptemp = 0;
while (1) {
do_it();
- helper = i + 1 | 0;
- f(i, helper);
- if (condition()) {
- i = helper;
- } else {
+ i$looptemp = i;
+ i = i + 1 | 0;
+ f(i$looptemp, i);
+ if (!condition()) {
break;
}
}
}
function looop4b() {
- var i = 0, helper = 0;
+ var i = 0, i$looptemp = 0;
while (1) {
do_it();
- helper = i + 1 | 0;
- g(helper);
- if (condition(i)) {
- i = helper;
- } else {
+ i$looptemp = i;
+ i = i + 1 | 0;
+ g(i);
+ if (!condition(i$looptemp)) {
break;
}
}
@@ -251,24 +247,22 @@ function multiloop($n_0, $35) {
function multiloop2($n_0, $35) {
$n_0 = $n_0 | 0;
$35 = $35 | 0;
- var $p_0 = 0, $39 = 0, $41 = 0, $46 = 0;
+ var $p_0 = 0, $41 = 0, $p_0$looptemp = 0;
$n_0 = $35;
$p_0 = (HEAP32[$15 >> 2] | 0) + ($35 << 1) | 0;
while (1) {
- $39 = $p_0 - 2 | 0;
- $41 = HEAPU16[$39 >> 1] | 0;
+ $p_0$looptemp = $p_0;
+ $p_0 = $p_0 - 2 | 0;
+ $41 = HEAPU16[$p_0 >> 1] | 0;
if ($41 >>> 0 < $2 >>> 0) {
$_off0 = 0;
} else {
$_off0 = $41 - $2 & 65535;
}
- HEAP16[$39 >> 1] = $p_0;
- $46 = $n_0 - 1 | 0;
- if (($46 | 0) == 0) {
+ HEAP16[$p_0 >> 1] = $p_0$looptemp;
+ $n_0 = $n_0 - 1 | 0;
+ if (($n_0 | 0) == 0) {
break;
- } else {
- $n_0 = $46;
- $p_0 = $39;
}
}
}
@@ -822,7 +816,7 @@ function selfAssign() {
function elimOneLoopVar($argc, $argv) {
$argc = $argc | 0;
$argv = $argv | 0;
- var $arg$0 = 0, $call10 = Math_fround(0), $curri$012 = 0, $inc = 0, $j$010 = 0, $ok$0 = 0, $primes$011 = 0, $retval$0 = 0, $vararg_buffer1 = 0;
+ var $arg$0 = 0, $call10 = Math_fround(0), $curri$012 = 0, $j$010 = 0, $ok$0 = 0, $primes$011 = 0, $retval$0 = 0, $vararg_buffer1 = 0;
$curri$012 = 2;
$primes$011 = 0;
while (1) {
@@ -831,14 +825,12 @@ function elimOneLoopVar($argc, $argv) {
if ($call10 > Math_fround(+2)) {
$j$010 = 2;
while (1) {
- $inc = $j$010 + 1 | 0;
if ((($curri$012 | 0) % ($j$010 | 0) & -1 | 0) == 0) {
$ok$0 = 0;
break L15;
}
- if (Math_fround($inc | 0) < $call10) {
- $j$010 = $inc;
- } else {
+ $j$010 = $j$010 + 1 | 0;
+ if (!(Math_fround($j$010 | 0) < $call10)) {
$ok$0 = 1;
break;
}
@@ -901,4 +893,79 @@ function elimOneLoopVar4() {
}
}
}
+function elimOneLoopVarStillUsed() {
+ var $call10 = Math_fround(0), $curri$012 = 0, $j$010 = 0, $retval$0 = 0;
+ while (1) {
+ if ((($curri$012 | 0) % ($j$010 | 0) & -1 | 0) == 0) {
+ break;
+ }
+ $j$010 = $j$010 + 1 | 0;
+ if (!(Math_fround($j$010 | 0) < $call10)) {
+ break;
+ }
+ }
+ return $retval$0 | 0;
+}
+function elimOneLoopVarStillUsedSE() {
+ var $call10 = Math_fround(0), $curri$012 = 0, $j$010 = 0, $retval$0 = 0, $j$010$looptemp = 0;
+ while (1) {
+ $j$010$looptemp = $j$010;
+ $j$010 = $j$010 + sideeffect() | 0;
+ if ((($curri$012 | 0) % ($j$010$looptemp | 0) & -1 | 0) == 0) {
+ break;
+ }
+ if (!(Math_fround($j$010 | 0) < $call10)) {
+ break;
+ }
+ }
+ return $retval$0 | 0;
+}
+function elimOneLoopVar5() {
+ var $storemerge3$neg9 = 0, $18 = 0, $25 = 0, $26 = 0, $30 = 0, $jp = 0;
+ $storemerge3$neg9 = -1;
+ while (1) {
+ $25 = $jp + ($26 << 2) | 0;
+ HEAP32[$25 >> 2] = ($18 + $storemerge3$neg9 | 0) + (HEAP32[$25 >> 2] | 0) | 0;
+ $30 = $26 + 1 | 0;
+ if (($30 | 0) == 63) {
+ f($30);
+ break;
+ } else {
+ $storemerge3$neg9 = $18 ^ -1;
+ $26 = $30;
+ }
+ }
+}
+function loopVarWithContinue() {
+ var i = 0, i$looptemp = 0;
+ i = 0;
+ while (1) {
+ i$looptemp = i;
+ i = i + 1;
+ if (check()) {
+ i = i$looptemp + 1;
+ continue;
+ }
+ work(i);
+ work(i$looptemp);
+ work(i);
+ if (check()) {
+ break;
+ }
+ }
+}
+function helperExtraUse() {
+ var i = 0, i$looptemp = 0;
+ i = 0;
+ while (1) {
+ i$looptemp = i;
+ i = i + 1;
+ work(i$looptemp);
+ work(i);
+ if (check()) {
+ break;
+ }
+ }
+ return i;
+}
diff --git a/tools/eliminator/asm-eliminator-test.js b/tools/eliminator/asm-eliminator-test.js
index a3de3d9d..7b949c44 100644
--- a/tools/eliminator/asm-eliminator-test.js
+++ b/tools/eliminator/asm-eliminator-test.js
@@ -1131,5 +1131,97 @@ function elimOneLoopVar4() {
}
}
}
-// 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", "looop2", "looop3", "looop4", "looop5", "looop6", "looop7", "looop8", "multiloop", "multiloop2", "tempDouble2", "watIf", "select2", "binary", "cute", "selfAssign", "elimOneLoopVar", "elimOneLoopVar2", "elimOneLoopVar3", "elimOneLoopVar4"]
+function elimOneLoopVarStillUsed() {
+ var $0 = 0, $1 = 0, $arg$0 = 0, $arrayidx = 0, $call10 = Math_fround(0), $cmp = 0, $cmp11 = 0, $cmp119 = 0, $cmp12 = 0, $cmp7 = 0, $conv = 0, $conv8 = Math_fround(0), $conv9 = Math_fround(0), $curri$012 = 0, $inc = 0, $inc14$primes$0 = 0, $inc16 = 0, $j$010 = 0, $ok$0 = 0;
+ var $primes$011 = 0, $rem = 0, $retval$0 = 0, $sub = 0, $vararg_buffer1 = 0, label = 0, sp = 0;
+ while (1) {
+ $rem = ($curri$012 | 0) % ($j$010 | 0) & -1;
+ $cmp12 = ($rem | 0) == 0;
+ $inc = $j$010 + 1 | 0;
+ if ($cmp12) {
+ $ok$0 = 0;
+ break;
+ }
+ $conv8 = Math_fround($inc | 0);
+ $cmp11 = $conv8 < $call10;
+ if ($cmp11) {
+ $j$010 = $inc;
+ } else {
+ break;
+ }
+ }
+ return $retval$0 | 0;
+}
+function elimOneLoopVarStillUsedSE() {
+ var $0 = 0, $1 = 0, $arg$0 = 0, $arrayidx = 0, $call10 = Math_fround(0), $cmp = 0, $cmp11 = 0, $cmp119 = 0, $cmp12 = 0, $cmp7 = 0, $conv = 0, $conv8 = Math_fround(0), $conv9 = Math_fround(0), $curri$012 = 0, $inc = 0, $inc14$primes$0 = 0, $inc16 = 0, $j$010 = 0, $ok$0 = 0;
+ var $primes$011 = 0, $rem = 0, $retval$0 = 0, $sub = 0, $vararg_buffer1 = 0, label = 0, sp = 0;
+ while (1) {
+ $rem = ($curri$012 | 0) % ($j$010 | 0) & -1;
+ $cmp12 = ($rem | 0) == 0;
+ $inc = $j$010 + sideeffect() | 0; // side effect!
+ if ($cmp12) {
+ $ok$0 = 0;
+ break;
+ }
+ $conv8 = Math_fround($inc | 0);
+ $cmp11 = $conv8 < $call10;
+ if ($cmp11) {
+ $j$010 = $inc;
+ } else {
+ break;
+ }
+ }
+ return $retval$0 | 0;
+}
+function elimOneLoopVar5() {
+ var $storemerge3$neg9 = 0, $18 = 0, $25 = 0, $26 = 0, $30 = 0, $jp = 0;
+ $storemerge3$neg9 = -1;
+ while (1) {
+ $25 = $jp + ($26 << 2) | 0;
+ HEAP32[$25 >> 2] = ($18 + $storemerge3$neg9 | 0) + (HEAP32[$25 >> 2] | 0) | 0;
+ $30 = $26 + 1 | 0;
+ if (($30 | 0) == 63) {
+ f($30); // loop var used here, so cannot be easily optimized
+ break;
+ } else {
+ $storemerge3$neg9 = $18 ^ -1;
+ $26 = $30;
+ }
+ }
+}
+function loopVarWithContinue() {
+ var i = 0, inc = 0;
+ i = 0;
+ while (1) {
+ inc = i + 1;
+ if (check()) {
+ i = i + 1;
+ continue;
+ }
+ work(inc);
+ work(i);
+ work(inc);
+ if (check()) {
+ break;
+ } else {
+ i = inc;
+ }
+ }
+}
+function helperExtraUse() {
+ var i = 0, inc = 0;
+ i = 0;
+ while (1) {
+ inc = i + 1;
+ work(i);
+ work(inc);
+ if (check()) {
+ break;
+ } else {
+ i = inc;
+ }
+ }
+ return inc;
+}
+// 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", "looop2", "looop3", "looop4", "looop5", "looop6", "looop7", "looop8", "multiloop", "multiloop2", "tempDouble2", "watIf", "select2", "binary", "cute", "selfAssign", "elimOneLoopVar", "elimOneLoopVar2", "elimOneLoopVar3", "elimOneLoopVar4", "elimOneLoopVarStillUsed", "elimOneLoopVarStillUsedSE", "elimOneLoopVar5", "helperExtraUse"]
diff --git a/tools/ffdb.py b/tools/ffdb.py
new file mode 100755
index 00000000..2171cb0e
--- /dev/null
+++ b/tools/ffdb.py
@@ -0,0 +1,453 @@
+#!/usr/bin/env python
+
+import socket, json, sys, uuid, datetime, time, logging, cgi, zipfile, os, tempfile, atexit, subprocess, re, base64, struct, imghdr
+
+LOG_VERBOSE = False # Verbose printing enabled with --verbose
+HOST = 'localhost' # The remote host to connect to the B2G device
+PORT = 6000 # The port on the host on which the B2G device listens on
+b2g_socket = None # Python socket object for the active connection to the B2G device
+read_queue = '' # Inbound queue of partial data read so far from the device
+
+webappsActorName = None
+
+def sizeof_fmt(num):
+ for x in ['bytes','KB','MB','GB']:
+ if num < 1024.0:
+ return "%3.1f%s" % (num, x)
+ num /= 1024.0
+ return "%3.1f%s" % (num, 'TB')
+
+def zipdir(path, zipfilename):
+ try:
+ import zlib
+ zip_mode = zipfile.ZIP_DEFLATED
+ except:
+ zip_mode = zipfile.ZIP_STORED
+
+ zipf = zipfile.ZipFile(zipfilename, 'w', zip_mode)
+ files_to_compress = []
+ for root, dirs, files in os.walk(path):
+ for file in files:
+ files_to_compress += [(root, file)]
+
+ n = 1
+ for tuple in files_to_compress:
+ (root, file) = tuple
+ filename = os.path.join(root, file)
+ filesize = os.path.getsize(filename)
+ path_in_archive = os.path.relpath(filename, path)
+ print 'Compressing ' + str(n) + '/' + str(len(files_to_compress)) + ': "' + path_in_archive + '" (' + sizeof_fmt(filesize) + ')...'
+ n += 1
+ zipf.write(os.path.join(root, file), path_in_archive)
+ zipf.close()
+ print 'Done. '
+
+# Returns given log message formatted to be outputted on a HTML page.
+def format_html(msg):
+ if not msg.endswith('\n'):
+ msg += '\n'
+ msg = cgi.escape(msg)
+ msg = msg.replace('\r\n', '<br />').replace('\n', '<br />')
+ return msg
+
+# Prints a verbose log message to stdout channel. Only shown if run with --verbose.
+def logv(msg):
+ if LOG_VERBOSE:
+ sys.stdout.write(format_html(msg) + '\n')
+ sys.stdout.flush()
+
+# Reads data from the socket, and tries to parse what we have got so far as a JSON message.
+# The messages are of form "bytelength:{jsondict}", where bytelength tells how many bytes
+# there are in the data that comes after the colon.
+# Returns a JSON dictionary of the received message.
+def read_b2g_response(print_errors_to_console = True):
+ global read_queue, b2g_socket
+ read_queue += b2g_socket.recv(65536*2)
+ payload = ''
+ while ':' in read_queue:
+ semicolon = read_queue.index(':')
+ payload_len = int(read_queue[:semicolon])
+ if semicolon+1+payload_len > len(read_queue):
+ read_queue += b2g_socket.recv(65536*2)
+ continue
+ payload = read_queue[semicolon+1:semicolon+1+payload_len]
+ read_queue = read_queue[semicolon+1+payload_len:]
+ logv('Read a message of size ' + str(payload_len) + 'b from socket.')
+ payload = json.loads(payload)
+ # Log received errors immediately to console
+ if print_errors_to_console and 'error' in payload:
+ print >> sys.stderr, 'Received error "' + payload['error'] + '"! Reason: ' + payload['message']
+ return payload
+
+# Sends a command to the B2G device and waits for the response and returns it as a JSON dict.
+def send_b2g_cmd(to, cmd, data = {}, print_errors_to_console = True):
+ global b2g_socket
+ msg = { 'to': to, 'type': cmd}
+ msg = dict(msg.items() + data.items())
+ msg = json.dumps(msg, encoding='latin-1')
+ msg = msg.replace('\\\\', '\\')
+ msg = str(len(msg))+':'+msg
+ logv('Sending cmd:' + cmd + ' to:' + to)
+ b2g_socket.sendall(msg)
+ return read_b2g_response(print_errors_to_console)
+
+def escape_bytes(b):
+ return str(b)
+
+# Sends a data fragment of a packaged app upload. This is a special-case version of the send_b2g_cmd
+# command optimized for performance.
+def send_b2g_data_chunk(to, data_blob):
+ byte_str = []
+ e = '\u0000'
+ # '"' == 34
+ # '\' == 92
+ i = 0
+ while i < len(data_blob):
+ o = ord(data_blob[i])
+# if o == 34 or o == 92 or o >= 128 or o <= 32:#o <= 32 or o >= 36:# or o == ord('\\'):
+ if o <= 34 or o >= 128 or o == 92:
+ c = hex(o)[2:]
+ byte_str += e[:-len(c)] + c
+ else:
+ byte_str += data_blob[i]
+ i += 1
+ message = '{"to":"'+to+'","type":"chunk","chunk":"' + ''.join(byte_str) + '"}'
+ message = str(len(message)) + ':' + message
+ logv('{"to":"'+to+'","type":"chunk","chunk":"<data>"}')
+ b2g_socket.sendall(message)
+ return read_b2g_response()
+
+def send_b2g_bulk_data(to, data_blob):
+ message = 'bulk ' + to + ' stream ' + str(len(data_blob)) + ':'
+ logv(message)
+ b2g_socket.sendall(message)
+ b2g_socket.sendall(data_blob)
+ # It seems that B2G doesn't send any response JSON back after a bulk transfer is finished, so no read_b2g_response() here.
+
+# Queries the device for a list of all installed apps.
+def b2g_get_appslist():
+ global webappsActorName
+ apps = send_b2g_cmd(webappsActorName, 'getAll')
+ return apps['apps']
+
+# Queries the device for a list of all currently running apps.
+def b2g_get_runningapps():
+ global webappsActorName
+ apps = send_b2g_cmd(webappsActorName, 'listRunningApps')
+ return apps['apps'] # Returns manifestURLs of all running apps
+
+def print_applist(applist, running_app_manifests, print_removable):
+ num_printed = 0
+ for app in applist:
+ if print_removable or app['removable']: # Print only removable apps unless --all is specified, skip the built-in apps that can't be uninstalled.
+ if 'manifest' in app and 'version' in app['manifest']:
+ version = " version '" + app['manifest']['version'] + "'"
+ else:
+ version = ''
+ if app['manifestURL'] in running_app_manifests:
+ version += ' RUNNING'
+ print ' ' + str(app['localId']) + ': "' + app['name'] + '"' + version
+ num_printed += 1
+ return num_printed
+
+def main():
+ global b2g_socket, webappsActorName, HOST, PORT, VERBOSE
+ if len(sys.argv) < 2 or '--help' in sys.argv or 'help' in sys.argv or '-v' in sys.argv:
+ print '''Firefox OS Debug Bridge, a tool for automating FFOS device tasks from the command line.
+
+ Usage: ffdb.py <command>, where command is one of:
+
+ list [--running] [--all]: Prints out the user applications installed on the device.
+ If --running is passed, only the currently opened apps are shown.
+ If --all is specified, then also uninstallable system applications are listed.
+ launch <app>: Starts the given application. If already running, brings to front.
+ close <app>: Terminates the execution of the given application.
+ uninstall <app>: Removes the given application from the device.
+ install <path>: Uploads and installs a packaged app that resides in the given local directory.
+ <path> may either refer to a directory containing a packaged app, or to a prepackaged zip file.
+ log <app> [--clear]: Starts a persistent log listener that reads web console messages from the given application.
+ If --clear is passed, the message log for that application is cleared instead.
+ navigate <url>: Opens the given web page in the B2G browser.
+ screenshot [filename.png]: Takes a screenshot of the current contents displayed on the device. If an optional
+ filename is specified, the screenshot is saved to that file. Otherwise the filename
+ will be autogenerated.
+
+ Options: Additionally, the following options may be passed to control FFDB execution:
+
+ --host <hostname>: Specifies the target network address to connect to. Default: 'localhost'.
+ --port <number>: Specifies the network port to connect to. Default: 6000.
+ --verbose: Enables verbose printing, mostly useful for debugging.
+ --simulator: Signal that we will be connecting to a FFOS simulator and not a real device.
+
+ In the above, whenever a command requires an <app> to be specified, either the human-readable name,
+ localId or manifestURL of the application can be used.'''
+
+ sys.exit(0)
+
+ connect_to_simulator = False
+
+ options_with_value = ['--host', '--port']
+ options = options_with_value + ['--verbose', '--simulator']
+ # Process options
+ for i in range(0, len(sys.argv)):
+ if sys.argv[i] in options_with_value:
+ if i+1 >= sys.argv or sys.argv[i+1].startswith('-'):
+ print >> sys.stderr, "Missing value for option " + sys.argv[i] +'!'
+ sys.exit(1)
+ if sys.argv[i] == '--host':
+ HOST = sys.argv[i+1]
+ elif sys.argv[i] == '--port':
+ PORT = int(sys.argv[i+1])
+ elif sys.argv[i] == '--verbose':
+ VERBOSE = True
+ elif sys.argv[i] == '--simulator':
+ connect_to_simulator = True
+
+ # Clear the processed options so that parsing the commands below won't trip up on these.
+ if sys.argv[i] in options: sys.argv[i] = ''
+ if sys.argv[i] in options_with_value: sys.argv[i+1] = ''
+
+ sys.argv = filter(lambda x: len(x) > 0, sys.argv)
+
+ b2g_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ try:
+ b2g_socket.connect((HOST, PORT))
+ except Exception, e:
+ if e[0] == 61: # Connection refused
+ if (HOST == 'localhost' or HOST == '127.0.0.1') and not connect_to_simulator:
+ cmd = ['adb', 'forward', 'tcp:'+str(PORT), 'localfilesystem:/data/local/debugger-socket']
+ print 'Connection to ' + HOST + ':' + str(PORT) + ' refused, attempting to forward device debugger-socket to local address by calling ' + str(cmd) + ':'
+ else:
+ print 'Error! Failed to connect to B2G ' + ('simulator' if connect_to_simulator else 'device') + ' debugger socket at address ' + HOST + ':' + str(PORT) + '!'
+ sys.exit(1)
+ try:
+ retcode = subprocess.check_call(cmd)
+ except Exception, e:
+ print 'Error! Failed to execute adb: ' + str(e)
+ print "Check that the device is connected properly, call 'adb devices' to list the detected devices."
+ sys.exit(1)
+ if retcode is not 0:
+ print 'Error! Failed to connect to B2G device and executing adb failed with return code ' + retcode + '!'
+ sys.exit(1)
+ time.sleep(3)
+ # Try again:
+ try:
+ b2g_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ b2g_socket.connect((HOST, PORT))
+ except Exception, e:
+ print 'Error! Failed to connect to B2G device debugger socket at address ' + HOST + ':' + str(PORT) + '!'
+ sys.exit(1)
+
+ handshake = read_b2g_response()
+ logv('Connected. Handshake: ' + str(handshake))
+
+ data = send_b2g_cmd('root', 'listTabs')
+ deviceActorName = data['deviceActor']
+ logv('deviceActor: ' + deviceActorName)
+ webappsActorName = data['webappsActor']
+ logv('webappsActor: ' + webappsActorName)
+
+ send_b2g_cmd(deviceActorName, 'getDescription')
+ send_b2g_cmd(deviceActorName, 'getRawPermissionsTable')
+
+ apps = b2g_get_appslist()
+
+ if sys.argv[1] == 'list':
+ running_app_manifests = b2g_get_runningapps()
+ printed_apps = apps
+ print_only_running = '--running' in sys.argv and not '--all' in sys.argv
+ if print_only_running: # Print running apps only?
+ print 'Running applications by id:'
+ printed_apps = filter(lambda x: x['manifestURL'] in running_app_manifests, apps)
+ else:
+ print 'Installed applications by id:'
+ num_printed = print_applist(printed_apps, running_app_manifests, '--all' in sys.argv or print_only_running)
+ if num_printed == 0:
+ if print_only_running:
+ print ' No applications running.'
+ else:
+ print ' No applications installed.'
+ if not '--all' in sys.argv and not print_only_running:
+ print 'Not showing built-in apps that cannot be uninstalled. Pass --all to include those in the listing.'
+ elif sys.argv[1] == 'launch' or sys.argv[1] == 'close' or sys.argv[1] == 'uninstall' or sys.argv[1] == 'getAppActor':
+ if len(sys.argv) < 3:
+ print 'Error! No application name given! Usage: ' + sys.argv[0] + ' ' + sys.argv[1] + ' <app>'
+ return 1
+ for app in apps:
+ if str(app['localId']) == sys.argv[2] or app['name'] == sys.argv[2] or app['manifestURL'] == sys.argv[2]:
+ send_b2g_cmd(webappsActorName, sys.argv[1], { 'manifestURL': app['manifestURL'] })
+ return 0
+ print 'Error! Application "' + sys.argv[2] + '" was not found! Use the \'list\' command to find installed applications.'
+ return 1
+ elif sys.argv[1] == 'install':
+ if len(sys.argv) < 3:
+ print 'Error! No application path given! Usage: ' + sys.argv[0] + ' ' + sys.argv[1] + ' <path>'
+ return 1
+ target_app_path = sys.argv[2]
+ if os.path.isdir(target_app_path):
+ print 'Zipping up the contents of directory "' + target_app_path + '"...'
+ (oshandle, tempzip) = tempfile.mkstemp(suffix='.zip', prefix='ffdb_temp_')
+ zipdir(target_app_path, tempzip)
+ target_app_path = tempzip
+ # Remember to delete the temporary package after we quit.
+ def delete_temp_file():
+ os.remove(tempzip)
+ atexit.register(delete_temp_file)
+
+ print 'Uploading application package "' + target_app_path + '"...'
+ print 'Size of compressed package: ' + sizeof_fmt(os.path.getsize(target_app_path)) + '.'
+ app_file = open(target_app_path, 'rb')
+ data = app_file.read()
+ file_size = len(data)
+
+ uploadResponse = send_b2g_cmd(webappsActorName, 'uploadPackage', { 'bulk': 'true'}, print_errors_to_console = False) # This may fail if on old device.
+ start_time = time.time()
+ if 'actor' in uploadResponse and 'BulkActor' in uploadResponse['actor']: # New B2G 2.0 hotness: binary data transfer
+ packageUploadActor = uploadResponse['actor']
+ send_b2g_bulk_data(packageUploadActor, data)
+ else: # Old B2G 1.4 and older, serialize binary data in JSON text strings (SLOW!)
+ print 'Bulk upload is not supported, uploading binary data with old slow format. Consider flashing your device to FFOS 2.0 or newer to enjoy faster upload speeds.'
+ uploadResponse = send_b2g_cmd(webappsActorName, 'uploadPackage')
+ packageUploadActor = uploadResponse['actor']
+ chunk_size = 4*1024*1024
+ i = 0
+ while i < file_size:
+ chunk = data[i:i+chunk_size]
+
+ send_b2g_data_chunk(packageUploadActor, chunk)
+ i += chunk_size
+ bytes_uploaded = min(i, file_size)
+ cur_time = time.time()
+ secs_elapsed = cur_time - start_time
+ percentage_done = bytes_uploaded * 1.0 / file_size
+ total_time = secs_elapsed / percentage_done
+ time_left = total_time - secs_elapsed
+ print sizeof_fmt(bytes_uploaded) + " uploaded, {:5.1f} % done.".format(percentage_done*100.0) + ' Elapsed: ' + str(int(secs_elapsed)) + ' seconds. Time left: ' + str(datetime.timedelta(seconds=int(time_left))) + '. Data rate: {:5.2f} KB/second.'.format(bytes_uploaded / 1024.0 / secs_elapsed)
+
+ send_b2g_cmd(webappsActorName, 'install', { 'appId': str(uuid.uuid4()), 'upload': packageUploadActor })
+ cur_time = time.time()
+ secs_elapsed = cur_time - start_time
+ print 'Upload of ' + sizeof_fmt(file_size) + ' finished. Total time elapsed: ' + str(int(secs_elapsed)) + ' seconds. Data rate: {:5.2f} KB/second.'.format(file_size / 1024.0 / secs_elapsed)
+ elif sys.argv[1] == 'navigate':
+ if len(sys.argv) < 3:
+ print 'Error! No URL given! Usage: ' + sys.argv[0] + ' ' + sys.argv[1] + ' <url>'
+ return 1
+ browserActor = ''
+ for app in apps:
+ if app['name'] == 'Browser':
+ browserActor = send_b2g_cmd(webappsActorName, 'getAppActor', { 'manifestURL': app['manifestURL'] })
+ break
+ if 'actor' in browserActor:
+ browserActor = browserActor['actor']['actor']
+ send_b2g_cmd(browserActor, 'navigateTo', { 'url': sys.argv[2]})
+ else:
+ print 'Web browser is not running!'
+ elif sys.argv[1] == 'log':
+ appActor = ''
+ for app in apps:
+ if str(app['localId']) == sys.argv[2] or app['name'] == sys.argv[2] or app['manifestURL'] == sys.argv[2]:
+ appActor = send_b2g_cmd(webappsActorName, 'getAppActor', { 'manifestURL': app['manifestURL'] })
+ break
+ if 'actor' in appActor:
+ consoleActor = appActor['actor']['consoleActor']
+
+ if '-c' in sys.argv or '-clear' in sys.argv or '--clear' in sys.argv:
+ send_b2g_cmd(consoleActor, 'clearMessagesCache')
+ print 'Cleared message log.'
+ sys.exit(0)
+
+ msgs = send_b2g_cmd(consoleActor, 'startListeners', { 'listeners': ['PageError','ConsoleAPI','NetworkActivity','FileActivity'] })
+
+ def log_b2g_message(msg):
+ WARNING = '\033[93m'
+ FAIL = '\033[91m'
+ ENDC = '\033[0m'
+ BOLD = "\033[1m"
+ msgs = []
+ if 'type' in msg and msg['type'] == 'consoleAPICall':
+ msgs = [msg['message']]
+ elif 'messages' in msg:
+ msgs = msg['messages']
+
+ for m in msgs:
+ args = m['arguments']
+
+ for arg in args:
+ if m['level'] == 'log':
+ color = 'I/'
+ elif m['level'] == 'warn':
+ color = WARNING + 'W/'
+ elif m['level'] == 'error':
+ color = FAIL + 'E/'
+ else:
+ color = m['level'] + '/'
+
+ print color + str(m['functionName']) + '@' + str(m['filename']) + ':' + str(m['lineNumber']) + ': ' + str(arg) + ENDC
+
+ msgs = send_b2g_cmd(consoleActor, 'getCachedMessages', { 'messageTypes': ['PageError', 'ConsoleAPI'] })
+ log_b2g_message(msgs)
+
+ while True:
+ msg = read_b2g_response()
+ log_b2g_message(msg)
+ else:
+ print 'Application "' + sys.argv[2] + '" is not running!'
+ elif sys.argv[1] == 'screenshot':
+ if len(sys.argv) >= 3:
+ filename = sys.argv[2]
+ if not filename.endswith('.png'):
+ print >> sys.stderr, "Writing screenshots only to .png files are supported!"
+ sys.exit(1)
+ else:
+ filename = time.strftime("screen_%Y%m%d_%H%M%S.png", time.gmtime())
+
+ data_reply = send_b2g_cmd(deviceActorName, 'screenshotToDataURL')
+ data = data_reply['value']
+ data_get_actor = data['actor']
+ data_len = int(data['length'])
+ data_str = data['initial']
+ delim = re.search(",", data_str).start()
+ data_format = data_str[:delim]
+ if data_format != "data:image/png;base64":
+ print >> sys.stderr, "Error: Received screenshot from device in an unexpected format '" + data_format + "'!"
+ sys.exit(1)
+ data = data_str[delim+1:]
+ chunk_size = 65000
+ pos = len(data_str)
+ while pos < data_len:
+ bytes_to_read = min(data_len - pos, chunk_size)
+ data_reply = send_b2g_cmd(data_get_actor, 'substring', { 'start': str(pos), 'end': str(pos + bytes_to_read) })
+ if len(data_reply['substring']) != bytes_to_read:
+ print >> sys.stderr, 'Error! Expected to receive ' + str(bytes_to_read) + ' bytes of image data, but got ' + str(len(data_reply['substring'])) + ' bytes instead!'
+ sys.exit(1)
+ data += data_reply['substring']
+ pos += bytes_to_read
+ send_b2g_cmd(data_get_actor, 'release') # We need to explicitly free the screenshot image string from the device, or the Devtools connection leaks resources!
+ binary_data = base64.b64decode(data)
+ open(filename, 'wb').write(binary_data)
+
+ def get_png_image_size(filename):
+ fhandle = open(filename, 'rb')
+ head = fhandle.read(24)
+ if len(head) != 24:
+ return (-1, -1)
+ check = struct.unpack('>i', head[4:8])[0]
+ if check != 0x0d0a1a0a:
+ return (-1, -1)
+ return struct.unpack('>ii', head[16:24])
+
+ width, height = get_png_image_size(filename)
+ if width <= 0 or height <= 0:
+ print >> sys.stderr, "Wrote " + sizeof_fmt(len(binary_data)) + " to file '" + filename + "', but the contents may be corrupted!"
+ else:
+ print "Wrote " + sizeof_fmt(len(binary_data)) + " to file '" + filename + "' (" + str(width) + 'x' + str(height) + ' pixels).'
+ else:
+ print "Unknown command '" + sys.argv[1] + "'! Pass --help for instructions."
+
+ b2g_socket.close()
+ return 0
+
+if __name__ == '__main__':
+ returncode = main()
+ logv('ffdb.py quitting with process exit code ' + str(returncode))
+ sys.exit(returncode)
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index c4585b84..9b8387be 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -136,6 +136,7 @@ var CONTROL_FLOW = set('do', 'while', 'for', 'if', 'switch');
var NAME_OR_NUM = set('name', 'num');
var ASSOCIATIVE_BINARIES = set('+', '*', '|', '&', '^');
var ALTER_FLOW = set('break', 'continue', 'return');
+var BITWISE = set('|', '&', '^');
var BREAK_CAPTURERS = set('do', 'while', 'for', 'switch');
var CONTINUE_CAPTURERS = LOOP;
@@ -387,14 +388,18 @@ function simplifyExpressions(ast) {
return innerNode;
}
}
- } else if (type === 'binary' && node[1] === '&' && node[3][0] === 'num') {
- // Rewrite (X < Y) & 1 to (X < Y)|0. (Subsequent passes will eliminate
- // the |0 if possible.)
- var input = node[2];
- var amount = node[3][1];
- if (input[0] === 'binary' && (input[1] in COMPARE_OPS) && amount == 1) {
- node[1] = '|';
- node[3][1] = 0;
+ } else if (type === 'binary' && (node[1] in BITWISE)) {
+ for (var i = 2; i <= 3; i++) {
+ var subNode = node[i];
+ if (subNode[0] === 'binary' && subNode[1] === '&' && subNode[3][0] === 'num' && subNode[3][1] == 1) {
+ // Rewrite (X < Y) & 1 to X < Y , when it is going into a bitwise operator. We could
+ // remove even more (just replace &1 with |0, then subsequent passes could remove the |0)
+ // but v8 issue #2513 means the code would then run very slowly in chrome.
+ var input = subNode[2];
+ if (input[0] === 'binary' && (input[1] in COMPARE_OPS)) {
+ node[i] = input;
+ }
+ }
}
}
});
@@ -749,11 +754,74 @@ function simplifyExpressions(ast) {
});
}
+ function emitsBoolean(node) {
+ if (node[0] === 'num') {
+ return node[1] === 0 || node[1] === 1;
+ }
+ if (node[0] === 'binary') return node[1] in COMPARE_OPS;
+ if (node[0] === 'unary-prefix') return node[1] === '!';
+ if (node[0] === 'conditional') return emitsBoolean(node[2]) && emitsBoolean(node[3]);
+ return false;
+ }
+
+ // expensive | expensive can be turned into expensive ? 1 : expensive, and
+ // expensive | cheap can be turned into cheap ? 1 : expensive,
+ // so that we can avoid the expensive computation, if it has no side effects.
+ function conditionalize(ast) {
+ var MIN_COST = 7;
+ traverse(ast, function(node, type) {
+ if (node[0] === 'binary' && (node[1] === '|' || node[1] === '&') && node[3][0] !== 'num' && node[2][0] !== 'num') {
+ // logical operator on two non-numerical values
+ var left = node[2];
+ var right = node[3];
+ if (!emitsBoolean(left) || !emitsBoolean(right)) return;
+ var leftEffects = hasSideEffects(left);
+ var rightEffects = hasSideEffects(right);
+ if (leftEffects && rightEffects) return; // both must execute
+ // canonicalize with side effects, if any, happening on the left
+ if (rightEffects) {
+ if (measureCost(left) < MIN_COST) return; // avoidable code is too cheap
+ var temp = left;
+ left = right;
+ right = temp;
+ } else if (leftEffects) {
+ if (measureCost(right) < MIN_COST) return; // avoidable code is too cheap
+ } else {
+ // no side effects, reorder based on cost estimation
+ var leftCost = measureCost(left);
+ var rightCost = measureCost(right);
+ if (Math.max(leftCost, rightCost) < MIN_COST) return; // avoidable code is too cheap
+ // canonicalize with expensive code on the right
+ if (leftCost > rightCost) {
+ var temp = left;
+ left = right;
+ right = temp;
+ }
+ }
+ // worth it, perform conditionalization
+ var ret;
+ if (node[1] === '|') {
+ ret = ['conditional', left, ['num', 1], right];
+ } else { // &
+ ret = ['conditional', left, right, ['num', 0]];
+ }
+ if (left[0] === 'unary-prefix' && left[1] === '!') {
+ ret[1] = flipCondition(left);
+ var temp = ret[2];
+ ret[2] = ret[3];
+ ret[3] = temp;
+ }
+ return ret;
+ }
+ });
+ }
+
traverseGeneratedFunctions(ast, function(func) {
simplifyIntegerConversions(func);
simplifyBitops(func);
joinAdditions(func);
simplifyNotComps(func);
+ conditionalize(func);
// simplifyZeroComp(func); TODO: investigate performance
});
}
@@ -970,10 +1038,32 @@ function hasSideEffects(node) { // this is 99% incomplete!
}
return false;
}
+ case 'conditional': return hasSideEffects(node[1]) || hasSideEffects(node[2]) || hasSideEffects(node[3]);
default: return true;
}
}
+// checks if a node has just basic operations, nothing with side effects nor that can notice side effects, which
+// implies we can move it around in the code
+function triviallySafeToMove(node, asmData) {
+ var ok = true;
+ traverse(node, function(node, type) {
+ switch (type) {
+ case 'stat': case 'binary': case 'unary-prefix': case 'assign': case 'num':
+ break;
+ case 'name':
+ if (!(node[1] in asmData.vars) && !(node[1] in asmData.params)) ok = false;
+ break;
+ case 'call':
+ if (callHasSideEffects(node)) ok = false;
+ break;
+ default:
+ ok = false;
+ }
+ });
+ return ok;
+}
+
// Clear out empty ifs and blocks, and redundant blocks/stats and so forth
// Operates on generated functions only
function vacuum(ast) {
@@ -1342,13 +1432,21 @@ var ASM_DOUBLE = 1;
var ASM_FLOAT = 2;
var ASM_NONE = 3;
-function detectAsmCoercion(node, asmInfo) {
+var ASM_FLOAT_ZERO = null; // TODO: share the entire node?
+
+function detectAsmCoercion(node, asmInfo, inVarDef) {
// for params, +x vs x|0, for vars, 0.0 vs 0
if (node[0] === 'num' && node[1].toString().indexOf('.') >= 0) return ASM_DOUBLE;
if (node[0] === 'unary-prefix') return ASM_DOUBLE;
if (node[0] === 'call' && node[1][0] === 'name' && node[1][1] === 'Math_fround') return ASM_FLOAT;
if (asmInfo && node[0] == 'name') return getAsmType(node[1], asmInfo);
- if (node[0] === 'name') return ASM_NONE;
+ if (node[0] === 'name') {
+ if (!inVarDef) return ASM_NONE;
+ // We are in a variable definition, where Math_fround(0) optimized into a global constant becomes f0 = Math_fround(0)
+ if (!ASM_FLOAT_ZERO) ASM_FLOAT_ZERO = node[1];
+ else assert(ASM_FLOAT_ZERO === node[1]);
+ return ASM_FLOAT;
+ }
return ASM_INT;
}
@@ -1366,7 +1464,13 @@ function makeAsmVarDef(v, type) {
switch (type) {
case ASM_INT: return [v, ['num', 0]];
case ASM_DOUBLE: return [v, ['unary-prefix', '+', ['num', 0]]];
- case ASM_FLOAT: return [v, ['call', ['name', 'Math_fround'], [['num', 0]]]];
+ case ASM_FLOAT: {
+ if (ASM_FLOAT_ZERO) {
+ return [v, ['name', ASM_FLOAT_ZERO]];
+ } else {
+ return [v, ['call', ['name', 'Math_fround'], [['num', 0]]]];
+ }
+ }
default: throw 'wha? ' + JSON.stringify([node, type]) + new Error().stack;
}
}
@@ -1409,9 +1513,7 @@ function normalizeAsm(func) {
var name = v[0];
var value = v[1];
if (!(name in data.vars)) {
- assert(value[0] === 'num' || (value[0] === 'unary-prefix' && value[2][0] === 'num') // must be valid coercion no-op
- || (value[0] === 'call' && value[1][0] === 'name' && value[1][1] === 'Math_fround'));
- data.vars[name] = detectAsmCoercion(value);
+ data.vars[name] = detectAsmCoercion(value, null, true);
v.length = 1; // make an un-assigning var
} else {
assert(j === 0, 'cannot break in the middle');
@@ -1425,22 +1527,6 @@ function normalizeAsm(func) {
traverse(stats[i], function(node, type) {
if (type === 'var') {
assert(0, 'should be no vars to fix! ' + func[1] + ' : ' + JSON.stringify(node));
- /*
- for (var j = 0; j < node[1].length; j++) {
- var v = node[1][j];
- var name = v[0];
- var value = v[1];
- if (!(name in data.vars)) {
- if (value[0] != 'name') {
- data.vars[name] = detectAsmCoercion(value); // detect by coercion
- } else {
- var origin = value[1];
- data.vars[name] = data.vars[origin] || ASM_INT; // detect by origin variable, or assume int for non-locals
- }
- }
- }
- unVarify(node[1], node);
- */
} else if (type === 'call' && node[1][0] === 'function') {
assert(!node[1][1]); // anonymous functions only
data.inlines.push(node[1]);
@@ -2001,12 +2087,18 @@ function registerizeHarder(ast) {
function pushActiveLabels(onContinue, onBreak) {
// Push the target junctions for continuing/breaking a loop.
// This should be called before traversing into a loop.
- var newLabels = copy(activeLabels[activeLabels.length-1]);
+ var prevLabels = activeLabels[activeLabels.length-1];
+ var newLabels = copy(prevLabels);
newLabels[null] = [onContinue, onBreak];
if (nextLoopLabel) {
newLabels[nextLoopLabel] = [onContinue, onBreak];
nextLoopLabel = null;
}
+ // An unlabelled 'continue' should jump to innermost loop,
+ // ignoring any nested 'switch' statements.
+ if (onContinue === null && prevLabels[null]) {
+ newLabels[null][0] = prevLabels[null][0];
+ }
activeLabels.push(newLabels);
}
@@ -2156,18 +2248,30 @@ function registerizeHarder(ast) {
break;
case 'conditional':
isInExpr++;
- buildFlowGraph(node[1]);
- var jEnter = markJunction();
- var jExit = addJunction();
- if (node[2]) {
- buildFlowGraph(node[2]);
- }
- joinJunction(jExit);
- setJunction(jEnter);
- if (node[3]) {
- buildFlowGraph(node[3]);
+ // If the conditional has no side-effects, we can treat it as a single
+ // block, which might open up opportunities to remove it entirely.
+ if (!hasSideEffects(node)) {
+ buildFlowGraph(node[1]);
+ if (node[2]) {
+ buildFlowGraph(node[2]);
+ }
+ if (node[3]) {
+ buildFlowGraph(node[3]);
+ }
+ } else {
+ buildFlowGraph(node[1]);
+ var jEnter = markJunction();
+ var jExit = addJunction();
+ if (node[2]) {
+ buildFlowGraph(node[2]);
+ }
+ joinJunction(jExit);
+ setJunction(jEnter);
+ if (node[3]) {
+ buildFlowGraph(node[3]);
+ }
+ joinJunction(jExit);
}
- joinJunction(jExit);
isInExpr--;
break;
case 'while':
@@ -3519,20 +3623,23 @@ function eliminate(ast, memSafe) {
seenUses[name]++;
}
} else if (type === 'while') {
+ if (!asm) return;
// try to remove loop helper variables specifically
var stats = node[2][1];
var last = stats[stats.length-1];
if (last && last[0] === 'if' && last[2][0] === 'block' && last[3] && last[3][0] === 'block') {
var ifTrue = last[2];
var ifFalse = last[3];
+ clearEmptyNodes(ifTrue[1]);
+ clearEmptyNodes(ifFalse[1]);
var flip = false;
- if (ifFalse[1][0] && ifFalse[1][0][0] === 'break') { // canonicalize break in the if
+ if (ifFalse[1][0] && ifFalse[1][ifFalse[1].length-1][0] === 'break') { // canonicalize break in the if-true
var temp = ifFalse;
ifFalse = ifTrue;
ifTrue = temp;
flip = true;
}
- if (ifTrue[1][0] && ifTrue[1][0][0] === 'break') {
+ if (ifTrue[1][0] && ifTrue[1][ifTrue[1].length-1][0] === 'break') {
var assigns = ifFalse[1];
clearEmptyNodes(assigns);
var loopers = [], helpers = [];
@@ -3569,6 +3676,17 @@ function eliminate(ast, memSafe) {
}
}
}
+ // remove loop vars that are used in the if
+ traverse(ifTrue, function(node, type) {
+ if (type === 'name') {
+ var index = loopers.indexOf(node[1]);
+ if (index < 0) index = helpers.indexOf(node[1]);
+ if (index >= 0) {
+ loopers.splice(index, 1);
+ helpers.splice(index, 1);
+ }
+ }
+ });
if (loopers.length === 0) return;
for (var l = 0; l < loopers.length; l++) {
var looper = loopers[l];
@@ -3589,17 +3707,61 @@ function eliminate(ast, memSafe) {
}
}
if (found < 0) return;
- var looperUsed = false;
- for (var i = found+1; i < stats.length && !looperUsed; i++) {
+ // if a loop variable is used after we assigned to the helper, we must save its value and use that.
+ // (note that this can happen due to elimination, if we eliminate an expression containing the
+ // loop var far down, past the assignment!)
+ // first, see if the looper and helper overlap
+ var firstLooperUsage = -1;
+ var lastLooperUsage = -1;
+ var firstHelperUsage = -1;
+ var lastHelperUsage = -1;
+ for (var i = found+1; i < stats.length; i++) {
var curr = i < stats.length-1 ? stats[i] : last[1]; // on the last line, just look in the condition
traverse(curr, function(node, type) {
- if (type === 'name' && node[1] === looper) {
- looperUsed = true;
- return true;
+ if (type === 'name') {
+ if (node[1] === looper) {
+ if (firstLooperUsage < 0) firstLooperUsage = i;
+ lastLooperUsage = i;
+ } else if (node[1] === helper) {
+ if (firstHelperUsage < 0) firstHelperUsage = i;
+ lastHelperUsage = i;
+ }
}
});
}
- if (looperUsed) return;
+ if (firstLooperUsage >= 0) {
+ // the looper is used, we cannot simply merge the two variables
+ if ((firstHelperUsage < 0 || firstHelperUsage > lastLooperUsage) && lastLooperUsage+1 < stats.length && triviallySafeToMove(stats[found], asmData) &&
+ seenUses[helper] === namings[helper]) {
+ // the helper is not used, or it is used after the last use of the looper, so they do not overlap,
+ // and the last looper usage is not on the last line (where we could not append after it), and the
+ // helper is not used outside of the loop.
+ // just move the looper definition to after the looper's last use
+ stats.splice(lastLooperUsage+1, 0, stats[found]);
+ stats.splice(found, 1);
+ } else {
+ // they overlap, we can still proceed with the loop optimization, but we must introduce a
+ // loop temp helper variable
+ var temp = looper + '$looptemp';
+ assert(!(temp in asmData.vars));
+ for (var i = firstLooperUsage; i <= lastLooperUsage; i++) {
+ var curr = i < stats.length-1 ? stats[i] : last[1]; // on the last line, just look in the condition
+ traverse(curr, function looperToLooptemp(node, type) {
+ if (type === 'name') {
+ if (node[1] === looper) {
+ node[1] = temp;
+ }
+ } else if (type === 'assign' && node[2][0] === 'name') {
+ // do not traverse the assignment target, phi assignments to the loop variable must remain
+ traverse(node[3], looperToLooptemp);
+ return null;
+ }
+ });
+ }
+ asmData.vars[temp] = asmData.vars[looper];
+ stats.splice(found, 0, ['stat', ['assign', true, ['name', temp], ['name', looper]]]);
+ }
+ }
}
for (var l = 0; l < helpers.length; l++) {
for (var k = 0; k < helpers.length; k++) {
@@ -3710,7 +3872,7 @@ function minifyGlobals(ast) {
var first = true; // do not minify initial 'var asm ='
// find the globals
traverse(ast, function(node, type) {
- if (type === 'var') {
+ if (type === 'var' || type === 'const') {
if (first) {
first = false;
return;
@@ -3914,6 +4076,21 @@ function measureSize(ast) {
return size;
}
+function measureCost(ast) {
+ var size = 0;
+ traverse(ast, function(node, type) {
+ if (type === 'num' || type === 'unary-prefix') size--;
+ else if (type === 'binary') {
+ if (node[3][0] === 'num' && node[3][1] === 0) size--;
+ else if (node[1] === '/' || node[1] === '%') size += 2;
+ }
+ else if (type === 'call' && !callHasSideEffects(node)) size -= 2;
+ else if (type === 'sub') size++;
+ size++;
+ });
+ return size;
+}
+
function aggressiveVariableEliminationInternal(func, asmData) {
// This removes as many variables as possible. This is often not the best thing because it increases
// code size, but it is far preferable to the risk of split functions needing to do more spilling, so
@@ -4915,36 +5092,44 @@ function safeHeap(ast) {
}
}
} else if (type === 'sub') {
- var heap = node[1][1];
- if (heap[0] !== 'H') return;
- var ptr = fixPtr(node[2], heap);
- // SAFE_HEAP_LOAD(ptr, bytes, isFloat)
- switch (heap) {
- case 'HEAP8': {
- return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 1], ['num', '0'], ['num', '0']]], ASM_INT);
- }
- case 'HEAPU8': {
- return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 1], ['num', '0'], ['num', '1']]], ASM_INT);
- }
- case 'HEAP16': {
- return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 2], ['num', '0'], ['num', '0']]], ASM_INT);
- }
- case 'HEAPU16': {
- return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 2], ['num', '0'], ['num', '1']]], ASM_INT);
- }
- case 'HEAP32': {
- return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '0'], ['num', '0']]], ASM_INT);
- }
- case 'HEAPU32': {
- return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '0'], ['num', '1']]], ASM_INT);
- }
- case 'HEAPF32': {
- return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '1'], ['num', '0']]], ASM_DOUBLE);
- }
- case 'HEAPF64': {
- return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 8], ['num', '1'], ['num', '0']]], ASM_DOUBLE);
+ var target = node[1][1];
+ if (target[0] === 'H') {
+ // heap access
+ var heap = target;
+ var ptr = fixPtr(node[2], heap);
+ // SAFE_HEAP_LOAD(ptr, bytes, isFloat)
+ switch (heap) {
+ case 'HEAP8': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 1], ['num', '0'], ['num', '0']]], ASM_INT);
+ }
+ case 'HEAPU8': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 1], ['num', '0'], ['num', '1']]], ASM_INT);
+ }
+ case 'HEAP16': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 2], ['num', '0'], ['num', '0']]], ASM_INT);
+ }
+ case 'HEAPU16': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 2], ['num', '0'], ['num', '1']]], ASM_INT);
+ }
+ case 'HEAP32': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '0'], ['num', '0']]], ASM_INT);
+ }
+ case 'HEAPU32': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '0'], ['num', '1']]], ASM_INT);
+ }
+ case 'HEAPF32': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '1'], ['num', '0']]], ASM_DOUBLE);
+ }
+ case 'HEAPF64': {
+ return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 8], ['num', '1'], ['num', '0']]], ASM_DOUBLE);
+ }
+ default: throw 'bad heap ' + heap;
}
- default: throw 'bad heap ' + heap;
+ } else {
+ assert(target[0] == 'F');
+ // function table indexing mask
+ assert(node[2][0] === 'binary' && node[2][1] === '&');
+ node[2][2] = makeAsmCoercion(['call', ['name', 'SAFE_FT_MASK'], [makeAsmCoercion(node[2][2], ASM_INT), makeAsmCoercion(node[2][3], ASM_INT)]], ASM_INT);
}
}
});
@@ -4952,10 +5137,19 @@ function safeHeap(ast) {
function optimizeFrounds(ast) {
// collapse fround(fround(..)), which can happen due to elimination
+ // also emit f0 instead of fround(0) (except in returns)
+ var inReturn = false;
function fix(node) {
+ if (node[0] === 'return') inReturn = true;
traverseChildren(node, fix);
- if (node[0] === 'call' && node[1][0] === 'name' && node[1][1] === 'Math_fround' && node[2][0][0] === 'call' && node[2][0][1][0] === 'name' && node[2][0][1][1] === 'Math_fround') {
- return node[2][0];
+ if (node[0] === 'return') inReturn = false;
+ if (node[0] === 'call' && node[1][0] === 'name' && node[1][1] === 'Math_fround') {
+ var arg = node[2][0];
+ if (arg[0] === 'num') {
+ if (!inReturn && arg[1] === 0) return ['name', 'f0'];
+ } else if (arg[0] === 'call' && arg[1][0] === 'name' && arg[1][1] === 'Math_fround') {
+ return arg;
+ }
}
}
traverseChildren(ast, fix);
@@ -4977,7 +5171,9 @@ function prepDotZero(ast) {
function fixDotZero(js) {
return js.replace(/DOT\$ZERO\(([-+]?(0x)?[0-9a-f]*\.?[0-9]+([eE][-+]?[0-9]+)?)\)/g, function(m, num) {
if (num.substr(0, 2) === '0x' || num.substr(0, 3) === '-0x') {
- return eval(num) + '.0';
+ var ret = eval(num).toString();
+ if (ret.indexOf('.') < 0) return ret + '.0';
+ return ret;
}
if (num.indexOf('.') >= 0) return num;
var e = num.indexOf('e');
@@ -4987,8 +5183,11 @@ function fixDotZero(js) {
}
function asmLastOpts(ast) {
+ var statsStack = [];
traverseGeneratedFunctions(ast, function(fun) {
traverse(fun, function(node, type) {
+ var stats = getStatements(node);
+ if (stats) statsStack.push(stats);
if (type === 'while' && node[1][0] === 'num' && node[1][1] === 1 && node[2][0] === 'block' && node[2].length == 2) {
// This is at the end of the pipeline, we can assume all other optimizations are done, and we modify loops
// into shapes that might confuse other passes
@@ -4996,15 +5195,28 @@ function asmLastOpts(ast) {
// while (1) { .. if (..) { break } } ==> do { .. } while(..)
var stats = node[2][1];
var last = stats[stats.length-1];
- if (last && last[0] === 'if' && !last[3] && last[2][0] === 'block' && last[2][1][0] && last[2][1][0][0] === 'break' && !last[2][1][0][1]) {
+ if (last && last[0] === 'if' && !last[3] && last[2][0] === 'block' && last[2][1][0]) {
+ var lastStats = last[2][1];
+ var lastNum = lastStats.length;
+ var lastLast = lastStats[lastNum-1];
+ if (!(lastLast[0] === 'break' && !lastLast[1])) return;// if not a simple break, dangerous
+ for (var i = 0; i < lastNum; i++) {
+ if (lastStats[i][0] !== 'stat' && lastStats[i][0] !== 'break') return; // something dangerous
+ }
+ // ok, a bunch of statements ending in a break
var abort = false;
var stack = 0;
+ var breaks = 0;
traverse(stats, function(node, type) {
- if (type == 'continue') {
- if (stack == 0 || node[1]) { // abort if labeled (we do not analyze labels here yet), or a continue directly on us
+ if (type === 'continue') {
+ if (stack === 0 || node[1]) { // abort if labeled (we do not analyze labels here yet), or a continue directly on us
abort = true;
return true;
}
+ } else if (type === 'break') {
+ if (stack === 0 || node[1]) { // relevant if labeled (we do not analyze labels here yet), or a break directly on us
+ breaks++;
+ }
} else if (type in LOOP) {
stack++;
}
@@ -5014,6 +5226,15 @@ function asmLastOpts(ast) {
}
});
if (abort) return;
+ assert(breaks > 0);
+ if (lastStats.length > 1 && breaks !== 1) return; // if we have code aside from the break, we can only move it out if there is just one break
+ // start to optimize
+ if (lastStats.length > 1) {
+ var parent = statsStack[statsStack.length-1];
+ var me = parent.indexOf(node);
+ if (me < 0) return; // not always directly on a stats, could be in a label for example
+ parent.splice.apply(parent, [me+1, 0].concat(lastStats.slice(0, lastStats.length-1)));
+ }
var conditionToBreak = last[1];
stats.pop();
node[0] = 'do';
@@ -5042,6 +5263,9 @@ function asmLastOpts(ast) {
}
}
}
+ }, function(node, type) {
+ var stats = getStatements(node);
+ if (stats) statsStack.pop();
});
});
}
diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py
index d0284528..e06c2d2f 100644
--- a/tools/js_optimizer.py
+++ b/tools/js_optimizer.py
@@ -137,6 +137,10 @@ def run_on_js(filename, passes, js_engine, jcache, source_map=False, extra_info=
if closure:
passes = filter(lambda p: p != 'closure', passes) # we will do it manually
+ cleanup = 'cleanup' in passes
+ if cleanup:
+ passes = filter(lambda p: p != 'cleanup', passes) # we will do it manually
+
if not know_generated and jcache:
# JCache cannot be used without metadata, since it might reorder stuff, and that's dangerous since only generated can be reordered
# This means jcache does not work after closure compiler runs, for example. But you won't get much benefit from jcache with closure
@@ -291,23 +295,29 @@ EMSCRIPTEN_FUNCS();
for filename in filenames: temp_files.note(filename)
- if closure:
- # run closure on the shell code, everything but what we js-optimize
+ if closure or cleanup:
+ # run on the shell code, everything but what we js-optimize
start_asm = '// EMSCRIPTEN_START_ASM\n'
end_asm = '// EMSCRIPTEN_END_ASM\n'
- closure_sep = 'wakaUnknownBefore(); var asm=wakaUnknownAfter(global,env,buffer)\n'
+ cl_sep = 'wakaUnknownBefore(); var asm=wakaUnknownAfter(global,env,buffer)\n'
- closuree = temp_files.get('.closure.js').name
- c = open(closuree, 'w')
+ cle = temp_files.get('.cl.js').name
+ c = open(cle, 'w')
pre_1, pre_2 = pre.split(start_asm)
post_1, post_2 = post.split(end_asm)
c.write(pre_1)
- c.write(closure_sep)
+ c.write(cl_sep)
c.write(post_2)
c.close()
- closured = shared.Building.closure_compiler(closuree, pretty='minifyWhitespace' not in passes)
- temp_files.note(closured)
- coutput = open(closured).read()
+ if closure:
+ if DEBUG: print >> sys.stderr, 'running closure on shell code'
+ cld = shared.Building.closure_compiler(cle, pretty='minifyWhitespace' not in passes)
+ else:
+ if DEBUG: print >> sys.stderr, 'running cleanup on shell code'
+ cld = cle + '.js'
+ subprocess.Popen(js_engine + [JS_OPTIMIZER, cle, 'noPrintMetadata'] + (['minifyWhitespace'] if 'minifyWhitespace' in passes else []), stdout=open(cld, 'w')).communicate()
+ temp_files.note(cld)
+ coutput = open(cld).read()
coutput = coutput.replace('wakaUnknownBefore();', '')
after = 'wakaUnknownAfter'
start = coutput.find(after)
diff --git a/tools/jsrun.py b/tools/jsrun.py
index f74a1492..d63451db 100644
--- a/tools/jsrun.py
+++ b/tools/jsrun.py
@@ -14,10 +14,10 @@ def timeout_run(proc, timeout=None, note='unnamed process', full_output=False):
out = proc.communicate()
out = map(lambda o: '' if o is None else o, out)
if TRACK_PROCESS_SPAWNS:
- logging.info('Process ' + str(proc.pid) + ' finished after ' + str(time.time() - start) + ' seconds.')
+ logging.info('Process ' + str(proc.pid) + ' finished after ' + str(time.time() - start) + ' seconds. Exit code: ' + str(proc.returncode))
return '\n'.join(out) if full_output else out[0]
-def run_js(filename, engine=None, args=[], check_timeout=False, stdin=None, stdout=PIPE, stderr=None, cwd=None, full_output=False):
+def run_js(filename, engine=None, args=[], check_timeout=False, stdin=None, stdout=PIPE, stderr=None, cwd=None, full_output=False, assert_returncode=None):
if type(engine) is not list:
engine = [engine]
command = engine + [filename] + (['--'] if 'd8' in engine[0] or 'jsc' in engine[0] else []) + args
@@ -30,8 +30,11 @@ def run_js(filename, engine=None, args=[], check_timeout=False, stdin=None, stdo
timeout = 15*60 if check_timeout else None
if TRACK_PROCESS_SPAWNS:
logging.info('Blocking on process ' + str(proc.pid) + ': ' + str(command) + (' for ' + str(timeout) + ' seconds' if timeout else ' until it finishes.'))
- return timeout_run(
+ ret = timeout_run(
proc,
timeout,
'Execution',
full_output=full_output)
+ if assert_returncode is not None and proc.returncode is not assert_returncode:
+ raise Exception('Expected the command ' + str(command) + ' to finish with return code ' + str(assert_returncode) + ', but it returned with code ' + str(proc.returncode) + ' instead! Output: ' + str(ret))
+ return ret
diff --git a/tools/shared.py b/tools/shared.py
index 82bdd98b..7aaa4136 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -326,7 +326,7 @@ def check_fastcomp():
break
d = os.path.dirname(d)
if not seen:
- logging.warning('did not see a source tree above LLVM_DIR, could not verify version numbers match')
+ logging.warning('did not see a source tree above the LLVM root directory (guessing based on directory of %s), could not verify version numbers match' % LLVM_COMPILER)
return True
except Exception, e:
logging.warning('could not check fastcomp: %s' % str(e))
@@ -1144,63 +1144,131 @@ class Building:
unresolved_symbols = set([func[1:] for func in Settings.EXPORTED_FUNCTIONS])
resolved_symbols = set()
temp_dirs = []
- files = map(os.path.abspath, files)
+ def make_paths_absolute(f):
+ if f.startswith('-'): # skip flags
+ return f
+ else:
+ return os.path.abspath(f)
+ files = map(make_paths_absolute, files)
+ # Paths of already included object files from archives.
+ added_contents = set()
+ # Map of archive name to list of extracted object file paths.
+ ar_contents = {}
has_ar = False
for f in files:
- has_ar = has_ar or Building.is_ar(f)
+ if not f.startswith('-'):
+ has_ar = has_ar or Building.is_ar(f)
+
+ # If we have only one archive or the force_archive_contents flag is set,
+ # then we will add every object file we see, regardless of whether it
+ # resolves any undefined symbols.
+ force_add_all = len(files) == 1 or force_archive_contents
+
+ # Considers an object file for inclusion in the link. The object is included
+ # if force_add=True or if the object provides a currently undefined symbol.
+ # If the object is included, the symbol tables are updated and the function
+ # returns True.
+ def consider_object(f, force_add=False):
+ new_symbols = Building.llvm_nm(f)
+ do_add = force_add or not unresolved_symbols.isdisjoint(new_symbols.defs)
+ if do_add:
+ logging.debug('adding object %s to link' % (f))
+ # Update resolved_symbols table with newly resolved symbols
+ resolved_symbols.update(new_symbols.defs)
+ # Update unresolved_symbols table by adding newly unresolved symbols and
+ # removing newly resolved symbols.
+ unresolved_symbols.update(new_symbols.undefs.difference(resolved_symbols))
+ unresolved_symbols.difference_update(new_symbols.defs)
+ actual_files.append(f)
+ return do_add
+
+ def get_archive_contents(f):
+ if f in ar_contents:
+ return ar_contents[f]
+
+ cwd = os.getcwd()
+ try:
+ temp_dir = os.path.join(EMSCRIPTEN_TEMP_DIR, 'ar_output_' + str(os.getpid()) + '_' + str(len(temp_dirs)))
+ temp_dirs.append(temp_dir)
+ safe_ensure_dirs(temp_dir)
+ os.chdir(temp_dir)
+ contents = filter(lambda x: len(x) > 0, Popen([LLVM_AR, 't', f], stdout=PIPE).communicate()[0].split('\n'))
+ if len(contents) == 0:
+ logging.debug('Archive %s appears to be empty (recommendation: link an .so instead of .a)' % f)
+ else:
+ for content in contents: # ar will silently fail if the directory for the file does not exist, so make all the necessary directories
+ dirname = os.path.dirname(content)
+ if dirname:
+ safe_ensure_dirs(dirname)
+ Popen([LLVM_AR, 'xo', f], stdout=PIPE).communicate() # if absolute paths, files will appear there. otherwise, in this directory
+ contents = map(lambda content: os.path.join(temp_dir, content), contents)
+ contents = filter(os.path.exists, map(os.path.abspath, contents))
+ contents = filter(Building.is_bitcode, contents)
+ ar_contents[f] = contents
+ finally:
+ os.chdir(cwd)
+
+ return contents
+
+ # Traverse a single archive. The object files are repeatedly scanned for
+ # newly satisfied symbols until no new symbols are found. Returns true if
+ # any object files were added to the link.
+ def consider_archive(f):
+ added_any_objects = False
+ loop_again = True
+ logging.debug('considering archive %s' % (f))
+ contents = get_archive_contents(f)
+ while loop_again: # repeatedly traverse until we have everything we need
+ loop_again = False
+ for content in contents:
+ if content in added_contents: continue
+ # Link in the .o if it provides symbols, *or* this is a singleton archive (which is apparently an exception in gcc ld)
+ if consider_object(content, force_add=force_add_all):
+ added_contents.add(content)
+ loop_again = True
+ added_any_objects = True
+ logging.debug('done running loop of archive %s' % (f))
+ return added_any_objects
+
+ current_archive_group = None
for f in files:
- if not Building.is_ar(f):
+ if f.startswith('-'):
+ if f in ['--start-group', '-(']:
+ assert current_archive_group is None, 'Nested --start-group, missing --end-group?'
+ current_archive_group = []
+ elif f in ['--end-group', '-)']:
+ assert current_archive_group is not None, '--end-group without --start-group'
+ # rescan the archives in the group until we don't find any more
+ # objects to link.
+ loop_again = True
+ logging.debug('starting archive group loop');
+ while loop_again:
+ loop_again = False
+ for archive in current_archive_group:
+ if consider_archive(archive):
+ loop_again = True
+ logging.debug('done with archive group loop');
+ current_archive_group = None
+ else:
+ logging.debug('Ignoring unsupported link flag: %s' % f)
+ elif not Building.is_ar(f):
if Building.is_bitcode(f):
if has_ar:
- new_symbols = Building.llvm_nm(f)
- resolved_symbols = resolved_symbols.union(new_symbols.defs)
- unresolved_symbols = unresolved_symbols.union(new_symbols.undefs.difference(resolved_symbols)).difference(new_symbols.defs)
- actual_files.append(f)
+ consider_object(f, force_add=True)
+ else:
+ # If there are no archives then we can simply link all valid bitcode
+ # files and skip the symbol table stuff.
+ actual_files.append(f)
else:
# Extract object files from ar archives, and link according to gnu ld semantics
# (link in an entire .o from the archive if it supplies symbols still unresolved)
- cwd = os.getcwd()
- try:
- temp_dir = os.path.join(EMSCRIPTEN_TEMP_DIR, 'ar_output_' + str(os.getpid()) + '_' + str(len(temp_dirs)))
- temp_dirs.append(temp_dir)
- safe_ensure_dirs(temp_dir)
- os.chdir(temp_dir)
- contents = filter(lambda x: len(x) > 0, Popen([LLVM_AR, 't', f], stdout=PIPE).communicate()[0].split('\n'))
- #print >> sys.stderr, ' considering archive', f, ':', contents
- if len(contents) == 0:
- logging.debug('Archive %s appears to be empty (recommendation: link an .so instead of .a)' % f)
- else:
- for content in contents: # ar will silently fail if the directory for the file does not exist, so make all the necessary directories
- dirname = os.path.dirname(content)
- if dirname:
- safe_ensure_dirs(dirname)
- Popen([LLVM_AR, 'xo', f], stdout=PIPE).communicate() # if absolute paths, files will appear there. otherwise, in this directory
- contents = map(lambda content: os.path.join(temp_dir, content), contents)
- contents = filter(os.path.exists, map(os.path.abspath, contents))
- added_contents = set()
- added = True
- #print >> sys.stderr, ' initial undef are now ', unresolved_symbols, '\n'
- while added: # recursively traverse until we have everything we need
- #print >> sys.stderr, ' running loop of archive including for', f
- added = False
- for content in contents:
- if content in added_contents: continue
- new_symbols = Building.llvm_nm(content)
- # Link in the .o if it provides symbols, *or* this is a singleton archive (which is apparently an exception in gcc ld)
- #print >> sys.stderr, 'need', content, '?', unresolved_symbols, 'and we can supply', new_symbols.defs
- #print >> sys.stderr, content, 'DEF', new_symbols.defs, '\n'
- if new_symbols.defs.intersection(unresolved_symbols) or len(files) == 1 or force_archive_contents:
- if Building.is_bitcode(content):
- #print >> sys.stderr, ' adding object', content, '\n'
- resolved_symbols = resolved_symbols.union(new_symbols.defs)
- unresolved_symbols = unresolved_symbols.union(new_symbols.undefs.difference(resolved_symbols)).difference(new_symbols.defs)
- #print >> sys.stderr, ' undef are now ', unresolved_symbols, '\n'
- actual_files.append(content)
- added_contents.add(content)
- added = True
- #print >> sys.stderr, ' done running loop of archive including for', f
- finally:
- os.chdir(cwd)
+ consider_archive(f)
+ # If we're inside a --start-group/--end-group section, add to the list
+ # so we can loop back around later.
+ if current_archive_group is not None:
+ current_archive_group.append(f)
+ assert current_archive_group is None, '--start-group without matching --end-group'
+
try_delete(target)
# Finish link
@@ -1362,12 +1430,10 @@ class Building:
cmdline = [PYTHON, EMSCRIPTEN, filename + ('.o.ll' if append_ext else ''), '-o', filename + '.o.js'] + args
if jsrun.TRACK_PROCESS_SPAWNS:
logging.info('Executing emscripten.py compiler with cmdline "' + ' '.join(cmdline) + '"')
- compiler_output = jsrun.timeout_run(Popen(cmdline, stdout=PIPE), None, 'Compiling')
- #print compiler_output
+ jsrun.timeout_run(Popen(cmdline, stdout=PIPE), None, 'Compiling')
# Detect compilation crashes and errors
- if compiler_output is not None and 'Traceback' in compiler_output and 'in test_' in compiler_output: print compiler_output; assert 0
- assert os.path.exists(filename + '.o.js') and len(open(filename + '.o.js', 'r').read()) > 0, 'Emscripten failed to generate .js: ' + str(compiler_output)
+ assert os.path.exists(filename + '.o.js'), 'Emscripten failed to generate .js'
return filename + '.o.js'
@@ -1650,12 +1716,17 @@ class JS:
return '+0'
@staticmethod
- def make_coercion(value, sig, settings=None):
+ def make_coercion(value, sig, settings=None, ffi_arg=False, ffi_result=False):
settings = settings or Settings
if sig == 'i':
return value + '|0'
elif sig == 'f' and settings.get('PRECISE_F32'):
- return 'Math_fround(' + value + ')'
+ if ffi_arg:
+ return '+Math_fround(' + value + ')'
+ elif ffi_result:
+ return 'Math_fround(+(' + value + '))'
+ else:
+ return 'Math_fround(' + value + ')'
elif sig == 'd' or sig == 'f':
return '+' + value
else:
@@ -1831,7 +1902,11 @@ def unsuffixed_basename(name):
return os.path.basename(unsuffixed(name))
def safe_move(src, dst):
- if os.path.abspath(src) == os.path.abspath(dst):
+ src = os.path.abspath(src)
+ dst = os.path.abspath(dst)
+ if os.path.isdir(dst):
+ dst = os.path.join(dst, os.path.basename(src))
+ if src == dst:
return
shutil.move(src, dst)
diff --git a/tools/system_libs.py b/tools/system_libs.py
index 50910a8a..78bf2d48 100644
--- a/tools/system_libs.py
+++ b/tools/system_libs.py
@@ -55,27 +55,49 @@ def calculate(temp_files, in_temp, stdout, stderr):
os.path.join('libcxx', 'new.cpp'),
]
musl_files = [
+ ['ctype', [
+ 'isdigit.c',
+ 'isspace.c',
+ 'isupper.c',
+ 'tolower.c',
+ ]],
['internal', [
+ 'intscan.c',
'floatscan.c',
'shgetc.c',
]],
['math', [
+ 'frexp.c',
+ 'frexpf.c',
+ 'frexpl.c',
'scalbn.c',
'scalbnl.c',
]],
+ ['multibyte', [
+ 'wctomb.c',
+ 'wcrtomb.c',
+ ]],
['stdio', [
'__overflow.c',
'__toread.c',
'__towrite.c',
'__uflow.c',
+ 'fwrite.c',
+ 'snprintf.c',
+ 'sprintf.c',
+ 'vfprintf.c',
+ 'vsnprintf.c',
+ 'vsprintf.c',
]],
['stdlib', [
'atof.c',
'atoi.c',
'atol.c',
'strtod.c',
+ 'strtol.c',
]],
['string', [
+ 'memchr.c',
'memcmp.c',
'strcasecmp.c',
'strcmp.c',
@@ -103,7 +125,22 @@ def calculate(temp_files, in_temp, stdout, stderr):
def create_libcextra():
logging.debug('building libcextra for cache')
musl_files = [
+ ['compat', [
+ 'strlwr.c',
+ 'strtol_l.c',
+ 'strupr.c'
+ ]],
['ctype', [
+ 'isalnum.c',
+ 'isalpha.c',
+ 'isascii.c',
+ 'isblank.c',
+ 'iscntrl.c',
+ 'isgraph.c',
+ 'islower.c',
+ 'isprint.c',
+ 'ispunct.c',
+ 'isxdigit.c',
'iswalnum.c',
'iswalpha.c',
'iswblank.c',
@@ -117,19 +154,30 @@ def calculate(temp_files, in_temp, stdout, stderr):
'iswspace.c',
'iswupper.c',
'iswxdigit.c',
+ 'toascii.c',
+ 'toupper.c',
'towctrans.c',
'wcswidth.c',
'wctrans.c',
'wcwidth.c',
]],
- ['internal', [
- 'intscan.c',
- ]],
['legacy', [
'err.c',
]],
['locale', [
'iconv.c',
+ 'isalnum_l.c',
+ 'isalpha_l.c',
+ 'isblank_l.c',
+ 'iscntrl_l.c',
+ 'isdigit_l.c',
+ 'isgraph_l.c',
+ 'islower_l.c',
+ 'isprint_l.c',
+ 'ispunct_l.c',
+ 'isspace_l.c',
+ 'isupper_l.c',
+ 'isxdigit_l.c',
'iswalnum_l.c',
'iswalpha_l.c',
'iswblank_l.c',
@@ -148,6 +196,8 @@ def calculate(temp_files, in_temp, stdout, stderr):
'strfmon.c',
'strncasecmp_l.c',
'strxfrm.c',
+ 'tolower_l.c',
+ 'toupper_l.c',
'towctrans_l.c',
'towlower_l.c',
'towupper_l.c',
@@ -198,12 +248,10 @@ def calculate(temp_files, in_temp, stdout, stderr):
'mbsrtowcs.c',
'mbstowcs.c',
'mbtowc.c',
- 'wcrtomb.c',
'wcsnrtombs.c',
'wcsrtombs.c',
'wcstombs.c',
'wctob.c',
- 'wctomb.c',
]],
['regex', [
'fnmatch.c',
@@ -213,6 +261,8 @@ def calculate(temp_files, in_temp, stdout, stderr):
'tre-mem.c',
]],
['stdio', [
+ '__string_read.c',
+ 'asprintf.c',
'fwprintf.c',
'swprintf.c',
'vfwprintf.c',
@@ -221,6 +271,10 @@ def calculate(temp_files, in_temp, stdout, stderr):
'wprintf.c',
'fputwc.c',
'fputws.c',
+ 'sscanf.c',
+ 'vasprintf.c',
+ 'vfscanf.c',
+ 'vsscanf.c',
]],
['stdlib', [
'atoll.c',
@@ -240,7 +294,6 @@ def calculate(temp_files, in_temp, stdout, stderr):
'memccpy.c',
'memmem.c',
'mempcpy.c',
- 'memchr.c',
'memrchr.c',
'rindex.c',
'stpcpy.c',
diff --git a/tools/test-js-optimizer-asm-last-output.js b/tools/test-js-optimizer-asm-last-output.js
index 1b9ac585..95afaeb7 100644
--- a/tools/test-js-optimizer-asm-last-output.js
+++ b/tools/test-js-optimizer-asm-last-output.js
@@ -30,6 +30,7 @@ function finall(x) {
a = -999999984306749400.0;
a = -999999984306749400.0;
a = -0xde0b6b000000000;
+ a = 1.1234567890123457e+21;
f(g() | 0);
return 12.0e10;
}
@@ -71,5 +72,31 @@ function looop() {
break;
}
}
+ do {
+ blah();
+ } while (!shah());
+ a = b;
+ LABELED : while (1) {
+ blah();
+ if (shah()) {
+ c = d;
+ break;
+ }
+ }
+ while (1) {
+ blah();
+ if (check) break;
+ if (shah()) {
+ e = f;
+ break;
+ }
+ }
+ do {
+ blah();
+ while (1) {
+ if (check) break;
+ }
+ } while (!shah());
+ g = h;
}
diff --git a/tools/test-js-optimizer-asm-last.js b/tools/test-js-optimizer-asm-last.js
index 1d39b1a6..6261e915 100644
--- a/tools/test-js-optimizer-asm-last.js
+++ b/tools/test-js-optimizer-asm-last.js
@@ -30,6 +30,7 @@ function finall(x) {
a = +-0xde0b6b000000000;
a = -+0xde0b6b000000000;
a = -0xde0b6b000000000;
+ a = +0x3ce7184d470dd60000;
f(g() & -1);
return +12e10;
}
@@ -86,6 +87,38 @@ function looop() {
break;
}
}
+ while (1) {
+ blah();
+ if (shah()) {
+ a = b;
+ break;
+ }
+ }
+ LABELED: while (1) {
+ blah();
+ if (shah()) {
+ c = d;
+ break;
+ }
+ }
+ while (1) {
+ blah();
+ if (check) break; // prevents optimization
+ if (shah()) {
+ e = f;
+ break;
+ }
+ }
+ while (1) {
+ blah();
+ while (1) {
+ if (check) break; // safe to optimize
+ }
+ if (shah()) {
+ g = h;
+ break;
+ }
+ }
}
// EMSCRIPTEN_GENERATED_FUNCTIONS: ["finall", "looop"]
diff --git a/tools/test-js-optimizer-asm-pre-f32.js b/tools/test-js-optimizer-asm-pre-f32.js
index 5471deeb..be515b36 100644
--- a/tools/test-js-optimizer-asm-pre-f32.js
+++ b/tools/test-js-optimizer-asm-pre-f32.js
@@ -14,4 +14,10 @@ function dupe() {
x = Math_fround(Math_fround(Math_fround(x)));
x = Math_fround(Math_fround(Math_fround(Math_fround(x))));
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["badf", "badf2", "dupe"]
+function zeros(x) {
+ x = Math_fround(x);
+ var y = Math_fround(0);
+ print(Math_fround(y) + Math_fround(0));
+ return Math_fround(0); // return needs to stay as is
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["badf", "badf2", "dupe", "zeros"]
diff --git a/tools/test-js-optimizer-asm-pre-output-f32.js b/tools/test-js-optimizer-asm-pre-output-f32.js
index 19059619..f0f2d0da 100644
--- a/tools/test-js-optimizer-asm-pre-output-f32.js
+++ b/tools/test-js-optimizer-asm-pre-output-f32.js
@@ -4,7 +4,7 @@ function badf() {
HEAP32[$gep23_asptr >> 2] = $9;
}
function badf2() {
- var $9 = Math_fround(0);
+ var $9 = f0;
$9 = Math_fround($8);
HEAPF32[$gep23_asptr >> 2] = $9;
}
@@ -14,4 +14,10 @@ function dupe() {
x = Math_fround(x);
x = Math_fround(x);
}
+function zeros(x) {
+ x = Math_fround(x);
+ var y = f0;
+ print(Math_fround(y) + f0);
+ return Math_fround(0);
+}
diff --git a/tools/test-js-optimizer-asm-pre-output.js b/tools/test-js-optimizer-asm-pre-output.js
index c9746e78..da3ebb4f 100644
--- a/tools/test-js-optimizer-asm-pre-output.js
+++ b/tools/test-js-optimizer-asm-pre-output.js
@@ -106,15 +106,11 @@ function sign_extension_simplification() {
}
}
function compare_result_simplification() {
- HEAP32[$4] = HEAP32[$5] < HEAP32[$6];
- HEAP32[$4] = HEAP32[$5] > HEAP32[$6];
- HEAP32[$4] = HEAP32[$5] <= HEAP32[$6];
- HEAP32[$4] = HEAP32[$5] <= HEAP32[$6];
- HEAP32[$4] = HEAP32[$5] == HEAP32[$6];
- HEAP32[$4] = HEAP32[$5] === HEAP32[$6];
- HEAP32[$4] = HEAP32[$5] != HEAP32[$6];
- HEAP32[$4] = HEAP32[$5] !== HEAP32[$6];
- var x = HEAP32[$5] != HEAP32[$6] | 0;
+ f((a > b & 1) + 1 | 0);
+ f(a > b | z);
+ f(a > b | c > d);
+ HEAP32[$4] = HEAP32[$5] < HEAP32[$6] & 1;
+ var x = HEAP32[$5] != HEAP32[$6] & 1;
}
function tempDoublePtr($45, $14, $28, $42) {
$45 = $45 | 0;
@@ -538,4 +534,68 @@ function fcomp() {
if (5 >= ($b | 0)) return 5;
if (5 >= 5) return 5;
}
+function conditionalizeMe() {
+ if (x > 1 ? x + y + z + w > 12 : 0) {
+ b();
+ }
+ if (a() > 1 ? x + y + z + w > 12 : 0) {
+ b();
+ }
+ if (x > 1 & x + y + z + k() > 12) {
+ b();
+ }
+ if (a() > 1 & x + y + z + k() > 12) {
+ b();
+ }
+ if (x > 1 ? 1 : x + y + z + w > 12) {
+ b();
+ }
+ if (a() > 1 ? 1 : x + y + z + w > 12) {
+ b();
+ }
+ if (x > 1 | x + y + z + k() > 12) {
+ b();
+ }
+ if (a() > 1 | x + y + z + k() > 12) {
+ b();
+ }
+ if (x > 1 ? 1 : x + y + z + w > 12) {
+ b();
+ }
+ if (a() > 1 ? 1 : x + y + z + w > 12) {
+ b();
+ }
+ if (x + y + z + k() > 12 | x > 1) {
+ b();
+ }
+ if (x + y + z + k() > 12 | a() > 1) {
+ b();
+ }
+ while (x > 1 ? x + y + z + w > 12 : 0) {
+ b();
+ }
+ while (a() > 1 ? x + y + z + w > 12 : 0) {
+ b();
+ }
+ while (x > 1 & x + y + z + k() > 12) {
+ b();
+ }
+ while (a() > 1 & x + y + z + k() > 12) {
+ b();
+ }
+ if (!($sub$i480 >= Math_fround(+0)) | !($sub4$i483 >= Math_fround(+0))) {
+ b();
+ }
+ if ($sub$i480 >= Math_fround(+0) ? !($sub4$i483 >= Math_fround(HEAPF32[x + y | 0])) : 1) {
+ b();
+ }
+ if (x > 10 | HEAP[20] + 2 > 5) {
+ b();
+ }
+ print(((HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > a % b % c % d ? 1 : $el) | $cheap > 0);
+ print(((HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > a % b % c % d ? 1 : -1) | $cheap > 0);
+ print($cheap > 0 ? 1 : (HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > a % b % c % d ? 1 : 0);
+ print(((HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > a % b % c % d ? -1 : 1) | $cheap > 0);
+ return (((((Math_imul(i6 + 1, i7) | 0) + 17 | 0) % 5 | 0) == 0 ? 1 : ((((Math_imul(i7 + 1, i7) | 0) + 11 | 0) >>> 0) % 3 | 0) == 0) | 0) == 0;
+}
diff --git a/tools/test-js-optimizer-asm-pre.js b/tools/test-js-optimizer-asm-pre.js
index 00ebd7d7..08d8c2d4 100644
--- a/tools/test-js-optimizer-asm-pre.js
+++ b/tools/test-js-optimizer-asm-pre.js
@@ -113,16 +113,11 @@ function sign_extension_simplification() {
}
}
function compare_result_simplification() {
- // Eliminate these '&1's.
+ f(((a > b)&1) + 1 | 0);
+ f(((a > b)&1) | z);
+ f(((a > b)&1) | (c > d & 1));
+ // Don't eliminate these '&1's.
HEAP32[$4] = (HEAP32[$5] < HEAP32[$6]) & 1;
- HEAP32[$4] = (HEAP32[$5] > HEAP32[$6]) & 1;
- HEAP32[$4] = (HEAP32[$5] <= HEAP32[$6]) & 1;
- HEAP32[$4] = (HEAP32[$5] <= HEAP32[$6]) & 1;
- HEAP32[$4] = (HEAP32[$5] == HEAP32[$6]) & 1;
- HEAP32[$4] = (HEAP32[$5] === HEAP32[$6]) & 1;
- HEAP32[$4] = (HEAP32[$5] != HEAP32[$6]) & 1;
- HEAP32[$4] = (HEAP32[$5] !== HEAP32[$6]) & 1;
- // Convert the &1 to |0 here, since we don't get an implicit coersion.
var x = (HEAP32[$5] != HEAP32[$6]) & 1;
}
function tempDoublePtr($45, $14, $28, $42) {
@@ -550,4 +545,68 @@ function fcomp() {
if (!(5 < ($b|0))) return 5;
if (!(5 < 5)) return 5;
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "rett", "ret2t", "retf", "i32_8", "tempDoublePtr", "boxx", "_main", "badf", "badf2", "fcomp"]
+function conditionalizeMe() {
+ if ((x > 1) & (x+y+z+w > 12)) {
+ b();
+ }
+ if ((a() > 1) & (x+y+z+w > 12)) {
+ b();
+ }
+ if ((x > 1) & (x+y+z+k() > 12)) {
+ b();
+ }
+ if ((a() > 1) & (x+y+z+k() > 12)) {
+ b();
+ }
+ if ((x > 1) | (x+y+z+w > 12)) {
+ b();
+ }
+ if ((a() > 1) | (x+y+z+w > 12)) {
+ b();
+ }
+ if ((x > 1) | (x+y+z+k() > 12)) {
+ b();
+ }
+ if ((a() > 1) | (x+y+z+k() > 12)) {
+ b();
+ }
+ if ((x+y+z+w > 12) | (x > 1)) {
+ b();
+ }
+ if ((x+y+z+w > 12) | (a() > 1)) {
+ b();
+ }
+ if ((x+y+z+k() > 12) | (x > 1)) {
+ b();
+ }
+ if ((x+y+z+k() > 12) | (a() > 1)) {
+ b();
+ }
+ while ((x > 1) & (x+y+z+w > 12)) {
+ b();
+ }
+ while ((a() > 1) & (x+y+z+w > 12)) {
+ b();
+ }
+ while ((x > 1) & (x+y+z+k() > 12)) {
+ b();
+ }
+ while ((a() > 1) & (x+y+z+k() > 12)) {
+ b();
+ }
+ if (!($sub$i480 >= Math_fround(+0)) | !($sub4$i483 >= Math_fround(+0))) {
+ b();
+ }
+ if (!($sub$i480 >= Math_fround(+0)) | !($sub4$i483 >= Math_fround(HEAPF32[x+y|0]))) {
+ b();
+ }
+ if (x > 10 | (HEAP[20] + 2) > 5) {
+ b();
+ }
+ print( (((HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > (a % b % c % d)) ? 1 : $el) | ($cheap > 0) ); // conditional does not always emit boolean
+ print( (((HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > (a % b % c % d)) ? 1 : -1) | ($cheap > 0) );
+ print( (((HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > (a % b % c % d)) ? 1 : 0) | ($cheap > 0) ); // this one is safe!
+ print( (((HEAP8[a] + HEAP8[b] + HEAP8[c] + HEAP8[d] + HEAP8[e] + HEAP8[f] | 0) > (a % b % c % d)) ? -1 : 1) | ($cheap > 0) );
+ return ((((Math_imul(i6+1, i7) | 0) + 17 | 0) % 5 | 0 | 0) == 0 | ((((Math_imul(i7+1, i7) | 0) + 11 | 0) >>> 0) % 3 | 0 | 0) == 0 | 0) == 0;
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "rett", "ret2t", "retf", "i32_8", "tempDoublePtr", "boxx", "_main", "badf", "badf2", "fcomp", "conditionalizeMe"]
diff --git a/tools/test-js-optimizer-asm-regs-harder-output.js b/tools/test-js-optimizer-asm-regs-harder-output.js
index e1df42cb..c3b326f6 100644
--- a/tools/test-js-optimizer-asm-regs-harder-output.js
+++ b/tools/test-js-optimizer-asm-regs-harder-output.js
@@ -129,4 +129,9 @@ function linkedVars() {
}
return i2 + i1;
}
+function deadCondExpr(i2) {
+ i2 = i2 | 0;
+ var i1 = 0;
+ return i1 | 0;
+}
diff --git a/tools/test-js-optimizer-asm-regs-harder.js b/tools/test-js-optimizer-asm-regs-harder.js
index 0231a215..fa72aab8 100644
--- a/tools/test-js-optimizer-asm-regs-harder.js
+++ b/tools/test-js-optimizer-asm-regs-harder.js
@@ -149,5 +149,11 @@ function linkedVars() {
}
return outer1 + outer2;
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "_doit", "stackRestore", "switchey", "switchey2", "iffey", "labelledJump", "linkedVars']
+function deadCondExpr(input) {
+ input = input|0;
+ var dead = 0, temp = 0;
+ dead = (!input ? -1 : input)|0;
+ return temp|0;
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "_doit", "stackRestore", "switchey", "switchey2", "iffey", "labelledJump", "linkedVars", "deadCondExpr"]
diff --git a/tools/webidl_binder.py b/tools/webidl_binder.py
new file mode 100644
index 00000000..168460fe
--- /dev/null
+++ b/tools/webidl_binder.py
@@ -0,0 +1,433 @@
+
+'''
+WebIDL binder
+
+https://github.com/kripken/emscripten/wiki/WebIDL-Binder
+'''
+
+import os, sys
+
+import shared
+
+sys.path.append(shared.path_from_root('third_party'))
+sys.path.append(shared.path_from_root('third_party', 'ply'))
+
+import WebIDL
+
+class Dummy:
+ def __init__(self, init):
+ for k, v in init.iteritems():
+ self.__dict__[k] = v
+
+ def getExtendedAttribute(self, name):
+ return None
+
+input_file = sys.argv[1]
+output_base = sys.argv[2]
+
+shared.try_delete(output_base + '.cpp')
+shared.try_delete(output_base + '.js')
+
+p = WebIDL.Parser()
+p.parse(open(input_file).read())
+data = p.finish()
+
+interfaces = {}
+implements = {}
+
+for thing in data:
+ if isinstance(thing, WebIDL.IDLInterface):
+ interfaces[thing.identifier.name] = thing
+ elif isinstance(thing, WebIDL.IDLImplementsStatement):
+ implements.setdefault(thing.implementor.identifier.name, []).append(thing.implementee.identifier.name)
+
+#print interfaces
+#print implements
+
+pre_c = []
+mid_c = []
+mid_js = []
+
+pre_c += [r'''
+#include <emscripten.h>
+''']
+
+mid_c += [r'''
+extern "C" {
+''']
+
+def emit_constructor(name):
+ global mid_js
+ mid_js += [r'''%s.prototype = %s;
+%s.prototype.constructor = %s;
+%s.prototype.__class__ = %s;
+%s.__cache__ = {};
+Module['%s'] = %s;
+''' % (name, 'Object.create(%s.prototype)' % (implements[name][0] if implements.get(name) else 'WrapperObject'), name, name, name, name, name, name, name)]
+
+
+mid_js += ['''
+// Bindings utilities
+
+function WrapperObject() {
+}
+''']
+
+emit_constructor('WrapperObject')
+
+mid_js += ['''
+function getCache(__class__) {
+ return (__class__ || WrapperObject).__cache__;
+}
+Module['getCache'] = getCache;
+
+function wrapPointer(ptr, __class__) {
+ var cache = getCache(__class__);
+ var ret = cache[ptr];
+ if (ret) return ret;
+ ret = Object.create((__class__ || WrapperObject).prototype);
+ ret.ptr = ptr;
+ return cache[ptr] = ret;
+}
+Module['wrapPointer'] = wrapPointer;
+
+function castObject(obj, __class__) {
+ return wrapPointer(obj.ptr, __class__);
+}
+Module['castObject'] = castObject;
+
+Module['NULL'] = wrapPointer(0);
+
+function destroy(obj) {
+ if (!obj['__destroy__']) throw 'Error: Cannot destroy object. (Did you create it yourself?)';
+ obj['__destroy__']();
+ // Remove from cache, so the object can be GC'd and refs added onto it released
+ delete getCache(obj.__class__)[obj.ptr];
+}
+Module['destroy'] = destroy;
+
+function compare(obj1, obj2) {
+ return obj1.ptr === obj2.ptr;
+}
+Module['compare'] = compare;
+
+function getPointer(obj) {
+ return obj.ptr;
+}
+Module['getPointer'] = getPointer;
+
+function getClass(obj) {
+ return obj.__class__;
+}
+Module['getClass'] = getClass;
+
+// Converts a value into a C-style string.
+function ensureString(value) {
+ if (typeof value == 'string') return allocate(intArrayFromString(value), 'i8', ALLOC_STACK);
+ return value;
+}
+
+''']
+
+C_FLOATS = ['float', 'double']
+
+def type_to_c(t, non_pointing=False):
+ #print 'to c ', t
+ t = t.replace(' (Wrapper)', '')
+ if t == 'Long':
+ return 'int'
+ elif t == 'Short':
+ return 'short'
+ elif t == 'Void':
+ return 'void'
+ elif t == 'String':
+ return 'char*'
+ elif t == 'Float':
+ return 'float'
+ elif t == 'Double':
+ return 'double'
+ elif t == 'Boolean':
+ return 'bool'
+ elif t in interfaces:
+ return (interfaces[t].getExtendedAttribute('Prefix') or [''])[0] + t + ('' if non_pointing else '*')
+ else:
+ return t
+
+def take_addr_if_nonpointer(m):
+ if m.getExtendedAttribute('Ref') or m.getExtendedAttribute('Value'):
+ return '&'
+ return ''
+
+def deref_if_nonpointer(m):
+ if m.getExtendedAttribute('Ref') or m.getExtendedAttribute('Value'):
+ return '*'
+ return ''
+
+def type_to_cdec(raw):
+ name = ret = type_to_c(raw.type.name, non_pointing=True)
+ if raw.getExtendedAttribute('Const'): ret = 'const ' + ret
+ if name not in interfaces: return ret
+ if raw.getExtendedAttribute('Ref'):
+ return ret + '&'
+ if raw.getExtendedAttribute('Value'):
+ return ret
+ return ret + '*'
+
+def render_function(class_name, func_name, sigs, return_type, non_pointer, copy, operator, constructor, func_scope, call_content=None, const=False):
+ global mid_c, mid_js, js_impl_methods
+
+ #print 'renderfunc', class_name, func_name, sigs, return_type, constructor
+
+ bindings_name = class_name + '_' + func_name
+ min_args = min(sigs.keys())
+ max_args = max(sigs.keys())
+
+ c_names = {}
+
+ # JS
+
+ cache = ('getCache(%s)[this.ptr] = this;' % class_name) if constructor else ''
+ call_prefix = '' if not constructor else 'this.ptr = '
+ call_postfix = ''
+ if return_type != 'Void' and not constructor: call_prefix = 'return '
+ if not constructor:
+ if return_type in interfaces:
+ call_prefix += 'wrapPointer('
+ call_postfix += ', ' + return_type + ')'
+
+ args = ['arg%d' % i for i in range(max_args)]
+ if not constructor:
+ body = ' var self = this.ptr;\n'
+ pre_arg = ['self']
+ else:
+ body = ''
+ pre_arg = []
+
+ for i in range(max_args):
+ # note: null has typeof object, but is ok to leave as is, since we are calling into asm code where null|0 = 0
+ body += " if (arg%d && typeof arg%d === 'object') arg%d = arg%d.ptr;\n" % (i, i, i, i)
+ body += " else arg%d = ensureString(arg%d);\n" % (i, i)
+
+ for i in range(min_args, max_args):
+ c_names[i] = 'emscripten_bind_%s_%d' % (bindings_name, i)
+ body += ' if (arg%d === undefined) { %s%s(%s)%s%s }\n' % (i, call_prefix, '_' + c_names[i], ', '.join(pre_arg + args[:i]), call_postfix, '' if 'return ' in call_prefix else '; ' + (cache or ' ') + 'return')
+ c_names[max_args] = 'emscripten_bind_%s_%d' % (bindings_name, max_args)
+ body += ' %s%s(%s)%s;\n' % (call_prefix, '_' + c_names[max_args], ', '.join(pre_arg + args), call_postfix)
+ if cache:
+ body += ' ' + cache + '\n'
+ mid_js += [r'''function%s(%s) {
+%s
+}''' % ((' ' + func_name) if constructor else '', ', '.join(args), body[:-1])]
+
+ # C
+
+ for i in range(min_args, max_args+1):
+ raw = sigs.get(i)
+ if raw is None: continue
+ sig = [arg.type.name for arg in raw]
+
+ c_arg_types = map(type_to_c, sig)
+
+ normal_args = ', '.join(['%s arg%d' % (c_arg_types[j], j) for j in range(i)])
+ if constructor:
+ full_args = normal_args
+ else:
+ full_args = type_to_c(class_name, non_pointing=True) + '* self' + ('' if not normal_args else ', ' + normal_args)
+ call_args = ', '.join(['%sarg%d' % ('*' if raw[j].getExtendedAttribute('Ref') else '', j) for j in range(i)])
+ if constructor:
+ call = 'new ' + type_to_c(class_name, non_pointing=True)
+ call += '(' + call_args + ')'
+ elif call_content is not None:
+ call = call_content
+ else:
+ call = 'self->' + func_name
+ call += '(' + call_args + ')'
+
+ if operator:
+ assert '=' in operator, 'can only do += *= etc. for now, all with "="'
+ cast_self = 'self'
+ if class_name != func_scope:
+ # this function comes from an ancestor class; for operators, we must cast it
+ cast_self = 'dynamic_cast<' + type_to_c(func_scope) + '>(' + cast_self + ')'
+ call = '(*%s %s %sarg0)' % (cast_self, operator, '*' if sig[0] in interfaces else '')
+
+ pre = ''
+
+ basic_return = 'return ' if constructor or return_type is not 'Void' else ''
+ return_prefix = basic_return
+ return_postfix = ''
+ if non_pointer:
+ return_prefix += '&';
+ if copy:
+ pre += ' static %s temp;\n' % type_to_c(return_type, non_pointing=True)
+ return_prefix += '(temp = '
+ return_postfix += ', &temp)'
+
+ c_return_type = type_to_c(return_type)
+ mid_c += [r'''
+%s%s EMSCRIPTEN_KEEPALIVE %s(%s) {
+%s %s%s%s;
+}
+''' % ('const ' if const else '', type_to_c(class_name) if constructor else c_return_type, c_names[i], full_args, pre, return_prefix, call, return_postfix)]
+
+ if not constructor:
+ if i == max_args:
+ dec_args = ', '.join(map(lambda j: type_to_cdec(raw[j]) + ' arg' + str(j), range(i)))
+ js_call_args = ', '.join(['%sarg%d' % (('(int)' if sig[j] in interfaces else '') + ('&' if raw[j].getExtendedAttribute('Ref') or raw[j].getExtendedAttribute('Value') else ''), j) for j in range(i)])
+
+ js_impl_methods += [r''' %s %s(%s) {
+ %sEM_ASM_%s({
+ var self = Module['getCache'](Module['%s'])[$0];
+ if (!self.hasOwnProperty('%s')) throw 'a JSImplementation must implement all functions, you forgot %s::%s.';
+ %sself.%s(%s)%s;
+ }, (int)this%s);
+ }''' % (c_return_type, func_name, dec_args,
+ basic_return, 'INT' if c_return_type not in C_FLOATS else 'DOUBLE',
+ class_name,
+ func_name, class_name, func_name,
+ return_prefix,
+ func_name,
+ ','.join(['$%d' % i for i in range(1, max_args)]),
+ return_postfix,
+ (', ' if js_call_args else '') + js_call_args)]
+
+
+for name, interface in interfaces.iteritems():
+ js_impl = interface.getExtendedAttribute('JSImplementation')
+ if not js_impl: continue
+ implements[name] = [js_impl[0]]
+
+names = interfaces.keys()
+names.sort(lambda x, y: 1 if implements.get(x) and implements[x][0] == y else (-1 if implements.get(y) and implements[y][0] == x else 0))
+
+for name in names:
+ interface = interfaces[name]
+
+ mid_js += ['\n// ' + name + '\n']
+ mid_c += ['\n// ' + name + '\n']
+
+ global js_impl_methods
+ js_impl_methods = []
+
+ cons = interface.getExtendedAttribute('Constructor')
+ if type(cons) == list: raise Exception('do not use "Constructor", instead create methods with the name of the interface')
+
+ js_impl = interface.getExtendedAttribute('JSImplementation')
+ if js_impl:
+ js_impl = js_impl[0]
+
+ # Methods
+
+ seen_constructor = False # ensure a constructor, even for abstract base classes
+ for m in interface.members:
+ if m.identifier.name == name:
+ seen_constructor = True
+ break
+ if not seen_constructor:
+ mid_js += ['function %s() { throw "cannot construct a %s, no constructor in IDL" }\n' % (name, name)]
+ emit_constructor(name)
+
+ for m in interface.members:
+ if not m.isMethod(): continue
+ constructor = m.identifier.name == name
+ if not constructor:
+ parent_constructor = False
+ temp = m.parentScope
+ while temp.parentScope:
+ if temp.identifier.name == m.identifier.name:
+ parent_constructor = True
+ temp = temp.parentScope
+ if parent_constructor:
+ continue
+ if not constructor:
+ mid_js += [r'''
+%s.prototype.%s = ''' % (name, m.identifier.name)]
+ sigs = {}
+ return_type = None
+ for ret, args in m.signatures():
+ if return_type is None:
+ return_type = ret.name
+ else:
+ assert return_type == ret.name, 'overloads must have the same return type'
+ for i in range(len(args)+1):
+ if i == len(args) or args[i].optional:
+ assert i not in sigs, 'overloading must differentiate by # of arguments (cannot have two signatures that differ by types but not by length)'
+ sigs[i] = args[:i]
+ render_function(name,
+ m.identifier.name, sigs, return_type,
+ m.getExtendedAttribute('Ref'),
+ m.getExtendedAttribute('Value'),
+ (m.getExtendedAttribute('Operator') or [None])[0],
+ constructor,
+ func_scope=m.parentScope.identifier.name,
+ const=m.getExtendedAttribute('Const'))
+ mid_js += [';\n']
+ if constructor:
+ emit_constructor(name)
+
+ for m in interface.members:
+ if not m.isAttr(): continue
+ attr = m.identifier.name
+
+ get_name = 'get_' + attr
+ mid_js += [r'''
+ %s.prototype.%s= ''' % (name, get_name)]
+ render_function(name,
+ get_name, { 0: [] }, m.type.name,
+ None,
+ None,
+ None,
+ False,
+ func_scope=interface,
+ call_content=take_addr_if_nonpointer(m) + 'self->' + attr,
+ const=m.getExtendedAttribute('Const'))
+
+ set_name = 'set_' + attr
+ mid_js += [r'''
+ %s.prototype.%s= ''' % (name, set_name)]
+ render_function(name,
+ set_name, { 1: [Dummy({ 'type': m.type })] }, 'Void',
+ None,
+ None,
+ None,
+ False,
+ func_scope=interface,
+ call_content='self->' + attr + ' = ' + deref_if_nonpointer(m) + 'arg0',
+ const=m.getExtendedAttribute('Const'))
+
+ if not interface.getExtendedAttribute('NoDelete'):
+ mid_js += [r'''
+ %s.prototype.__destroy__ = ''' % name]
+ render_function(name,
+ '__destroy__', { 0: [] }, 'Void',
+ None,
+ None,
+ None,
+ False,
+ func_scope=interface,
+ call_content='delete self')
+
+ # Emit C++ class implementation that calls into JS implementation
+
+ if js_impl:
+ pre_c += [r'''
+class %s : public %s {
+public:
+%s
+};
+''' % (name, type_to_c(js_impl, non_pointing=True), '\n'.join(js_impl_methods))]
+
+mid_c += ['\n}\n\n']
+mid_js += ['\n']
+
+# Write
+
+c = open(output_base + '.cpp', 'w')
+for x in pre_c: c.write(x)
+for x in mid_c: c.write(x)
+c.close()
+
+js = open(output_base + '.js', 'w')
+for x in mid_js: js.write(x)
+js.close()
+