summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--cmake/Platform/Emscripten.cmake41
-rwxr-xr-xemcc153
-rwxr-xr-xemrun26
-rw-r--r--src/analyzer.js12
-rw-r--r--src/compiler.js2
-rw-r--r--src/jsifier.js16
-rw-r--r--src/library.js3
-rw-r--r--src/library_gl.js76
-rw-r--r--src/library_sdl.js35
-rw-r--r--src/parseTools.js35
-rw-r--r--src/preamble.js15
-rw-r--r--src/relooper/Relooper.cpp50
-rw-r--r--src/relooper/Relooper.h34
-rw-r--r--src/relooper/fuzzer.py6
-rw-r--r--src/relooper/test.cpp28
-rw-r--r--src/relooper/test.txt377
-rw-r--r--src/relooper/test2.txt40
-rw-r--r--src/relooper/test3.txt82
-rw-r--r--src/relooper/test4.txt52
-rw-r--r--src/relooper/test5.txt104
-rw-r--r--src/relooper/test6.txt38
-rw-r--r--src/relooper/test_dead.txt2
-rw-r--r--src/relooper/test_debug.txt62
-rw-r--r--src/relooper/test_fuzz1.txt100
-rw-r--r--src/relooper/test_fuzz2.txt42
-rw-r--r--src/relooper/test_fuzz3.txt36
-rw-r--r--src/relooper/test_fuzz4.txt56
-rw-r--r--src/relooper/test_fuzz5.txt122
-rw-r--r--src/relooper/test_fuzz6.txt358
-rw-r--r--src/relooper/test_inf.txt1606
-rwxr-xr-xsrc/relooper/testit.sh30
-rw-r--r--src/runtime.js2
-rw-r--r--tests/aniso.c5
-rw-r--r--tests/cases/longjmp_tiny_invoke_phi.ll46
-rw-r--r--tests/cases/longjmp_tiny_invoke_phi.txt4
-rw-r--r--tests/core/closebitcasts.c32
-rw-r--r--tests/core/closebitcasts.txt2
-rw-r--r--tests/cubegeom.c12
-rwxr-xr-xtests/fuzz/test.sh52
-rwxr-xr-xtests/runner.py1
-rw-r--r--tests/sdl_canvas.c2
-rw-r--r--tests/test_benchmark.py6
-rw-r--r--tests/test_browser.py21
-rw-r--r--tests/test_core.py13
-rw-r--r--tests/test_other.py127
-rw-r--r--tests/test_sanity.py28
-rw-r--r--tools/eliminator/asm-eliminator-test-output.js10
-rw-r--r--tools/eliminator/asm-eliminator-test.js10
-rw-r--r--tools/eliminator/eliminator-test-output.js11
-rw-r--r--tools/eliminator/eliminator-test.js17
-rw-r--r--tools/js-optimizer.js34
-rw-r--r--tools/shared.py34
53 files changed, 2329 insertions, 1780 deletions
diff --git a/AUTHORS b/AUTHORS
index d71eea47..6cf860ab 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -113,3 +113,4 @@ a license to everyone to use it as detailed in LICENSE.)
* Heidi Pan <heidi.pan@intel.com> (copyright owned by Intel)
* Vasilis Kalintiris <ehostunreach@gmail.com>
* Adam C. Clifton <adam@hulkamaniac.com>
+* Volo Zyko <volo.zyko@gmail.com>
diff --git a/cmake/Platform/Emscripten.cmake b/cmake/Platform/Emscripten.cmake
index c30632ca..4f434d14 100644
--- a/cmake/Platform/Emscripten.cmake
+++ b/cmake/Platform/Emscripten.cmake
@@ -109,6 +109,8 @@ 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 a global EMSCRIPTEN variable that can be used in client CMakeLists.txt to detect when building using Emscripten.
# There seems to be some kind of bug with CMake, so you might need to define this manually on the command line with "-DEMSCRIPTEN=1".
@@ -122,22 +124,22 @@ SET(APPLE)
set(CMAKE_C_SIZEOF_DATA_PTR 4)
set(CMAKE_CXX_SIZEOF_DATA_PTR 4)
-set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_RELEASE")
-set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_MINSIZEREL")
-set(CMAKE_C_FLAGS_RELWITHDEBINFO "" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_RELWITHDEBINFO")
-set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_CXX_FLAGS_RELEASE")
-set(CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG" CACHE STRING "Emscripten-overridden CMAKE_CXX_FLAGS_MINSIZEREL")
-set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "" CACHE STRING "Emscripten-overridden CMAKE_CXX_FLAGS_RELWITHDEBINFO")
+set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O2" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_RELEASE")
+set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG -O2" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_MINSIZEREL")
+set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2" CACHE STRING "Emscripten-overridden CMAKE_C_FLAGS_RELWITHDEBINFO")
+set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O2" CACHE STRING "Emscripten-overridden CMAKE_CXX_FLAGS_RELEASE")
+set(CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG -O2" CACHE STRING "Emscripten-overridden CMAKE_CXX_FLAGS_MINSIZEREL")
+set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2" CACHE STRING "Emscripten-overridden CMAKE_CXX_FLAGS_RELWITHDEBINFO")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-O2" CACHE STRING "Emscripten-overridden CMAKE_EXE_LINKER_FLAGS_RELEASE")
set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-O2" CACHE STRING "Emscripten-overridden CMAKE_EXE_LINKER_FLAGS_MINSIZEREL")
-set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "-O2" CACHE STRING "Emscripten-overridden CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO")
+set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "-O2 -g" CACHE STRING "Emscripten-overridden CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "-O2" CACHE STRING "Emscripten-overridden CMAKE_SHARED_LINKER_FLAGS_RELEASE")
set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "-O2" CACHE STRING "Emscripten-overridden CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL")
-set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "-O2" CACHE STRING "Emscripten-overridden CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO")
+set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "-O2 -g" CACHE STRING "Emscripten-overridden CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "-O2" CACHE STRING "Emscripten-overridden CMAKE_MODULE_LINKER_FLAGS_RELEASE")
set(CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL "-O2" CACHE STRING "Emscripten-overridden CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL")
-set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "-O2" CACHE STRING "Emscripten-overridden CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO")
+set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "-O2 -g" CACHE STRING "Emscripten-overridden CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO")
function(em_validate_asmjs_after_build target)
add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo Validating build output for asm.js... COMMAND "python" ARGS "${EMSCRIPTEN_ROOT_PATH}/tools/validate_asmjs.py" "$<TARGET_FILE:${target}>")
@@ -203,3 +205,24 @@ endfunction()
function(em_link_post_js target)
em_add_tracked_link_flag(${target} "--post-js" ${ARGN})
endfunction()
+
+# Experimental support for targeting generation of Visual Studio project files (vs-tool) of Emscripten projects for Windows.
+# To use this, pass the combination -G "Visual Studio 10" -DCMAKE_TOOLCHAIN_FILE=Emscripten.cmake
+if ("${CMAKE_GENERATOR}" MATCHES "^Visual Studio.*")
+ # By default, CMake generates VS project files with a <GenerateManifest>true</GenerateManifest> directive.
+ # This causes VS to attempt to invoke rc.exe during the build, which will fail since app manifests are meaningless for Emscripten.
+ # To disable this, add the following linker flag. This flag will not go to emcc, since the Visual Studio CMake generator will swallow it.
+ set(EMSCRIPTEN_VS_LINKER_FLAGS "/MANIFEST:NO")
+ # CMake is hardcoded to write a ClCompile directive <ObjectFileName>$(IntDir)</ObjectFileName> in all VS project files it generates.
+ # This makes VS pass emcc a -o param that points to a directory instead of a file, which causes emcc autogenerate the output filename.
+ # CMake is hardcoded to assume all object files have the suffix .obj, so adjust the emcc-autogenerated default suffix name to match.
+ set(EMSCRIPTEN_VS_LINKER_FLAGS "${EMSCRIPTEN_VS_LINKER_FLAGS} --default-obj-ext .obj")
+ # Also hint CMake that it should not hardcode <ObjectFileName> generation. Requires a custom CMake build for this to work (ignored on others)
+ # See http://www.cmake.org/Bug/view.php?id=14673 and https://github.com/juj/CMake
+ set(CMAKE_VS_NO_DEFAULT_OBJECTFILENAME 1)
+
+ # Apply and cache Emscripten Visual Studio IDE-specific linker flags.
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EMSCRIPTEN_VS_LINKER_FLAGS}" CACHE STRING "")
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${EMSCRIPTEN_VS_LINKER_FLAGS}" CACHE STRING "")
+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${EMSCRIPTEN_VS_LINKER_FLAGS}" CACHE STRING "")
+endif()
diff --git a/emcc b/emcc
index 726838af..621cb340 100755
--- a/emcc
+++ b/emcc
@@ -53,14 +53,17 @@ from tools import shared, jsrun
from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename, WINDOWS
from tools.response_file import read_response_file
-C_SUFFIXES = ('.c', '.C')
-CXX_SUFFIXES = ('.cpp', '.cxx', '.cc', '.CPP', '.CXX', '.CC')
-SOURCE_SUFFIXES = C_SUFFIXES + CXX_SUFFIXES + ('.m', '.mm')
-BITCODE_SUFFIXES = ('.bc', '.o', '.obj')
-DYNAMICLIB_SUFFIXES = ('.dylib', '.so', '.dll')
-STATICLIB_SUFFIXES = ('.a',)
-ASSEMBLY_SUFFIXES = ('.ll',)
+# endings = dot + a suffix, safe to test by filename.endswith(endings)
+C_ENDINGS = ('.c', '.C')
+CXX_ENDINGS = ('.cpp', '.cxx', '.cc', '.CPP', '.CXX', '.CC')
+SOURCE_ENDINGS = C_ENDINGS + CXX_ENDINGS + ('.m', '.mm')
+BITCODE_ENDINGS = ('.bc', '.o', '.obj')
+DYNAMICLIB_ENDINGS = ('.dylib', '.so', '.dll')
+STATICLIB_ENDINGS = ('.a',)
+ASSEMBLY_ENDINGS = ('.ll',)
+
LIB_PREFIXES = ('', 'lib')
+
JS_CONTAINING_SUFFIXES = ('js', 'html')
# Mapping of emcc opt levels to llvm opt levels. We use llvm opt level 3 in emcc opt
@@ -345,7 +348,9 @@ Options that are modified or new in %s include:
--embed-file and --preload-file
wildcard is supported
- --compression <codec> Compress both the compiled code and embedded/
+ --compression <codec> **THIS OPTION IS DEPRECATED**
+
+ Compress both the compiled code and embedded/
preloaded files. <codec> should be a triple,
<native_encoder>,<js_decoder>,<js_name>
@@ -514,6 +519,13 @@ Options that are modified or new in %s include:
file, and if that is not set, the default location
~/.emscripten is assumed.
+ --default-obj-ext .ext Specifies the file suffix to generate if the location
+ of a directory name is passed to -o directive, e.g.
+ emcc -c a.c -o dir/
+ will by default generate an output name 'dir/a.o',
+ but this cmdline param can be passed to generate a
+ file with a custom suffix 'dir/a.ext'.
+
The target file, if specified (-o <target>), defines what will
be generated:
@@ -762,9 +774,13 @@ def in_temp(name):
def filename_type_suffix(filename):
for i in reversed(filename.split('.')[1:]):
if not i.isdigit():
- return '.' + i
+ return i
return ''
+def filename_type_ending(filename):
+ suffix = filename_type_suffix(filename)
+ return '' if not suffix else ('.' + suffix)
+
try:
call = CXX if use_cxx else CC
@@ -797,6 +813,7 @@ try:
use_preload_cache = False
no_heap_copy = False
proxy_to_worker = False
+ default_object_extension = '.o'
if use_cxx:
default_cxx_std = '-std=c++03' # Enforce a consistent C++ standard when compiling .cpp files, if user does not specify one on the cmdline.
@@ -907,6 +924,7 @@ try:
newargs[i] = ''
newargs[i+1] = ''
elif newargs[i].startswith('--compression'):
+ logging.warning('--compression is deprecated. Instead, it is recommended you use native gzip compression in your webserver')
check_bad_eq(newargs[i])
parts = newargs[i+1].split(',')
assert len(parts) == 3, '--compression requires specifying native_encoder,js_decoder,js_name - see emcc --help. got: %s' % newargs[i+1]
@@ -992,6 +1010,12 @@ try:
# This option is parsed in tools/shared.py, here only clean it up from being passed to clang.
newargs[i] = ''
newargs[i+1] = ''
+ elif newargs[i] == '--default-obj-ext':
+ newargs[i] = ''
+ default_object_extension = newargs[i+1]
+ if not default_object_extension.startswith('.'):
+ default_object_extension = '.' + default_object_extension
+ newargs[i+1] = ''
newargs = [ arg for arg in newargs if arg is not '' ]
@@ -1053,23 +1077,23 @@ try:
prev = newargs[i-1]
if prev in ['-MT', '-MF', '-MQ', '-D', '-U', '-o', '-x', '-Xpreprocessor', '-include', '-imacros', '-idirafter', '-iprefix', '-iwithprefix', '-iwithprefixbefore', '-isysroot', '-imultilib', '-A', '-isystem', '-iquote', '-install_name', '-compatibility_version', '-current_version', '-I', '-L']: continue # ignore this gcc-style argument
- if (os.path.islink(arg) and os.path.realpath(arg).endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + ASSEMBLY_SUFFIXES)):
+ if (os.path.islink(arg) and os.path.realpath(arg).endswith(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + ASSEMBLY_ENDINGS)):
arg = os.path.realpath(arg)
if not arg.startswith('-'):
if not os.path.exists(arg):
- logging.error(arg + ': No such file or directory')
+ logging.error('%s: No such file or directory ("%s" was expected to be an input file, based on the commandline arguments provided)' % (arg, arg))
exit(1)
- arg_suffix = filename_type_suffix(arg)
- if arg_suffix.endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + ASSEMBLY_SUFFIXES) or shared.Building.is_ar(arg): # we already removed -o <target>, so all these should be inputs
+ arg_ending = filename_type_ending(arg)
+ if arg_ending.endswith(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + ASSEMBLY_ENDINGS) or shared.Building.is_ar(arg): # we already removed -o <target>, so all these should be inputs
newargs[i] = ''
- if arg_suffix.endswith(SOURCE_SUFFIXES):
+ if arg_ending.endswith(SOURCE_ENDINGS):
input_files.append(arg)
has_source_inputs = True
- elif arg_suffix.endswith(ASSEMBLY_SUFFIXES) or shared.Building.is_bitcode(arg): # this should be bitcode, make sure it is valid
+ 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)
- elif arg_suffix.endswith(STATICLIB_SUFFIXES + DYNAMICLIB_SUFFIXES):
+ 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)
for prefix in LIB_PREFIXES:
@@ -1081,10 +1105,10 @@ try:
newargs[i] = ''
else:
logging.warning(arg + ' is not valid LLVM bitcode')
- elif arg_suffix.endswith(STATICLIB_SUFFIXES):
+ elif arg_ending.endswith(STATICLIB_ENDINGS):
if not shared.Building.is_ar(arg):
if shared.Building.is_bitcode(arg):
- logging.error(arg + ': File has a suffix of a static library ' + str(STATICLIB_SUFFIXES) + ', but instead is an LLVM bitcode file! When linking LLVM bitcode files, use one of the suffixes ' + str(BITCODE_SUFFIXES))
+ logging.error(arg + ': File has a suffix of a static library ' + str(STATICLIB_ENDINGS) + ', but instead is an LLVM bitcode file! When linking LLVM bitcode files, use one of the suffixes ' + str(BITCODE_ENDINGS))
else:
logging.error(arg + ': Unknown format, not a static library!')
exit(1)
@@ -1109,17 +1133,12 @@ try:
target = target_basename + '.o'
final_suffix = 'o'
- # do not link in libs when just generating object code (not an 'executable', i.e. JS, or a library)
- if ('.' + final_suffix) in BITCODE_SUFFIXES and len(libs) > 0:
- logging.warning('not linking against libraries since only compiling to bitcode')
- libs = []
-
# Find library files
for lib in libs:
logging.debug('looking for library "%s"' % lib)
found = False
for prefix in LIB_PREFIXES:
- for suff in STATICLIB_SUFFIXES + DYNAMICLIB_SUFFIXES:
+ for suff in STATICLIB_ENDINGS + DYNAMICLIB_ENDINGS:
name = prefix + lib + suff
for lib_dir in lib_dirs:
path = os.path.join(lib_dir, name)
@@ -1130,12 +1149,21 @@ try:
break
if found: break
if found: break
-
- if ignore_dynamic_linking:
- input_files = filter(lambda input_file: not input_file.endswith(DYNAMICLIB_SUFFIXES), input_files)
+ if not found: logging.warning('emcc: cannot find library "%s"' % lib)
+
+ # If not compiling to JS, then we are compiling to an intermediate bitcode objects or library, so
+ # ignore dynamic linking, since multiple dynamic linkings can interfere with each other
+ if not filename_type_suffix(target) in JS_CONTAINING_SUFFIXES or ignore_dynamic_linking:
+ def check(input_file):
+ if filename_type_ending(input_file) in DYNAMICLIB_ENDINGS:
+ if not ignore_dynamic_linking: logging.warning('ignoring dynamic library %s because not compiling to JS or HTML, remember to link it when compiling to JS or HTML at the end' % os.path.basename(input_file))
+ return False
+ else:
+ return True
+ input_files = filter(lambda input_file: check(input_file), input_files)
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_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + STATICLIB_SUFFIXES + ASSEMBLY_SUFFIXES))
+ 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))
exit(0)
newargs = CC_ADDITIONAL_ARGS + newargs
@@ -1162,7 +1190,9 @@ try:
logging.warning('disabling asm.js since embind is not ready for it yet')
shared.Settings.ASM_JS = 0
- if os.environ.get('EMCC_FAST_COMPILER'):
+ fastcomp = os.environ.get('EMCC_FAST_COMPILER') == '1'
+
+ if fastcomp:
shared.Settings.ASM_JS = 1
if shared.Settings.DISABLE_EXCEPTION_CATCHING == 0:
logging.warning('disabling exception catching since not supported in fastcomp yet')
@@ -1181,9 +1211,12 @@ try:
assert shared.Settings.PGO == 0, 'pgo not supported in fastcomp'
assert shared.Settings.TARGET_LE32 == 1, 'fastcomp requires le32'
assert not bind, 'embind not supported in fastcomp yet'
+ if jcache:
+ logging.warning('jcache is not supported in fastcomp (you should not need it anyhow), disabling')
+ jcache = False
if shared.Settings.ASM_JS:
- assert opt_level >= 1 or os.environ.get('EMCC_FAST_COMPILER'), 'asm.js requires -O1 or above'
+ assert opt_level >= 1 or fastcomp, 'asm.js requires -O1 or above'
if bind:
shared.Settings.RESERVED_FUNCTION_POINTERS = max(shared.Settings.RESERVED_FUNCTION_POINTERS, 10)
@@ -1195,16 +1228,6 @@ try:
shared.Settings.CORRECT_OVERFLOWS = 1
assert not shared.Settings.PGO, 'cannot run PGO in ASM_JS mode'
- heap = 4096
- while heap < shared.Settings.TOTAL_MEMORY:
- if heap < 16*1024*1024:
- heap *= 2
- else:
- heap += 16*1024*1024
- if heap != shared.Settings.TOTAL_MEMORY:
- logging.warning('increasing TOTAL_MEMORY to %d to be more reasonable for asm.js' % heap)
- shared.Settings.TOTAL_MEMORY = heap
-
if shared.Settings.CORRECT_SIGNS >= 2 or shared.Settings.CORRECT_OVERFLOWS >= 2 or shared.Settings.CORRECT_ROUNDINGS >= 2:
debug_level = 4 # must keep debug info to do line-by-line operations
@@ -1272,14 +1295,14 @@ try:
# First, generate LLVM bitcode. For each input file, we get base.o with bitcode
for input_file in input_files:
- file_suffix = filename_type_suffix(input_file)
- if file_suffix.endswith(SOURCE_SUFFIXES):
+ file_ending = filename_type_ending(input_file)
+ if file_ending.endswith(SOURCE_ENDINGS):
logging.debug('compiling source file: ' + input_file)
input_file = shared.Building.preprocess(input_file, in_temp(uniquename(input_file)))
output_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
temp_files.append(output_file)
args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file]
- if file_suffix.endswith(CXX_SUFFIXES):
+ if file_ending.endswith(CXX_ENDINGS):
args += shared.EMSDK_CXX_OPTS
logging.debug("running: " + call + ' ' + ' '.join(args))
execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that)
@@ -1287,17 +1310,17 @@ try:
logging.error('compiler frontend failed to generate LLVM bitcode, halting')
sys.exit(1)
else: # bitcode
- if file_suffix.endswith(BITCODE_SUFFIXES):
+ if file_ending.endswith(BITCODE_ENDINGS):
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)
- elif file_suffix.endswith(DYNAMICLIB_SUFFIXES) or shared.Building.is_ar(input_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)
- elif file_suffix.endswith(ASSEMBLY_SUFFIXES):
+ elif file_ending.endswith(ASSEMBLY_ENDINGS):
if not LEAVE_INPUTS_RAW:
# Note that by assembling the .ll file, then disassembling it later, we will
# remove annotations which is a good thing for compilation time
@@ -1315,8 +1338,8 @@ try:
# Optimize source files
if llvm_opts > 0:
for i, input_file in enumerate(input_files):
- file_suffix = filename_type_suffix(input_file)
- if file_suffix.endswith(SOURCE_SUFFIXES):
+ file_ending = filename_type_ending(input_file)
+ if file_ending.endswith(SOURCE_ENDINGS):
temp_file = temp_files[i]
logging.debug('optimizing %s with -O%s' % (input_file, llvm_opts))
shared.Building.llvm_opt(temp_file, llvm_opts)
@@ -1329,7 +1352,16 @@ try:
else:
if len(input_files) == 1:
temp_output_base = in_temp(unsuffixed(uniquename(input_files[0])))
- shutil.move(temp_output_base + '.o', specified_target)
+ if specified_target.endswith('/') or specified_target.endswith('\\') or os.path.isdir(specified_target): # User passed '-o <directory' as the location to output to.
+ obj_output_name = os.path.join(specified_target, os.path.splitext(os.path.basename(input_file))[0] + default_object_extension)
+ logging.debug('User specified -o <directoryname> as the location of the output. Generating output file ' + obj_output_name)
+ try:
+ shutil.move(temp_output_base + '.o', obj_output_name)
+ except IOError, e:
+ logging.error('Could not write to output file ' + obj_output_name + '. Perhaps the output directory does not exist?')
+ exit(1)
+ else: # User passed '-o <filename>' as the location to output to.
+ shutil.move(temp_output_base + '.o', specified_target)
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.
@@ -1661,11 +1693,11 @@ 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_SUFFIXES or suffix(temp_files[0]) in DYNAMICLIB_SUFFIXES) and shared.Building.is_ar(temp_files[0])):
+ (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
logging.debug('linking: ' + str(linker_inputs))
t0 = time.time()
- shared.Building.link(linker_inputs, in_temp(target_basename + '.bc'), force_archive_contents = len(filter(lambda temp: not temp.endswith(STATICLIB_SUFFIXES), temp_files)) == 0)
+ shared.Building.link(linker_inputs, in_temp(target_basename + '.bc'), force_archive_contents = len(filter(lambda temp: not temp.endswith(STATICLIB_ENDINGS), temp_files)) == 0)
t1 = time.time()
logging.debug(' linking took %.2f seconds' % (t1 - t0))
final = in_temp(target_basename + '.bc')
@@ -1711,22 +1743,25 @@ try:
# At minimum remove dead functions etc., this potentially saves a lot in the size of the generated code (and the time to compile it)
link_opts += shared.Building.get_safe_internalize() + ['-globaldce']
- # Simplify LLVM bitcode for fastcomp
- if os.environ.get('EMCC_FAST_COMPILER') and not AUTODEBUG:
- link_opts += ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt']
- if (not save_bc and not os.environ.get('EMCC_FAST_COMPILER')) or AUTODEBUG:
+ if (not save_bc and not fastcomp) or AUTODEBUG:
# let llvm opt directly emit ll, to skip writing and reading all the bitcode
link_opts += ['-S']
shared.Building.llvm_opt(final, link_opts, final + '.link.ll')
final = final + '.link.ll'
if DEBUG: save_intermediate('linktime', 'll')
else:
+ if fastcomp and not save_bc:
+ # Simplify LLVM bitcode for fastcomp
+ link_opts += ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt']
shared.Building.llvm_opt(final, link_opts)
if DEBUG: save_intermediate('linktime', 'bc')
-
- if save_bc:
- shutil.copyfile(final, save_bc)
+ if save_bc:
+ shutil.copyfile(final, save_bc)
+ if fastcomp:
+ shared.Building.llvm_opt(final, ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt'], final + '.adsimp.bc')
+ final += '.adsimp.bc'
+ if DEBUG: save_intermediate('adsimp', 'bc')
# Prepare .ll for Emscripten
if not LEAVE_INPUTS_RAW:
@@ -1743,7 +1778,7 @@ try:
if DEBUG: save_intermediate('autodebug', 'll')
# Simplify bitcode after autodebug
- if os.environ.get('EMCC_FAST_COMPILER') and AUTODEBUG:
+ if fastcomp and (AUTODEBUG or LEAVE_INPUTS_RAW):
shared.Building.llvm_opt(final, ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt'], final + '.adsimp.bc')
final += '.adsimp.bc'
if DEBUG: save_intermediate('adsimp', 'bc')
diff --git a/emrun b/emrun
index d5975b8a..e3596eed 100755
--- a/emrun
+++ b/emrun
@@ -492,15 +492,18 @@ def win_print_gpu_info():
print "GPU"+str(i)+ ": " + gpus[i] + " with " + gpu_memory[i] + " MBs of VRAM"
def linux_print_gpu_info():
- glxinfo = subprocess.check_output('glxinfo')
- for line in glxinfo.split("\n"):
- if "OpenGL vendor string:" in line:
- gl_vendor = line[len("OpenGL vendor string:"):].strip()
- if "OpenGL version string:" in line:
- gl_version = line[len("OpenGL version string:"):].strip()
- if "OpenGL renderer string:" in line:
- gl_renderer = line[len("OpenGL renderer string:"):].strip()
- logi('GPU: ' + gl_vendor + ' ' + gl_renderer + ', GL version ' + gl_version)
+ try:
+ glxinfo = subprocess.check_output('glxinfo')
+ for line in glxinfo.split("\n"):
+ if "OpenGL vendor string:" in line:
+ gl_vendor = line[len("OpenGL vendor string:"):].strip()
+ if "OpenGL version string:" in line:
+ gl_version = line[len("OpenGL version string:"):].strip()
+ if "OpenGL renderer string:" in line:
+ gl_renderer = line[len("OpenGL renderer string:"):].strip()
+ logi('GPU: ' + gl_vendor + ' ' + gl_renderer + ', GL version ' + gl_version)
+ except:
+ pass
def osx_print_gpu_info():
try:
@@ -722,11 +725,12 @@ def find_browser(name):
('firefox_beta', os.path.expanduser('~/firefox_beta/firefox')),
('firefox_aurora', os.path.expanduser('~/firefox_aurora/firefox')),
('firefox_nightly', os.path.expanduser('~/firefox_nightly/firefox')),
- ('chrome', which('google-chrome-stable'))]
+ ('chrome', which('google-chrome-stable')),
+ ('chrome', which('google-chrome'))]
for (alias, browser_exe) in browser_locations:
if name == alias:
- if os.path.isfile(browser_exe):
+ if browser_exe is not None and os.path.isfile(browser_exe):
return [browser_exe]
return None # Could not find the browser
diff --git a/src/analyzer.js b/src/analyzer.js
index 17582ea3..e8ca6cf6 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -1570,7 +1570,17 @@ function analyzer(data, sidePass) {
for (var j = 0; j < label.lines.length; j++) {
var line = label.lines[j];
if ((line.intertype == 'call' || line.intertype == 'invoke') && line.ident == setjmp) {
- // Add a new label
+ if (line.intertype == 'invoke') {
+ // setjmp cannot trigger unwinding, so just reduce the invoke to a call + branch
+ line.intertype = 'call';
+ label.lines.push({
+ intertype: 'branch',
+ label: line.toLabel,
+ lineNum: line.lineNum + 0.01, // XXX legalizing might confuse this
+ });
+ line.toLabel = line.unwindLabel = -2;
+ }
+ // split this label into up to the setjmp (including), then a new label for the rest. longjmp will reach the rest
var oldLabel = label.ident;
var newLabel = func.labelIdCounter++;
if (!func.setjmpTable) func.setjmpTable = [];
diff --git a/src/compiler.js b/src/compiler.js
index 7d768c3d..e4ce1c88 100644
--- a/src/compiler.js
+++ b/src/compiler.js
@@ -134,7 +134,7 @@ load('settings.js');
var settings_file = arguments_[0];
var ll_file = arguments_[1];
phase = arguments_[2];
-if (phase == 'pre') {
+if (phase == 'pre' || phase == 'glue') {
additionalLibraries = Array.prototype.slice.call(arguments_, 3);
} else {
var forwardedDataFile = arguments_[3];
diff --git a/src/jsifier.js b/src/jsifier.js
index 6b831b04..58dc4653 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -6,7 +6,6 @@
// Handy sets
var STRUCT_LIST = set('struct', 'list');
-var UNDERSCORE_OPENPARENS = set('_', '(');
var RELOOP_IGNORED_LASTS = set('return', 'unreachable', 'resume');
var addedLibraryItems = {};
@@ -96,19 +95,6 @@ function JSify(data, functionsOnly, givenFunctions) {
// Functions
- Functions.currExternalFunctions = !mainPass ? givenFunctions.currExternalFunctions : {};
-
- data.functionStubs.forEach(function(func) {
- // Don't overwrite stubs that have more info.
- if (!Functions.currExternalFunctions.hasOwnProperty(func.ident) ||
- !Functions.currExternalFunctions[func.ident].numParams === undefined) {
- Functions.currExternalFunctions[func.ident] = {
- hasVarArgs: func.hasVarArgs,
- numParams: func.params && func.params.length
- };
- }
- });
-
if (phase == 'funcs') { // || phase == 'pre') { // pre has function shells, just to defined implementedFunctions
var MAX_BATCH_FUNC_LINES = 1000;
while (data.unparsedFunctions.length > 0) {
@@ -1824,7 +1810,7 @@ function JSify(data, functionsOnly, givenFunctions) {
print('staticSealed = true; // seal the static portion of memory\n');
print('STACK_MAX = STACK_BASE + ' + TOTAL_STACK + ';\n');
print('DYNAMIC_BASE = DYNAMICTOP = Runtime.alignMemory(STACK_MAX);\n');
- print('assert(DYNAMIC_BASE < TOTAL_MEMORY); // Stack must fit in TOTAL_MEMORY; allocations from here on may enlarge TOTAL_MEMORY\n');
+ print('assert(DYNAMIC_BASE < TOTAL_MEMORY, "TOTAL_MEMORY not big enough for stack");\n');
}
if (asmLibraryFunctions.length > 0) {
diff --git a/src/library.js b/src/library.js
index fc731e01..354e5549 100644
--- a/src/library.js
+++ b/src/library.js
@@ -8858,7 +8858,8 @@ LibraryManager.library = {
}
}
str += ')';
- args = args.callee.caller.arguments;
+ var caller = args.callee.caller;
+ args = caller ? caller.arguments : [];
if (first)
str = '';
return [args, funcname, str];
diff --git a/src/library_gl.js b/src/library_gl.js
index 29f78c8a..075d7cb5 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -268,11 +268,27 @@ var LibraryGL = {
return;
case "object":
if (result === null) {
- GL.recordError(0x0500); // GL_INVALID_ENUM
+ // null is a valid result for some (e.g., which buffer is bound - perhaps nothing is bound), but otherwise
+ // can mean an invalid name_, which we need to report as an error
+ switch(name_) {
+ case 0x8894: // ARRAY_BUFFER_BINDING
+ case 0x8B8D: // CURRENT_PROGRAM
+ case 0x8895: // ELEMENT_ARRAY_BUFFER_BINDING
+ case 0x8CA6: // FRAMEBUFFER_BINDING
+ case 0x8CA7: // RENDERBUFFER_BINDING
+ case 0x8069: // TEXTURE_BINDING_2D
+ case 0x8514: { // TEXTURE_BINDING_CUBE_MAP
+ ret = 0;
+ break;
+ }
+ default: {
+ GL.recordError(0x0500); // GL_INVALID_ENUM
#if GL_ASSERTIONS
- Module.printErr('GL_INVALID_ENUM in glGet' + type + 'v(' + name_ + ') and it returns null!');
+ Module.printErr('GL_INVALID_ENUM in glGet' + type + 'v(' + name_ + ') and it returns null!');
#endif
- return;
+ return;
+ }
+ }
} else if (result instanceof Float32Array ||
result instanceof Uint32Array ||
result instanceof Int32Array ||
@@ -547,6 +563,9 @@ var LibraryGL = {
Module.ctx.getExtension('WEBKIT_EXT_texture_filter_anisotropic');
GL.floatExt = Module.ctx.getExtension('OES_texture_float');
+
+ // Extension available from Firefox 26 and Google Chrome 30
+ GL.instancedArraysExt = Module.ctx.getExtension('ANGLE_instanced_arrays');
// These are the 'safe' feature-enabling extensions that don't add any performance impact related to e.g. debugging, and
// should be enabled by default so that client GLES2/GL code will not need to go through extra hoops to get its stuff working.
@@ -1685,7 +1704,7 @@ var LibraryGL = {
glGetFramebufferAttachmentParameteriv__sig: 'viiii',
glGetFramebufferAttachmentParameteriv: function(target, attachment, pname, params) {
var result = Module.ctx.getFramebufferAttachmentParameter(target, attachment, pname);
- {{{ makeSetValue('params', '0', 'params', 'i32') }}};
+ {{{ makeSetValue('params', '0', 'result', 'i32') }}};
},
glIsFramebuffer__sig: 'ii',
@@ -1916,6 +1935,13 @@ var LibraryGL = {
return id;
};
+ function ensurePrecision(source) {
+ if (!/precision +(low|medium|high)p +float *;/.test(source)) {
+ source = 'precision mediump float;\n' + source;
+ }
+ return source;
+ }
+
var glShaderSource = _glShaderSource;
_glShaderSource = function _glShaderSource(shader, count, string, length) {
var source = GL.getSource(shader, count, string, length);
@@ -1989,6 +2015,7 @@ var LibraryGL = {
source = 'varying float v_fogFragCoord; \n' +
source.replace(/gl_FogFragCoord/g, 'v_fogFragCoord');
}
+ source = ensurePrecision(source);
} else { // Fragment shader
for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) {
var old = source;
@@ -2020,7 +2047,7 @@ var LibraryGL = {
source = 'varying float v_fogFragCoord; \n' +
source.replace(/gl_FogFragCoord/g, 'v_fogFragCoord');
}
- source = 'precision mediump float;\n' + source;
+ source = ensurePrecision(source);
}
#if GL_DEBUG
GL.shaderSources[shader] = source;
@@ -4959,6 +4986,45 @@ var LibraryGL = {
return Module.ctx.getError();
}
},
+
+ // ANGLE_instanced_arrays WebGL extension related functions
+
+ glVertexAttribDivisor__sig: 'vii',
+ glVertexAttribDivisor: function(index, divisor) {
+#if GL_ASSERTIONS
+ assert(GL.instancedArraysExt, 'Must have ANGLE_instanced_arrays extension to use WebGL instancing');
+#endif
+ GL.instancedArraysExt.vertexAttribDivisorANGLE(index, divisor);
+ },
+
+ glDrawArraysInstanced__sig: 'viiii',
+ glDrawArraysInstanced: function(mode, first, count, primcount) {
+#if GL_ASSERTIONS
+ assert(GL.instancedArraysExt, 'Must have ANGLE_instanced_arrays extension to use WebGL instancing');
+#endif
+ GL.instancedArraysExt.drawArraysInstancedANGLE(mode, first, count, primcount);
+ },
+
+ glDrawElementsInstanced__sig: 'viiiii',
+ glDrawElementsInstanced: function(mode, count, type, indices, primcount) {
+#if GL_ASSERTIONS
+ assert(GL.instancedArraysExt, 'Must have ANGLE_instanced_arrays extension to use WebGL instancing');
+#endif
+ GL.instancedArraysExt.drawElementsInstancedANGLE(mode, count, type, indices, primcount);
+ },
+
+ // OpenGL Desktop/ES 2.0 instancing extensions compatibility
+
+ glVertexAttribDivisorNV: 'glVertexAttribDivisor',
+ glDrawArraysInstancedNV: 'glDrawArraysInstanced',
+ glDrawElementsInstancedNV: 'glDrawElementsInstanced',
+ glVertexAttribDivisorEXT: 'glVertexAttribDivisor',
+ glDrawArraysInstancedEXT: 'glDrawArraysInstanced',
+ glDrawElementsInstancedEXT: 'glDrawElementsInstanced',
+ glVertexAttribDivisorARB: 'glVertexAttribDivisor',
+ glDrawArraysInstancedARB: 'glDrawArraysInstanced',
+ glDrawElementsInstancedARB: 'glDrawElementsInstanced',
+
// signatures of simple pass-through functions, see later
glActiveTexture__sig: 'vi',
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 2efc1271..fc38dd1c 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -1059,11 +1059,35 @@ var LibrarySDL = {
var src = buffer >> 2;
var dst = 0;
var isScreen = surf == SDL.screen;
- var data32 = new Uint32Array(data.buffer);
- var num = data32.length;
- while (dst < num) {
- // HEAP32[src++] is an optimization. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
- data32[dst++] = HEAP32[src++] | (isScreen ? 0xff000000 : 0);
+ var num;
+ if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) {
+ // IE10/IE11: ImageData objects are backed by the deprecated CanvasPixelArray,
+ // not UInt8ClampedArray. These don't have buffers, so we need to revert
+ // to copying a byte at a time. We do the undefined check because modern
+ // browsers do not define CanvasPixelArray anymore.
+ num = data.length;
+ while (dst < num) {
+ var val = HEAP32[src]; // This is optimized. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
+ data[dst ] = val & 0xff;
+ data[dst+1] = (val >> 8) & 0xff;
+ data[dst+2] = (val >> 16) & 0xff;
+ data[dst+3] = isScreen ? 0xff : ((val >> 24) & 0xff);
+ src++;
+ dst += 4;
+ }
+ } else {
+ var data32 = new Uint32Array(data.buffer);
+ num = data32.length;
+ if (isScreen) {
+ while (dst < num) {
+ // HEAP32[src++] is an optimization. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
+ data32[dst++] = HEAP32[src++] | 0xff000000;
+ }
+ } else {
+ while (dst < num) {
+ data32[dst++] = HEAP32[src++];
+ }
+ }
}
#else
var num = surfData.image.data.length;
@@ -1220,6 +1244,7 @@ var LibrarySDL = {
if (surf) SDL.freeSurface(surf);
},
+ SDL_UpperBlit__deps: ['SDL_LockSurface'],
SDL_UpperBlit: function(src, srcrect, dst, dstrect) {
var srcData = SDL.surfaces[src];
var dstData = SDL.surfaces[dst];
diff --git a/src/parseTools.js b/src/parseTools.js
index ff981264..874514b1 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -16,6 +16,7 @@ function processMacros(text) {
// Simple #if/else/endif preprocessing for a file. Checks if the
// ident checked is true in our global.
+// Also handles #include x.js (similar to C #include <file>)
function preprocess(text) {
var lines = text.split('\n');
var ret = '';
@@ -30,25 +31,29 @@ function preprocess(text) {
ret += line + '\n';
}
} else {
- if (line[1] && line[1] == 'i') { // if
- var parts = line.split(' ');
- var ident = parts[1];
- var op = parts[2];
- var value = parts[3];
- if (op) {
- if (op === '==') {
- showStack.push(ident in this && this[ident] == value);
- } else if (op === '!=') {
- showStack.push(!(ident in this && this[ident] == value));
+ if (line[1] == 'i') {
+ if (line[2] == 'f') { // if
+ var parts = line.split(' ');
+ var ident = parts[1];
+ var op = parts[2];
+ var value = parts[3];
+ if (op) {
+ if (op === '==') {
+ showStack.push(ident in this && this[ident] == value);
+ } else if (op === '!=') {
+ showStack.push(!(ident in this && this[ident] == value));
+ } else {
+ error('unsupported preprecessor op ' + op);
+ }
} else {
- error('unsupported preprecessor op ' + op);
+ showStack.push(ident in this && this[ident] > 0);
}
- } else {
- showStack.push(ident in this && this[ident] > 0);
+ } else if (line[2] == 'n') { // include
+ ret += '\n' + read(line.substr(line.indexOf(' ')+1)) + '\n'
}
- } else if (line[2] && line[2] == 'l') { // else
+ } else if (line[2] == 'l') { // else
showStack.push(!showStack.pop());
- } else if (line[2] && line[2] == 'n') { // endif
+ } else if (line[2] == 'n') { // endif
showStack.pop();
} else {
throw "Unclear preprocessor command: " + line;
diff --git a/src/preamble.js b/src/preamble.js
index 832ec2c3..f9fccdf6 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -866,6 +866,21 @@ var TOTAL_STACK = Module['TOTAL_STACK'] || {{{ TOTAL_STACK }}};
var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || {{{ TOTAL_MEMORY }}};
var FAST_MEMORY = Module['FAST_MEMORY'] || {{{ FAST_MEMORY }}};
+#if ASM_JS
+var totalMemory = 4096;
+while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) {
+ if (totalMemory < 16*1024*1024) {
+ totalMemory *= 2;
+ } else {
+ totalMemory += 16*1024*1024
+ }
+}
+if (totalMemory !== TOTAL_MEMORY) {
+ Module.printErr('increasing TOTAL_MEMORY to ' + totalMemory + ' to be more reasonable');
+ TOTAL_MEMORY = totalMemory;
+}
+#endif
+
// Initialize the runtime's memory
#if USE_TYPED_ARRAYS
// check for full engine support (use string 'subarray' to avoid closure compiler confusion)
diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp
index d2a48f63..de69e0ef 100644
--- a/src/relooper/Relooper.cpp
+++ b/src/relooper/Relooper.cpp
@@ -101,9 +101,7 @@ void Branch::Render(Block *Target, bool SetLabel) {
// Block
-int Block::IdCounter = 1; // 0 is reserved for clearings
-
-Block::Block(const char *CodeInit, const char *BranchVarInit) : Parent(NULL), Id(Block::IdCounter++), IsCheckedMultipleEntry(false) {
+Block::Block(const char *CodeInit, const char *BranchVarInit) : Parent(NULL), Id(-1), IsCheckedMultipleEntry(false) {
Code = strdup(CodeInit);
BranchVar = BranchVarInit ? strdup(BranchVarInit) : NULL;
}
@@ -142,6 +140,7 @@ void Block::Render(bool InLoop) {
if (!ProcessedBranchesOut.size()) return;
bool SetLabel = true; // in some cases it is clear we can avoid setting label, see later
+ bool ForceSetLabel = Shape::IsEmulated(Parent);
// A setting of the label variable (label = x) is necessary if it can
// cause an impact. The main case is where we set label to x, then elsewhere
@@ -210,7 +209,7 @@ void Block::Render(bool InLoop) {
Target = DefaultTarget;
Details = ProcessedBranchesOut[DefaultTarget];
}
- bool SetCurrLabel = SetLabel && Target->IsCheckedMultipleEntry;
+ bool SetCurrLabel = (SetLabel && Target->IsCheckedMultipleEntry) || ForceSetLabel;
bool HasFusedContent = Fused && contains(Fused->InnerMap, Target);
bool HasContent = SetCurrLabel || Details->Type != Branch::Direct || HasFusedContent || Details->Code;
if (iter != ProcessedBranchesOut.end()) {
@@ -272,10 +271,6 @@ void Block::Render(bool InLoop) {
}
}
-// Shape
-
-int Shape::IdCounter = 0;
-
// MultipleShape
void MultipleShape::RenderLoopPrefix() {
@@ -330,16 +325,19 @@ void LoopShape::Render(bool InLoop) {
if (Next) Next->Render(InLoop);
};
-/*
// EmulatedShape
void EmulatedShape::Render(bool InLoop) {
+ PrintIndented("label = %d;\n", Entry->Id);
+ if (Labeled) {
+ PrintIndented("L%d: ", Id);
+ }
PrintIndented("while(1) {\n");
Indenter::Indent();
- PrintIndented("switch(label) {\n");
+ PrintIndented("switch(label|0) {\n");
Indenter::Indent();
- for (int i = 0; i < Blocks.size(); i++) {
- Block *Curr = Blocks[i];
+ for (BlockSet::iterator iter = Blocks.begin(); iter != Blocks.end(); iter++) {
+ Block *Curr = *iter;
PrintIndented("case %d: {\n", Curr->Id);
Indenter::Indent();
Curr->Render(InLoop);
@@ -353,11 +351,10 @@ void EmulatedShape::Render(bool InLoop) {
PrintIndented("}\n");
if (Next) Next->Render(InLoop);
};
-*/
// Relooper
-Relooper::Relooper() : Root(NULL) {
+Relooper::Relooper() : Root(NULL), Emulate(false), BlockIdCounter(1), ShapeIdCounter(0) { // block ID 0 is reserved for clearings
}
Relooper::~Relooper() {
@@ -366,6 +363,7 @@ Relooper::~Relooper() {
}
void Relooper::AddBlock(Block *New) {
+ New->Id = BlockIdCounter++;
Blocks.push_back(New);
}
@@ -419,7 +417,7 @@ void Relooper::Calculate(Block *Entry) {
for (BlockSet::iterator iter = Original->BranchesIn.begin(); iter != Original->BranchesIn.end(); iter++) {
Block *Prior = *iter;
Block *Split = new Block(Original->Code, Original->BranchVar);
- Parent->Blocks.push_back(Split);
+ Parent->AddBlock(Split);
PrintDebug(" to %d\n", Split->Id);
Split->BranchesIn.insert(Prior);
Branch *Details = Prior->BranchesOut[Original];
@@ -461,7 +459,7 @@ void Relooper::Calculate(Block *Entry) {
}
}
- Pre.SplitDeadEnds();
+ if (!Emulate) Pre.SplitDeadEnds();
// Recursively process the graph
@@ -470,6 +468,7 @@ void Relooper::Calculate(Block *Entry) {
// Add a shape to the list of shapes in this Relooper calculation
void Notice(Shape *New) {
+ New->Id = Parent->ShapeIdCounter++;
Parent->Shapes.push_back(New);
}
@@ -526,6 +525,21 @@ void Relooper::Calculate(Block *Entry) {
return Simple;
}
+ Shape *MakeEmulated(BlockSet &Blocks, Block *Entry, BlockSet &NextEntries) {
+ PrintDebug("creating emulated block with entry #%d and everything it can reach, %d blocks\n", Entry->Id, Blocks.size());
+ EmulatedShape *Emulated = new EmulatedShape;
+ Notice(Emulated);
+ Emulated->Entry = Entry;
+ for (BlockSet::iterator iter = Blocks.begin(); iter != Blocks.end(); iter++) {
+ Block *Curr = *iter;
+ Emulated->Blocks.insert(Curr);
+ Curr->Parent = Emulated;
+ Solipsize(Curr, Branch::Continue, Emulated, Blocks);
+ }
+ Blocks.clear();
+ return Emulated;
+ }
+
Shape *MakeLoop(BlockSet &Blocks, BlockSet& Entries, BlockSet &NextEntries) {
// Find the inner blocks in this loop. Proceed backwards from the entries until
// you reach a seen block, collecting as you go.
@@ -837,6 +851,9 @@ void Relooper::Calculate(Block *Entry) {
if (Entries->size() == 0) return Ret;
if (Entries->size() == 1) {
Block *Curr = *(Entries->begin());
+ if (Parent->Emulate) {
+ Make(MakeEmulated(Blocks, Curr, *NextEntries));
+ }
if (Curr->BranchesIn.size() == 0) {
// One entry, no looping ==> Simple
Make(MakeSimple(Blocks, Curr, *NextEntries));
@@ -844,6 +861,7 @@ void Relooper::Calculate(Block *Entry) {
// One entry, looping ==> Loop
Make(MakeLoop(Blocks, *Entries, *NextEntries));
}
+
// More than one entry, try to eliminate through a Multiple groups of
// independent blocks from an entry/ies. It is important to remove through
// multiples as opposed to looping since the former is more performant.
diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h
index f3dedf8c..04f2ffc3 100644
--- a/src/relooper/Relooper.h
+++ b/src/relooper/Relooper.h
@@ -57,7 +57,7 @@ struct Block {
BlockBranchMap ProcessedBranchesOut;
BlockSet ProcessedBranchesIn;
Shape *Parent; // The shape we are directly inside
- int Id; // A unique identifier
+ int Id; // A unique identifier, defined when added to relooper
const char *Code; // The string representation of the code in this block. Owning pointer (we copy the input)
const char *BranchVar; // If we have more than one branch out, the variable whose value determines where we go
bool IsCheckedMultipleEntry; // If true, we are a multiple entry, so reaching us requires setting the label variable
@@ -69,9 +69,6 @@ struct Block {
// Prints out the instructions code and branchings
void Render(bool InLoop);
-
- // INTERNAL
- static int IdCounter;
};
// Represents a structured control flow shape, one of
@@ -96,20 +93,22 @@ class SimpleShape;
class LabeledShape;
class MultipleShape;
class LoopShape;
+class EmulatedShape;
struct Shape {
- int Id; // A unique identifier. Used to identify loops, labels are Lx where x is the Id.
+ int Id; // A unique identifier. Used to identify loops, labels are Lx where x is the Id. Defined when added to relooper
Shape *Next; // The shape that will appear in the code right after this one
Shape *Natural; // The shape that control flow gets to naturally (if there is Next, then this is Next)
enum ShapeType {
Simple,
Multiple,
- Loop
+ Loop,
+ Emulated
};
ShapeType Type;
- Shape(ShapeType TypeInit) : Id(Shape::IdCounter++), Next(NULL), Type(TypeInit) {}
+ Shape(ShapeType TypeInit) : Id(-1), Next(NULL), Type(TypeInit) {}
virtual ~Shape() {}
virtual void Render(bool InLoop) = 0;
@@ -118,9 +117,7 @@ struct Shape {
static MultipleShape *IsMultiple(Shape *It) { return It && It->Type == Multiple ? (MultipleShape*)It : NULL; }
static LoopShape *IsLoop(Shape *It) { return It && It->Type == Loop ? (LoopShape*)It : NULL; }
static LabeledShape *IsLabeled(Shape *It) { return IsMultiple(It) || IsLoop(It) ? (LabeledShape*)It : NULL; }
-
- // INTERNAL
- static int IdCounter;
+ static EmulatedShape *IsEmulated(Shape *It) { return It && It->Type == Emulated ? (EmulatedShape*)It : NULL; }
};
struct SimpleShape : public Shape {
@@ -162,12 +159,15 @@ struct LoopShape : public LabeledShape {
void Render(bool InLoop);
};
-/*
-struct EmulatedShape : public Shape {
- std::deque<Block*> Blocks;
+// TODO EmulatedShape is only partially functional. Currently it can be used for the
+// entire set of blocks being relooped, but not subsets.
+struct EmulatedShape : public LabeledShape {
+ Block *Entry;
+ BlockSet Blocks;
+
+ EmulatedShape() : LabeledShape(Emulated) { Labeled = true; }
void Render(bool InLoop);
};
-*/
// Implements the relooper algorithm for a function's blocks.
//
@@ -184,6 +184,9 @@ struct Relooper {
std::deque<Block*> Blocks;
std::deque<Shape*> Shapes;
Shape *Root;
+ bool Emulate;
+ int BlockIdCounter;
+ int ShapeIdCounter;
Relooper();
~Relooper();
@@ -204,6 +207,9 @@ struct Relooper {
// Sets asm.js mode on or off (default is off)
static void SetAsmJSMode(int On);
+
+ // Sets whether we must emulate everything with switch-loop code
+ void SetEmulate(int E) { Emulate = E; }
};
typedef std::map<Block*, BlockSet> BlockBlockSetMap;
diff --git a/src/relooper/fuzzer.py b/src/relooper/fuzzer.py
index 50846d10..fa47583e 100644
--- a/src/relooper/fuzzer.py
+++ b/src/relooper/fuzzer.py
@@ -87,6 +87,12 @@ int main() {
Relooper r;
'''
+ if random.random() < 0.1:
+ print 'emulate'
+ fast += '''
+ r.SetEmulate(true);
+'''
+
for i in range(num):
fast += ''' r.AddBlock(b%d);
''' % i
diff --git a/src/relooper/test.cpp b/src/relooper/test.cpp
index fbd9c7aa..773f6ee4 100644
--- a/src/relooper/test.cpp
+++ b/src/relooper/test.cpp
@@ -258,5 +258,33 @@ int main() {
puts(buffer);
}
+
+ if (1) {
+ Relooper::SetOutputBuffer(buffer, sizeof(buffer));
+
+ printf("\n\n-- If pattern, emulated --\n\n", "the_var");
+
+ Block *b_a = new Block("// block A\n", NULL);
+ Block *b_b = new Block("// block B\n", "b_check()");
+ Block *b_c = new Block("// block C\n", NULL);
+
+ b_a->AddBranchTo(b_b, "check == 10", "atob();");
+ b_a->AddBranchTo(b_c, NULL, "atoc();");
+
+ b_b->AddBranchTo(b_c, "case 17:", "btoc();");
+ b_b->AddBranchTo(b_a, NULL, NULL);
+
+ Relooper r;
+ r.SetEmulate(true);
+ r.AddBlock(b_a);
+ r.AddBlock(b_b);
+ r.AddBlock(b_c);
+
+ r.Calculate(b_a);
+ printf("\n\n", "the_var");
+ r.Render();
+
+ puts(buffer);
+ }
}
diff --git a/src/relooper/test.txt b/src/relooper/test.txt
index 2c530567..540f7bdb 100644
--- a/src/relooper/test.txt
+++ b/src/relooper/test.txt
@@ -4,23 +4,23 @@
-// block A
-switch (the_var) {
-check == 10 {
- atob();
- // block B
+ // block A
switch (the_var) {
+ check == 10 {
+ atob();
+ // block B
+ switch (the_var) {
+ default: {
+ btoc();
+ }
+ }
+ break;
+ }
default: {
- btoc();
+ atoc();
}
}
- break;
-}
-default: {
- atoc();
-}
-}
-// block C
+ // block C
@@ -28,25 +28,25 @@ default: {
-// block A
-switch (the_var) {
-check == 15 {
- // block B
+ // block A
switch (the_var) {
- default: {
- }
+ check == 15 {
+ // block B
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
-}
-default: {
- // block C
- switch (the_var) {
default: {
+ // block C
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
-}
-}
-// block D
+ // block D
@@ -54,81 +54,81 @@ default: {
-L9: while(1) {
- // block A
- var check = maybe();
- switch (the_var) {
- default: {
- }
- }
- // block B
- switch (the_var) {
- check == 41 {
- break;
- }
- default: {
- break L9;
- }
+ L0: while(1) {
+ // block A
+ var check = maybe();
+ switch (the_var) {
+ default: {
+ }
+ }
+ // block B
+ switch (the_var) {
+ check == 41 {
+ break;
+ }
+ default: {
+ break L0;
+ }
+ }
}
-}
-// block C
+ // block C
-- Loop with phi to head
-// code 1
-switch (the_var) {
-default: {
- var $i_0 = 0;var $x_0 = 5;
-}
-}
-L14: while(1) {
- // code 2
+ // code 1
switch (the_var) {
- $2 {
- break;
- }
default: {
- var $x_1 = $x_0;
- label = 18;
- break L14;
+ var $i_0 = 0;var $x_0 = 5;
+ }
+ }
+ L1: while(1) {
+ // code 2
+ switch (the_var) {
+ $2 {
+ break;
+ }
+ default: {
+ var $x_1 = $x_0;
+ label = -1;
+ break L1;
+ }
+ }
+ // code 3
+ switch (the_var) {
+ $6 {
+ break L1;
+ break;
+ }
+ default: {
+ var $i_0 = $7;var $x_0 = $5;
+ }
+ }
}
+ if (label == -1) {
+ // code 7
}
- // code 3
+ // code 4
switch (the_var) {
- $6 {
- break L14;
+ $10 {
+ // code 5
+ switch (the_var) {
+ default: {
+ }
+ }
break;
}
default: {
- var $i_0 = $7;var $x_0 = $5;
}
}
-}
-if (label == 18) {
- // code 7
-}
-// code 4
-switch (the_var) {
-$10 {
- // code 5
+ // code 6
switch (the_var) {
default: {
+ var $x_1 = $13;
}
}
- break;
-}
-default: {
-}
-}
-// code 6
-switch (the_var) {
-default: {
- var $x_1 = $13;
-}
-}
-// code 7
+ // code 7
@@ -136,30 +136,30 @@ default: {
-// block A...................................................................................................
-switch (the_var) {
-chak() {
- atob();
- // block B...................................................................................................
+ // block A...................................................................................................
switch (the_var) {
- default: {
- btod();
- }
+ chak() {
+ atob();
+ // block B...................................................................................................
+ switch (the_var) {
+ default: {
+ btod();
+ }
+ }
+ // block D
+ break;
}
- // block D
- break;
-}
-default: {
- atoc();
- // block C...................................................................................................
- switch (the_var) {
default: {
- ctod2();
+ atoc();
+ // block C...................................................................................................
+ switch (the_var) {
+ default: {
+ ctod2();
+ }
+ }
+ // block D
}
}
- // block D
-}
-}
@@ -167,27 +167,27 @@ default: {
-// block A
-switch (the_var) {
-check == 10 {
- break;
-}
-default: {
- return C;
-}
-}
-while(1) {
- // block B
+ // block A
switch (the_var) {
- default: {
- }
+ check == 10 {
+ break;
}
- // block D
- switch (the_var) {
default: {
+ return C;
}
}
-}
+ while(1) {
+ // block B
+ switch (the_var) {
+ default: {
+ }
+ }
+ // block D
+ switch (the_var) {
+ default: {
+ }
+ }
+ }
@@ -195,51 +195,51 @@ while(1) {
-// block A
-L37: do {
- switch (the_var) {
- expensive() {
- label = 33;
- break;
- }
- default: {
- // block B
+ // block A
+ L1: do {
switch (the_var) {
- expensive2() {
- label = 33;
- break L37;
+ expensive() {
+ label = 3;
break;
}
default: {
+ // block B
+ switch (the_var) {
+ expensive2() {
+ label = 3;
+ break L1;
+ break;
+ }
+ default: {
+ }
+ }
+ // block D
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- // block D
+ } while(0);
+ if (label == 3) {
+ // block C;
switch (the_var) {
default: {
}
}
}
+ while(1) {
+ // block E
+ switch (the_var) {
+ default: {
+ }
+ }
+ // block F
+ switch (the_var) {
+ default: {
+ }
+ }
}
-} while(0);
-if (label == 33) {
- // block C;
- switch (the_var) {
- default: {
- }
- }
-}
-while(1) {
- // block E
- switch (the_var) {
- default: {
- }
- }
- // block F
- switch (the_var) {
- default: {
- }
- }
-}
@@ -247,26 +247,71 @@ while(1) {
-// block A
-L46: do {
- switch (the_var) {
- shouldLoop() {
- while(1) {
- // block B
- switch (the_var) {
- moarLoop() {
+ // block A
+ L1: do {
+ switch (the_var) {
+ shouldLoop() {
+ while(1) {
+ // block B
+ switch (the_var) {
+ moarLoop() {
+ break;
+ }
+ default: {
+ break L1;
+ }
+ }
+ }
+ break;
+ }
+ default: {
+ }
+ }
+ } while(0);
+ // block C
+
+
+
+-- If pattern, emulated --
+
+
+
+ label = 1;
+ L0: while(1) {
+ switch(label|0) {
+ case 3: {
+ // block C
break;
}
- default: {
- break L46;
+ case 1: {
+ // block A
+ if (check == 10) {
+ atob();
+ label = 2;
+ continue L0;
+ } else {
+ atoc();
+ label = 3;
+ continue L0;
+ }
+ break;
}
+ case 2: {
+ // block B
+ switch (b_check()) {
+ case 17: {
+ btoc();
+ label = 3;
+ continue L0;
+ break;
+ }
+ default: {
+ label = 1;
+ continue L0;
+ }
+ }
+ break;
}
}
- break;
- }
- default: {
- }
}
-} while(0);
-// block C
diff --git a/src/relooper/test2.txt b/src/relooper/test2.txt
index a558a8b7..aba9ec1f 100644
--- a/src/relooper/test2.txt
+++ b/src/relooper/test2.txt
@@ -1,26 +1,26 @@
-ep
-L1: do {
- switch (var) {
- ep -> LBB1 {
- LBB1
- switch (the_var) {
- LBB1 -> LBB2 {
+ ep
+ L1: do {
+ switch (var) {
+ ep -> LBB1 {
+ LBB1
+ switch (the_var) {
+ LBB1 -> LBB2 {
+ break;
+ }
+ default: {
+ break L1;
+ }
+ }
+ LBB2
+ switch (the_var) {
+ default: {
+ }
+ }
break;
}
default: {
- break L1;
}
}
- LBB2
- switch (the_var) {
- default: {
- }
- }
- break;
- }
- default: {
- }
- }
-} while(0);
-LBB3
+ } while(0);
+ LBB3
diff --git a/src/relooper/test3.txt b/src/relooper/test3.txt
index f77e2618..33f85a7e 100644
--- a/src/relooper/test3.txt
+++ b/src/relooper/test3.txt
@@ -1,56 +1,56 @@
-ep
-L1: do {
- switch (the_var) {
- ep -> LBB1 {
- LBB1
+ ep
+ L1: do {
switch (the_var) {
- LBB1 -> LBB2 {
+ ep -> LBB1 {
+ LBB1
+ switch (the_var) {
+ LBB1 -> LBB2 {
+ break;
+ }
+ default: {
+ break L1;
+ }
+ }
+ LBB2
+ switch (the_var) {
+ default: {
+ }
+ }
break;
}
default: {
- break L1;
- }
- }
- LBB2
- switch (the_var) {
- default: {
}
}
- break;
- }
- default: {
- }
- }
-} while(0);
-LBB3
-L5: do {
- switch (the_var) {
- LBB3 -> LBB4 {
- LBB4
+ } while(0);
+ LBB3
+ L5: do {
switch (the_var) {
- LBB4 -> LBB5 {
- break;
- }
- default: {
- break L5;
- }
- }
- while(1) {
- LBB5
+ LBB3 -> LBB4 {
+ LBB4
switch (the_var) {
- LBB5 -> LBB6 {
- break L5;
+ LBB4 -> LBB5 {
break;
}
default: {
+ break L5;
+ }
}
+ while(1) {
+ LBB5
+ switch (the_var) {
+ LBB5 -> LBB6 {
+ break L5;
+ break;
+ }
+ default: {
+ }
+ }
}
+ break;
+ }
+ default: {
+ }
}
- break;
- }
- default: {
- }
- }
-} while(0);
-LBB6
+ } while(0);
+ LBB6
diff --git a/src/relooper/test4.txt b/src/relooper/test4.txt
index 1829e523..7e3fe8e1 100644
--- a/src/relooper/test4.txt
+++ b/src/relooper/test4.txt
@@ -1,44 +1,44 @@
-//19
-L1: do {
- switch (the_var) {
- 1 {
- //20
+ //19
+ L1: do {
switch (the_var) {
1 {
+ //20
+ switch (the_var) {
+ 1 {
+ break;
+ }
+ default: {
+ label = 4;
+ break L1;
+ }
+ }
+ //21
+ switch (the_var) {
+ default: {
+ }
+ }
break;
}
default: {
label = 4;
- break L1;
}
}
- //21
+ } while(0);
+ if (label == 4) {
+ //22
switch (the_var) {
default: {
}
}
- break;
- }
- default: {
- label = 4;
}
- }
-} while(0);
-if (label == 4) {
- //22
+ //23
switch (the_var) {
+ 1 {
+ //24
+ break;
+ }
default: {
+ //28
}
}
-}
-//23
-switch (the_var) {
- 1 {
- //24
- break;
-}
-default: {
- //28
-}
-}
diff --git a/src/relooper/test5.txt b/src/relooper/test5.txt
index 82ef5edf..e3c204f6 100644
--- a/src/relooper/test5.txt
+++ b/src/relooper/test5.txt
@@ -1,56 +1,56 @@
-//0
-switch (the_var) {
-check(0) {
- L2: while(1) {
- //1
- switch (the_var) {
- check(1) {
- break;
- }
- default: {
- break L2;
- }
- }
+ //0
+ switch (the_var) {
+ check(0) {
+ L2: while(1) {
+ //1
+ switch (the_var) {
+ check(1) {
+ break;
+ }
+ default: {
+ break L2;
+ }
+ }
+ }
+ L4: while(1) {
+ //2
+ switch (the_var) {
+ check(2) {
+ break;
+ }
+ default: {
+ break L4;
+ }
+ }
+ }
+ //3
+ break;
}
- L4: while(1) {
- //2
- switch (the_var) {
- check(2) {
- break;
- }
- default: {
- break L4;
- }
- }
+ default: {
+ goingFrom0to4();
+ L7: while(1) {
+ //4
+ switch (the_var) {
+ check(4) {
+ break;
+ }
+ default: {
+ break L7;
+ }
+ }
+ }
+ L9: while(1) {
+ //5
+ switch (the_var) {
+ check(5) {
+ break L9;
+ break;
+ }
+ default: {
+ }
+ }
+ }
+ //3
}
- //3
- break;
-}
-default: {
- goingFrom0to4();
- L7: while(1) {
- //4
- switch (the_var) {
- check(4) {
- break;
- }
- default: {
- break L7;
- }
- }
- }
- L9: while(1) {
- //5
- switch (the_var) {
- check(5) {
- break L9;
- break;
- }
- default: {
- }
- }
}
- //3
-}
-}
diff --git a/src/relooper/test6.txt b/src/relooper/test6.txt
index f9d6e93a..837fc243 100644
--- a/src/relooper/test6.txt
+++ b/src/relooper/test6.txt
@@ -1,26 +1,26 @@
-//0
-L1: do {
- switch (the_var) {
- check(0) {
- //1
+ //0
+ L1: do {
switch (the_var) {
- check(1) {
+ check(0) {
+ //1
+ switch (the_var) {
+ check(1) {
+ break;
+ }
+ default: {
+ break L1;
+ }
+ }
+ //2
+ switch (the_var) {
+ default: {
+ }
+ }
break;
}
default: {
- break L1;
}
}
- //2
- switch (the_var) {
- default: {
- }
- }
- break;
- }
- default: {
- }
- }
-} while(0);
-//3
+ } while(0);
+ //3
diff --git a/src/relooper/test_dead.txt b/src/relooper/test_dead.txt
index ae54e2cd..43d557ae 100644
--- a/src/relooper/test_dead.txt
+++ b/src/relooper/test_dead.txt
@@ -4,6 +4,6 @@
-// block A
+ // block A
I did not crash even though I have dead code with a branch!
diff --git a/src/relooper/test_debug.txt b/src/relooper/test_debug.txt
index eb33fdbc..498dee39 100644
--- a/src/relooper/test_debug.txt
+++ b/src/relooper/test_debug.txt
@@ -4,18 +4,18 @@ int main() {
rl_set_output_buffer(buffer);
void *block_map[10000];
void *rl = rl_new_relooper();
- void *b1 = rl_new_block("// code 1");
- block_map[1] = b1;
- rl_relooper_add_block(rl, block_map[1]);
- void *b2 = rl_new_block("// code 2");
- block_map[2] = b2;
- rl_relooper_add_block(rl, block_map[2]);
- void *b3 = rl_new_block("// code 3");
- block_map[3] = b3;
- rl_relooper_add_block(rl, block_map[3]);
- void *b4 = rl_new_block("// code 4");
- block_map[4] = b4;
- rl_relooper_add_block(rl, block_map[4]);
+ void *b-1 = rl_new_block("// code -1");
+ block_map[-1] = b-1;
+ rl_relooper_add_block(rl, block_map[-1]);
+ void *b-1 = rl_new_block("// code -1");
+ block_map[-1] = b-1;
+ rl_relooper_add_block(rl, block_map[-1]);
+ void *b-1 = rl_new_block("// code -1");
+ block_map[-1] = b-1;
+ rl_relooper_add_block(rl, block_map[-1]);
+ void *b-1 = rl_new_block("// code -1");
+ block_map[-1] = b-1;
+ rl_relooper_add_block(rl, block_map[-1]);
rl_block_add_branch_to(block_map[1], block_map[2], "ep -> LBB1", NULL);
rl_block_add_branch_to(block_map[1], block_map[4], NULL, NULL);
rl_block_add_branch_to(block_map[2], block_map[3], "LBB1 -> LBB2", NULL);
@@ -114,29 +114,29 @@ int main() {
// Process() returning
// === Optimizing shapes ===
// Fusing Multiple to Simple
-ep
-L1: do {
- switch (the_var) {
- ep -> LBB1 {
- LBB1
+ ep
+ L1: do {
switch (the_var) {
- LBB1 -> LBB2 {
+ ep -> LBB1 {
+ LBB1
+ switch (the_var) {
+ LBB1 -> LBB2 {
+ break;
+ }
+ default: {
+ break L1;
+ }
+ }
+ LBB2
+ switch (the_var) {
+ default: {
+ }
+ }
break;
}
default: {
- break L1;
}
}
- LBB2
- switch (the_var) {
- default: {
- }
- }
- break;
- }
- default: {
- }
- }
-} while(0);
-LBB3
+ } while(0);
+ LBB3
diff --git a/src/relooper/test_fuzz1.txt b/src/relooper/test_fuzz1.txt
index d887f5b8..ccd38934 100644
--- a/src/relooper/test_fuzz1.txt
+++ b/src/relooper/test_fuzz1.txt
@@ -1,72 +1,72 @@
-print('entry'); var label; var state; var decisions = [4, 1, 7, 2, 6, 6, 8]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
-switch (the_var) {
-default: {
-}
-}
-print(5); state = check();
-switch (the_var) {
-default: {
-}
-}
-print(6); state = check();
-switch (the_var) {
-state == 7 {
- print(7); state = check();
+ print('entry'); var label; var state; var decisions = [4, 1, 7, 2, 6, 6, 8]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
switch (the_var) {
default: {
- label = 3;
}
}
- break;
-}
-default: {
-}
-}
-L5: while(1) {
- if (label == 3) {
- label = 0;
- print(2); state = check();
+ print(5); state = check();
+ switch (the_var) {
+ default: {
+ }
+ }
+ print(6); state = check();
+ switch (the_var) {
+ state == 7 {
+ print(7); state = check();
switch (the_var) {
default: {
+ label = 3;
}
}
+ break;
}
- print(1); state = check();
- switch (the_var) {
default: {
}
}
- while(1) {
- print(3); state = check();
- switch (the_var) {
- state == 8 {
- break;
+ L5: while(1) {
+ if (label == 3) {
+ label = 0;
+ print(2); state = check();
+ switch (the_var) {
+ default: {
+ }
+ }
}
- default: {
- continue L5;
- }
- }
- print(8); state = check();
+ print(1); state = check();
switch (the_var) {
- state == 4 {
- break;
- }
default: {
- label = 3;
- continue L5;
}
}
- print(4); state = check();
- switch (the_var) {
- state == 3 {
- break;
- }
- default: {
- continue L5;
- }
+ while(1) {
+ print(3); state = check();
+ switch (the_var) {
+ state == 8 {
+ break;
+ }
+ default: {
+ continue L5;
+ }
+ }
+ print(8); state = check();
+ switch (the_var) {
+ state == 4 {
+ break;
+ }
+ default: {
+ label = 3;
+ continue L5;
+ }
+ }
+ print(4); state = check();
+ switch (the_var) {
+ state == 3 {
+ break;
+ }
+ default: {
+ continue L5;
+ }
+ }
}
}
-}
diff --git a/src/relooper/test_fuzz2.txt b/src/relooper/test_fuzz2.txt
index 69f4350c..a94908a1 100644
--- a/src/relooper/test_fuzz2.txt
+++ b/src/relooper/test_fuzz2.txt
@@ -1,30 +1,30 @@
-print('entry'); var label; var state; var decisions = [4, 1, 4, 3, 4, 1, 2, 5, 1, 3, 5, 5, 1, 5, 2, 4, 4, 3]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
-switch (the_var) {
-state == 1 {
- while(1) {
- print(1); state = check();
- switch (the_var) {
- default: {
- }
+ print('entry'); var label; var state; var decisions = [4, 1, 4, 3, 4, 1, 2, 5, 1, 3, 5, 5, 1, 5, 2, 4, 4, 3]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
+ switch (the_var) {
+ state == 1 {
+ while(1) {
+ print(1); state = check();
+ switch (the_var) {
+ default: {
+ }
+ }
}
+ break;
}
- break;
-}
-default: {
-}
-}
-while(1) {
- print(3); state = check();
- switch (the_var) {
default: {
}
}
- print(2); state = check();
- switch (the_var) {
- default: {
- }
+ while(1) {
+ print(3); state = check();
+ switch (the_var) {
+ default: {
+ }
+ }
+ print(2); state = check();
+ switch (the_var) {
+ default: {
+ }
+ }
}
-}
diff --git a/src/relooper/test_fuzz3.txt b/src/relooper/test_fuzz3.txt
index 398b4803..15037eec 100644
--- a/src/relooper/test_fuzz3.txt
+++ b/src/relooper/test_fuzz3.txt
@@ -1,25 +1,25 @@
-print('entry'); var label; var state; var decisions = [3, 3, 4, 1, 2, 1, 2, 4, 4, 4, 2, 3, 3, 1, 2]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
-switch (the_var) {
-default: {
-}
-}
-print(1); state = check();
-switch (the_var) {
-default: {
-}
-}
-print(3); state = check();
-switch (the_var) {
-default: {
-}
-}
-while(1) {
- print(4); state = check();
+ print('entry'); var label; var state; var decisions = [3, 3, 4, 1, 2, 1, 2, 4, 4, 4, 2, 3, 3, 1, 2]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
switch (the_var) {
default: {
}
}
-}
+ print(1); state = check();
+ switch (the_var) {
+ default: {
+ }
+ }
+ print(3); state = check();
+ switch (the_var) {
+ default: {
+ }
+ }
+ while(1) {
+ print(4); state = check();
+ switch (the_var) {
+ default: {
+ }
+ }
+ }
diff --git a/src/relooper/test_fuzz4.txt b/src/relooper/test_fuzz4.txt
index 2e2f2c6f..adf879f9 100644
--- a/src/relooper/test_fuzz4.txt
+++ b/src/relooper/test_fuzz4.txt
@@ -1,41 +1,41 @@
-print('entry'); var label; var state; var decisions = [2, 2, 1, 3, 2, 2, 1, 3, 2, 3, 3, 1, 3, 2, 1]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
-switch (the_var) {
-state == 2 {
- while(1) {
- print(2); state = check();
- switch (the_var) {
- default: {
- }
- }
- }
- break;
-}
-default: {
-}
-}
-L4: while(1) {
- print(4); state = check();
+ print('entry'); var label; var state; var decisions = [2, 2, 1, 3, 2, 2, 1, 3, 2, 3, 3, 1, 3, 2, 1]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
switch (the_var) {
- state == 4 {
+ state == 2 {
+ while(1) {
+ print(2); state = check();
+ switch (the_var) {
+ default: {
+ }
+ }
+ }
break;
}
default: {
- break L4;
}
}
-}
-print(3); state = check();
-switch (the_var) {
-default: {
-}
-}
-while(1) {
- print(1); state = check();
+ L4: while(1) {
+ print(4); state = check();
+ switch (the_var) {
+ state == 4 {
+ break;
+ }
+ default: {
+ break L4;
+ }
+ }
+ }
+ print(3); state = check();
switch (the_var) {
default: {
}
}
-}
+ while(1) {
+ print(1); state = check();
+ switch (the_var) {
+ default: {
+ }
+ }
+ }
diff --git a/src/relooper/test_fuzz5.txt b/src/relooper/test_fuzz5.txt
index f87e5b79..fea540ed 100644
--- a/src/relooper/test_fuzz5.txt
+++ b/src/relooper/test_fuzz5.txt
@@ -1,86 +1,86 @@
-print('entry'); var label; var state; var decisions = [133, 98, 134, 143, 162, 187, 130, 87, 91, 49, 102, 47, 9, 132, 179, 176, 157, 25, 64, 161, 57, 107, 16, 167, 185, 45, 191, 180, 23, 131]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
-switch (the_var) {
-default: {
-}
-}
-L1: while(1) {
- print(7); state = check();
+ print('entry'); var label; var state; var decisions = [133, 98, 134, 143, 162, 187, 130, 87, 91, 49, 102, 47, 9, 132, 179, 176, 157, 25, 64, 161, 57, 107, 16, 167, 185, 45, 191, 180, 23, 131]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
switch (the_var) {
- state % 3 == 1 {
- label = 3;
- break;
+ default: {
+ }
}
- state % 3 == 0 {
- print(8); state = check();
+ L1: while(1) {
+ print(7); state = check();
switch (the_var) {
- state % 2 == 0 {
- label = 5;
+ state % 3 == 1 {
+ label = 3;
break;
}
- default: {
- label = 7;
- }
- }
- break;
- }
- default: {
- break L1;
- }
- }
- L5: while(1) {
- if (label == 3) {
- label = 0;
- print(2); state = check();
- switch (the_var) {
- default: {
- }
- }
- print(1); state = check();
+ state % 3 == 0 {
+ print(8); state = check();
switch (the_var) {
state % 2 == 0 {
label = 5;
- continue L5;
break;
}
default: {
label = 7;
- continue L5;
}
}
+ break;
}
- else if (label == 5) {
- label = 0;
- print(4); state = check();
- switch (the_var) {
- default: {
- label = 3;
- continue L5;
- }
- }
+ default: {
+ break L1;
}
- else if (label == 7) {
- label = 0;
- print(6); state = check();
- switch (the_var) {
- state % 2 == 0 {
- continue L1;
- break;
+ }
+ L5: while(1) {
+ if (label == 3) {
+ label = 0;
+ print(2); state = check();
+ switch (the_var) {
+ default: {
+ }
+ }
+ print(1); state = check();
+ switch (the_var) {
+ state % 2 == 0 {
+ label = 5;
+ continue L5;
+ break;
+ }
+ default: {
+ label = 7;
+ continue L5;
+ }
+ }
}
- default: {
- label = 7;
- continue L5;
+ else if (label == 5) {
+ label = 0;
+ print(4); state = check();
+ switch (the_var) {
+ default: {
+ label = 3;
+ continue L5;
+ }
+ }
}
+ else if (label == 7) {
+ label = 0;
+ print(6); state = check();
+ switch (the_var) {
+ state % 2 == 0 {
+ continue L1;
+ break;
+ }
+ default: {
+ label = 7;
+ continue L5;
+ }
+ }
}
}
}
-}
-while(1) {
- print(3); state = check();
- switch (the_var) {
- default: {
- }
+ while(1) {
+ print(3); state = check();
+ switch (the_var) {
+ default: {
+ }
+ }
}
-}
diff --git a/src/relooper/test_fuzz6.txt b/src/relooper/test_fuzz6.txt
index b9c1499a..40605dfc 100644
--- a/src/relooper/test_fuzz6.txt
+++ b/src/relooper/test_fuzz6.txt
@@ -1,291 +1,291 @@
-print('entry'); var label; var state; var decisions = [759, 1223, 618, 1805, 277, 512, 204, 1545, 606, 734, 585, 447, 1670, 1031, 665, 1728, 353, 634, 1033, 13, 658, 589, 474, 854, 405, 1111, 1640, 697, 1156, 1357, 317, 618, 990, 1401, 405, 564, 497, 829, 653, 1194, 25, 322, 1178, 198, 1565, 1419, 1608, 486, 368, 606, 813, 22, 148, 141, 261, 375, 472, 964, 1106, 694, 205, 771, 44, 675, 545, 1027, 1528, 240, 1289, 564, 792, 744, 366, 668, 823, 210, 428, 1009, 1662, 1317, 1183, 681, 14, 1334, 712, 506, 224, 695, 401, 1035, 384, 486, 1519, 122, 1186, 1487, 1819, 1702, 463, 1706, 660, 1642, 847, 991, 976, 940, 867, 46, 23, 1449, 56, 1711, 634, 404, 1558, 168, 710, 1581, 1302, 870, 997, 1295, 1739, 769, 1005, 291, 1638, 1771, 842, 659, 1695, 713, 935, 802, 1173, 1572, 850, 607, 996, 55, 1576, 321, 1815, 662, 1044, 1612, 1680, 1050, 844, 553, 278, 1447, 1662, 1094, 1797, 774, 1013, 1204, 907, 340, 1172, 1460, 869, 1264, 111, 1176, 484, 845, 258, 417, 1246, 1017, 745, 189, 333, 1658, 1395, 1764, 1786, 165, 404, 847, 1429, 1574, 403, 718, 1118, 1756, 94, 56, 1498, 1696, 1355, 840, 50, 82, 371, 1087, 875, 1337, 267, 958, 1209, 1167, 1025, 1684, 184, 962, 1496, 201, 127, 372, 1, 1005, 402, 1387, 213, 1143, 1271, 167, 10, 12, 1060, 1390, 1366, 893, 747, 1005, 481, 876, 227, 514, 589, 250, 273, 1188, 1052, 719, 219, 1006, 38, 120, 1454, 489, 672, 149, 534, 1081, 1721, 586, 330, 25, 356, 1743, 1607, 336, 981, 419, 1036, 1293, 1026, 1300, 1453, 792, 22, 45, 420, 409, 1027, 1437, 1421, 795, 136, 1276, 1610, 1593]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
-switch (the_var) {
-default: {
-}
-}
-L1: while(1) {
- print(30); state = check();// .................................................................................................................................................................................................................
- switch (the_var) {
- state % 3 == 0 {
- break;
- }
- state % 3 == 1 {
- label = 67;
- break L1;
- break;
- }
- default: {
- break L1;
- }
- }
- print(58); state = check();// ......................................................................................
- switch (the_var) {
- default: {
- }
- }
-}
-if (label == 67) {
- print(66); state = check();// ...............................................................................................................
+ print('entry'); var label; var state; var decisions = [759, 1223, 618, 1805, 277, 512, 204, 1545, 606, 734, 585, 447, 1670, 1031, 665, 1728, 353, 634, 1033, 13, 658, 589, 474, 854, 405, 1111, 1640, 697, 1156, 1357, 317, 618, 990, 1401, 405, 564, 497, 829, 653, 1194, 25, 322, 1178, 198, 1565, 1419, 1608, 486, 368, 606, 813, 22, 148, 141, 261, 375, 472, 964, 1106, 694, 205, 771, 44, 675, 545, 1027, 1528, 240, 1289, 564, 792, 744, 366, 668, 823, 210, 428, 1009, 1662, 1317, 1183, 681, 14, 1334, 712, 506, 224, 695, 401, 1035, 384, 486, 1519, 122, 1186, 1487, 1819, 1702, 463, 1706, 660, 1642, 847, 991, 976, 940, 867, 46, 23, 1449, 56, 1711, 634, 404, 1558, 168, 710, 1581, 1302, 870, 997, 1295, 1739, 769, 1005, 291, 1638, 1771, 842, 659, 1695, 713, 935, 802, 1173, 1572, 850, 607, 996, 55, 1576, 321, 1815, 662, 1044, 1612, 1680, 1050, 844, 553, 278, 1447, 1662, 1094, 1797, 774, 1013, 1204, 907, 340, 1172, 1460, 869, 1264, 111, 1176, 484, 845, 258, 417, 1246, 1017, 745, 189, 333, 1658, 1395, 1764, 1786, 165, 404, 847, 1429, 1574, 403, 718, 1118, 1756, 94, 56, 1498, 1696, 1355, 840, 50, 82, 371, 1087, 875, 1337, 267, 958, 1209, 1167, 1025, 1684, 184, 962, 1496, 201, 127, 372, 1, 1005, 402, 1387, 213, 1143, 1271, 167, 10, 12, 1060, 1390, 1366, 893, 747, 1005, 481, 876, 227, 514, 589, 250, 273, 1188, 1052, 719, 219, 1006, 38, 120, 1454, 489, 672, 149, 534, 1081, 1721, 586, 330, 25, 356, 1743, 1607, 336, 981, 419, 1036, 1293, 1026, 1300, 1453, 792, 22, 45, 420, 409, 1027, 1437, 1421, 795, 136, 1276, 1610, 1593]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }
switch (the_var) {
default: {
}
}
-}
-print(6); state = check();// .........
-switch (the_var) {
-default: {
-}
-}
-while(1) {
- print(88); state = check();// ....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
- switch (the_var) {
- default: {
+ L1: while(1) {
+ print(30); state = check();// .................................................................................................................................................................................................................
+ switch (the_var) {
+ state % 3 == 0 {
+ break;
+ }
+ state % 3 == 1 {
+ label = 67;
+ break L1;
+ break;
+ }
+ default: {
+ break L1;
+ }
+ }
+ print(58); state = check();// ......................................................................................
+ switch (the_var) {
+ default: {
+ }
+ }
}
+ if (label == 67) {
+ print(66); state = check();// ...............................................................................................................
+ switch (the_var) {
+ default: {
+ }
+ }
}
- print(70); state = check();// ..........................................................................................................................
+ print(6); state = check();// .........
switch (the_var) {
default: {
}
}
- L10: while(1) {
- print(47); state = check();// ....................................................................................................................................
+ while(1) {
+ print(88); state = check();// ....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
switch (the_var) {
default: {
}
}
- print(28); state = check();// ..............................................................................................................
+ print(70); state = check();// ..........................................................................................................................
switch (the_var) {
default: {
}
}
- L13: while(1) {
- print(75); state = check();// .............................................
+ L10: while(1) {
+ print(47); state = check();// ....................................................................................................................................
switch (the_var) {
default: {
}
}
- print(7); state = check();// .............................................................................................................................................................................................
+ print(28); state = check();// ..............................................................................................................
switch (the_var) {
- state % 2 == 0 {
- break;
- }
default: {
- break L13;
- }
}
- }
- print(89); state = check();// ......................................................................................................................................................................................................................................................................................................................................................
- switch (the_var) {
- default: {
- }
- }
- print(68); state = check();// ......................................................................................................................................................................................................................................................................................................................
- switch (the_var) {
- default: {
- }
- }
- L18: while(1) {
- print(51); state = check();// .............................................................................................
- switch (the_var) {
- default: {
}
- }
- L20: while(1) {
- print(36); state = check();// .........................
+ L13: while(1) {
+ print(75); state = check();// .............................................
switch (the_var) {
- state % 2 == 0 {
- break L20;
- break;
- }
default: {
}
}
- print(16); state = check();// ................................................................................................................................................................................................................................................................................................................................................................
+ print(7); state = check();// .............................................................................................................................................................................................
switch (the_var) {
- default: {
- }
+ state % 2 == 0 {
+ break;
}
- print(57); state = check();// ...........................................................................................................................................................................................................................................................................................................................
- switch (the_var) {
default: {
+ break L13;
}
}
- print(39); state = check();// ................
+ }
+ print(89); state = check();// ......................................................................................................................................................................................................................................................................................................................................................
+ switch (the_var) {
+ default: {
+ }
+ }
+ print(68); state = check();// ......................................................................................................................................................................................................................................................................................................................
+ switch (the_var) {
+ default: {
+ }
+ }
+ L18: while(1) {
+ print(51); state = check();// .............................................................................................
switch (the_var) {
- state % 3 == 0 {
- break;
- }
- state % 3 == 1 {
- label = 74;
- break;
- }
default: {
- label = 32;
- break L20;
}
}
- L25: while(1) {
- if (label == 74) {
- label = 0;
- print(73); state = check();// .
+ L20: while(1) {
+ print(36); state = check();// .........................
+ switch (the_var) {
+ state % 2 == 0 {
+ break L20;
+ break;
+ }
+ default: {
+ }
+ }
+ print(16); state = check();// ................................................................................................................................................................................................................................................................................................................................................................
+ switch (the_var) {
+ default: {
+ }
+ }
+ print(57); state = check();// ...........................................................................................................................................................................................................................................................................................................................
+ switch (the_var) {
+ default: {
+ }
+ }
+ print(39); state = check();// ................
+ switch (the_var) {
+ state % 3 == 0 {
+ break;
+ }
+ state % 3 == 1 {
+ label = 74;
+ break;
+ }
+ default: {
+ label = 32;
+ break L20;
+ }
+ }
+ L25: while(1) {
+ if (label == 74) {
+ label = 0;
+ print(73); state = check();// .
+ switch (the_var) {
+ state % 3 == 1 {
+ label = 32;
+ break L20;
+ break;
+ }
+ state % 3 == 0 {
+ break L25;
+ break;
+ }
+ default: {
+ }
+ }
+ print(43); state = check();// .........
+ switch (the_var) {
+ default: {
+ }
+ }
+ print(32); state = check();// ......................................................................................................
+ switch (the_var) {
+ default: {
+ }
+ }
+ print(83); state = check();// ........................................................................................
+ switch (the_var) {
+ default: {
+ }
+ }
+ print(77); state = check();// ...........................................................................................................................................................................................................................................................................................
+ switch (the_var) {
+ default: {
+ }
+ }
+ print(76); state = check();// ..............................................................................................................................................................................................................................................................................................................................................................................................................................
+ switch (the_var) {
+ default: {
+ }
+ }
+ print(22); state = check();// .........................................................................................................
+ switch (the_var) {
+ default: {
+ }
+ }
+ }
+ print(72); state = check();// ..........................................................................................................
switch (the_var) {
- state % 3 == 1 {
- label = 32;
+ state % 2 == 0 {
+ label = 92;
break L20;
break;
}
- state % 3 == 0 {
- break L25;
+ default: {
+ }
+ }
+ print(80); state = check();// ....................................
+ switch (the_var) {
+ state % 2 == 0 {
+ continue L18;
break;
}
default: {
}
}
- print(43); state = check();// .........
+ print(50); state = check();// ........................................
switch (the_var) {
default: {
}
}
- print(32); state = check();// ......................................................................................................
+ print(29); state = check();// ...............
switch (the_var) {
default: {
}
}
- print(83); state = check();// ........................................................................................
+ print(8); state = check();// ....................................................................................................................................................................................................................................................
switch (the_var) {
+ state % 2 == 0 {
+ continue L10;
+ break;
+ }
default: {
}
}
- print(77); state = check();// ...........................................................................................................................................................................................................................................................................................
+ print(19); state = check();// ......................................................................................................................................................................................................................
switch (the_var) {
default: {
}
}
- print(76); state = check();// ..............................................................................................................................................................................................................................................................................................................................................................................................................................
+ print(56); state = check();// ....................................................................................................................................................................................................................
switch (the_var) {
default: {
}
}
- print(22); state = check();// .........................................................................................................
+ print(34); state = check();// ..........................................................................................................................................
switch (the_var) {
default: {
+ label = 74;
}
}
}
- print(72); state = check();// ..........................................................................................................
- switch (the_var) {
- state % 2 == 0 {
- label = 92;
- break L20;
- break;
- }
- default: {
- }
- }
- print(80); state = check();// ....................................
- switch (the_var) {
- state % 2 == 0 {
- continue L18;
- break;
- }
- default: {
- }
- }
- print(50); state = check();// ........................................
- switch (the_var) {
- default: {
- }
- }
- print(29); state = check();// ...............
- switch (the_var) {
- default: {
- }
- }
- print(8); state = check();// ....................................................................................................................................................................................................................................................
+ print(62); state = check();// .......................................................................................
switch (the_var) {
- state % 2 == 0 {
- continue L10;
- break;
- }
default: {
}
}
- print(19); state = check();// ......................................................................................................................................................................................................................
+ }
+ if (label == 32) {
+ label = 0;
+ print(31); state = check();// ..........................................................................................................................................................................................................
switch (the_var) {
default: {
}
}
- print(56); state = check();// ....................................................................................................................................................................................................................
+ }
+ else if (label == 92) {
+ label = 0;
+ print(91); state = check();// ..............................................
switch (the_var) {
default: {
}
}
- print(34); state = check();// ..........................................................................................................................................
+ print(33); state = check();// ....
switch (the_var) {
default: {
- label = 74;
}
}
}
- print(62); state = check();// .......................................................................................
+ print(60); state = check();// ......................................................................................................................................................................................................................................
switch (the_var) {
default: {
}
}
- }
- if (label == 32) {
- label = 0;
- print(31); state = check();// ..........................................................................................................................................................................................................
+ print(10); state = check();// ...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
switch (the_var) {
default: {
}
}
- }
- else if (label == 92) {
- label = 0;
- print(91); state = check();// ..............................................
+ print(52); state = check();// ..............................................................................
switch (the_var) {
+ state % 2 == 0 {
+ break L10;
+ break;
+ }
default: {
}
}
- print(33); state = check();// ....
+ print(2); state = check();// .........
switch (the_var) {
default: {
}
}
}
- print(60); state = check();// ......................................................................................................................................................................................................................................
- switch (the_var) {
- default: {
- }
- }
- print(10); state = check();// ...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
- switch (the_var) {
- default: {
- }
- }
- print(52); state = check();// ..............................................................................
- switch (the_var) {
- state % 2 == 0 {
- break L10;
- break;
- }
- default: {
- }
- }
- print(2); state = check();// .........
- switch (the_var) {
- default: {
- }
- }
+ }
+ print(61); state = check();// .........................................................................................................................................................
+ switch (the_var) {
+ default: {
+ }
}
}
- print(61); state = check();// .........................................................................................................................................................
- switch (the_var) {
- default: {
- }
- }
-}
diff --git a/src/relooper/test_inf.txt b/src/relooper/test_inf.txt
index 6db32edb..2acadbfb 100644
--- a/src/relooper/test_inf.txt
+++ b/src/relooper/test_inf.txt
@@ -1,1072 +1,1039 @@
-code 0
-switch (the_var) {
-uint(i4) >= uint(i5) {
- code 2
+ code 0
switch (the_var) {
- default: {
- }
- }
- break;
-}
-default: {
- code 1
- switch (the_var) {
- default: {
- }
- }
-}
-}
-code 3
-L5: do {
- switch (the_var) {
- i2 == 0 {
+ uint(i4) >= uint(i5) {
+ code 2
+ switch (the_var) {
+ default: {
+ }
+ }
break;
}
default: {
- code 4
+ code 1
switch (the_var) {
default: {
}
}
- while(1) {
- code 5
+ }
+ }
+ code 3
+ L5: do {
+ switch (the_var) {
+ i2 == 0 {
+ break;
+ }
+ default: {
+ code 4
switch (the_var) {
- uint(i6) >= uint(i7) {
- code 7
- switch (the_var) {
- default: {
- }
- }
- break;
- }
default: {
- code 6
- switch (the_var) {
- default: {
- }
- }
}
}
- code 8
- switch (the_var) {
- uint(i6) >= uint(i7) {
- code 10
+ while(1) {
+ code 5
switch (the_var) {
+ uint(i6) >= uint(i7) {
+ code 7
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
+ }
default: {
+ code 6
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- break;
- }
- default: {
- code 9
+ code 8
switch (the_var) {
+ uint(i6) >= uint(i7) {
+ code 10
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
+ }
default: {
+ code 9
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 11
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 13
+ code 11
switch (the_var) {
+ uint(i5) >= uint(i6) {
+ code 13
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
+ }
default: {
+ code 12
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- break;
- }
- default: {
- code 12
+ code 14
switch (the_var) {
+ i2 != 0 {
+ break;
+ }
default: {
+ break L5;
}
}
}
- }
- code 14
- switch (the_var) {
- i2 != 0 {
- break;
- }
- default: {
- break L5;
- }
- }
}
- }
- }
-} while(0);
-code 15
-switch (the_var) {
-uint(i4) >= uint(i5) {
- code 17
- switch (the_var) {
- default: {
- }
- }
- break;
-}
-default: {
- code 16
- switch (the_var) {
- default: {
- }
- }
-}
-}
-code 18
-L26: do {
+ }
+ } while(0);
+ code 15
switch (the_var) {
- i2 == 0 {
+ uint(i4) >= uint(i5) {
+ code 17
+ switch (the_var) {
+ default: {
+ }
+ }
break;
}
default: {
- code 19
+ code 16
switch (the_var) {
default: {
}
}
- while(1) {
- code 20
+ }
+ }
+ code 18
+ L26: do {
+ switch (the_var) {
+ i2 == 0 {
+ break;
+ }
+ default: {
+ code 19
switch (the_var) {
- uint(i5) >= uint(i6) {
- code 22
- switch (the_var) {
- default: {
- }
- }
- break;
- }
default: {
- code 21
- switch (the_var) {
- default: {
- }
- }
}
}
- code 23
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 25
+ while(1) {
+ code 20
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 22
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 24
- switch (the_var) {
default: {
+ code 21
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 26
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 28
+ code 23
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 25
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 27
- switch (the_var) {
default: {
+ code 24
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 29
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 31
+ code 26
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 28
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 30
- switch (the_var) {
default: {
+ code 27
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 32
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 34
+ code 29
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 31
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 33
- switch (the_var) {
default: {
+ code 30
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 35
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 37
+ code 32
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 34
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 36
- switch (the_var) {
default: {
+ code 33
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 38
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 40
+ code 35
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 37
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 39
- switch (the_var) {
default: {
+ code 36
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 41
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 43
+ code 38
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 40
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 42
- switch (the_var) {
default: {
+ code 39
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 44
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 46
+ code 41
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 43
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 45
- switch (the_var) {
default: {
+ code 42
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 47
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 49
+ code 44
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 46
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 48
- switch (the_var) {
default: {
+ code 45
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 50
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 52
+ code 47
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 49
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 51
- switch (the_var) {
default: {
+ code 48
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 53
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 55
+ code 50
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 52
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 54
- switch (the_var) {
default: {
+ code 51
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 56
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 58
+ code 53
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 55
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 57
- switch (the_var) {
default: {
+ code 54
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 59
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 61
+ code 56
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 58
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 60
- switch (the_var) {
default: {
+ code 57
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 62
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 64
+ code 59
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 61
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 63
- switch (the_var) {
default: {
+ code 60
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 65
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 67
+ code 62
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 64
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 66
- switch (the_var) {
default: {
+ code 63
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 68
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 70
+ code 65
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 67
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 69
- switch (the_var) {
default: {
+ code 66
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 71
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 73
+ code 68
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 70
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 72
- switch (the_var) {
default: {
+ code 69
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 74
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 76
+ code 71
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 73
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 75
- switch (the_var) {
default: {
+ code 72
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 77
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 79
+ code 74
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 76
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 78
- switch (the_var) {
default: {
+ code 75
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 80
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 82
+ code 77
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 79
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 81
- switch (the_var) {
default: {
+ code 78
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 83
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 85
+ code 80
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 82
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 84
- switch (the_var) {
default: {
+ code 81
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 86
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 88
+ code 83
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 85
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 87
- switch (the_var) {
default: {
+ code 84
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 89
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 91
+ code 86
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 88
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 90
- switch (the_var) {
default: {
+ code 87
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 92
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 94
+ code 89
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 91
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 93
- switch (the_var) {
default: {
+ code 90
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 95
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 97
+ code 92
switch (the_var) {
+ uint(i5) >= uint(i6) {
+ code 94
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
+ }
default: {
+ code 93
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- break;
- }
- default: {
- code 96
+ code 95
switch (the_var) {
+ uint(i5) >= uint(i6) {
+ code 97
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
+ }
default: {
+ code 96
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 98
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 100
+ code 98
switch (the_var) {
+ uint(i5) >= uint(i6) {
+ code 100
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
+ }
default: {
+ code 99
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- break;
- }
- default: {
- code 99
+ code 101
switch (the_var) {
+ i2 != 0 {
+ break;
+ }
default: {
+ break L26;
}
}
}
- }
- code 101
- switch (the_var) {
- i2 != 0 {
- break;
- }
- default: {
- break L26;
- }
- }
}
- }
- }
-} while(0);
-code 102
-switch (the_var) {
-uint(i4) >= uint(i5) {
- code 104
- switch (the_var) {
- default: {
- }
- }
- break;
-}
-default: {
- code 103
- switch (the_var) {
- default: {
- }
- }
-}
-}
-code 105
-L143: do {
+ }
+ } while(0);
+ code 102
switch (the_var) {
- i2 == 0 {
+ uint(i4) >= uint(i5) {
+ code 104
+ switch (the_var) {
+ default: {
+ }
+ }
break;
}
default: {
- code 106
+ code 103
switch (the_var) {
default: {
}
}
- while(1) {
- code 107
+ }
+ }
+ code 105
+ L143: do {
+ switch (the_var) {
+ i2 == 0 {
+ break;
+ }
+ default: {
+ code 106
switch (the_var) {
- uint(i5) >= uint(i6) {
- code 109
- switch (the_var) {
- default: {
- }
- }
- break;
- }
default: {
- code 108
- switch (the_var) {
- default: {
- }
- }
}
}
- code 110
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 112
+ while(1) {
+ code 107
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 109
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 111
- switch (the_var) {
default: {
+ code 108
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 113
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 115
+ code 110
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 112
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 114
- switch (the_var) {
default: {
+ code 111
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 116
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 118
+ code 113
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 115
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 117
- switch (the_var) {
default: {
+ code 114
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 119
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 121
+ code 116
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 118
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 120
- switch (the_var) {
default: {
+ code 117
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 122
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 124
+ code 119
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 121
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 123
- switch (the_var) {
default: {
+ code 120
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 125
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 127
+ code 122
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 124
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 126
- switch (the_var) {
default: {
+ code 123
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 128
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 130
+ code 125
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 127
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 129
- switch (the_var) {
default: {
+ code 126
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 131
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 133
+ code 128
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 130
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 132
- switch (the_var) {
default: {
+ code 129
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 134
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 136
+ code 131
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 133
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 135
- switch (the_var) {
default: {
+ code 132
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 137
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 139
+ code 134
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 136
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 138
- switch (the_var) {
default: {
+ code 135
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 140
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 142
+ code 137
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 139
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 141
- switch (the_var) {
default: {
+ code 138
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 143
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 145
+ code 140
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 142
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 144
- switch (the_var) {
default: {
+ code 141
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 146
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 148
+ code 143
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 145
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 147
- switch (the_var) {
default: {
+ code 144
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 149
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 151
+ code 146
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 148
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 150
- switch (the_var) {
default: {
+ code 147
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 152
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 154
+ code 149
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 151
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 153
- switch (the_var) {
default: {
+ code 150
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 155
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 157
+ code 152
switch (the_var) {
- default: {
+ uint(i5) >= uint(i6) {
+ code 154
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- }
- break;
- }
- default: {
- code 156
- switch (the_var) {
default: {
+ code 153
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 158
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 160
+ code 155
switch (the_var) {
- default: {
- }
+ uint(i5) >= uint(i6) {
+ code 157
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
}
- break;
- }
- default: {
- code 159
- switch (the_var) {
default: {
+ code 156
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 161
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 163
+ code 158
switch (the_var) {
+ uint(i5) >= uint(i6) {
+ code 160
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
+ }
default: {
+ code 159
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- break;
- }
- default: {
- code 162
+ code 161
switch (the_var) {
+ uint(i5) >= uint(i6) {
+ code 163
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
+ }
default: {
+ code 162
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 164
- switch (the_var) {
- uint(i5) >= uint(i6) {
- code 166
+ code 164
switch (the_var) {
+ uint(i5) >= uint(i6) {
+ code 166
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
+ }
default: {
+ code 165
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- break;
- }
- default: {
- code 165
+ code 167
switch (the_var) {
+ i2 != 0 {
+ break;
+ }
default: {
+ break L143;
}
}
}
- }
- code 167
- switch (the_var) {
- i2 != 0 {
- break;
- }
- default: {
- break L143;
- }
- }
}
- }
- }
-} while(0);
-code 168
-switch (the_var) {
-uint(i4) >= uint(i5) {
- code 170
- switch (the_var) {
- default: {
- }
- }
- break;
-}
-default: {
- code 169
- switch (the_var) {
- default: {
- }
- }
-}
-}
-code 171
-switch (the_var) {
-i2 == 0 {
- code 183
- break;
-}
-default: {
-}
-}
-code 172
-switch (the_var) {
-default: {
-}
-}
-L235: while(1) {
- code 173
+ }
+ } while(0);
+ code 168
switch (the_var) {
- uint(i5) >= uint(i6) {
- code 175
+ uint(i4) >= uint(i5) {
+ code 170
switch (the_var) {
default: {
}
@@ -1074,58 +1041,91 @@ L235: while(1) {
break;
}
default: {
- code 174
+ code 169
switch (the_var) {
default: {
}
}
}
}
- code 176
+ code 171
+ switch (the_var) {
+ i2 == 0 {
+ code 183
+ break;
+ }
+ default: {
+ }
+ }
+ code 172
switch (the_var) {
- uint(i5) >= uint(i6) {
- code 178
+ default: {
+ }
+ }
+ L235: while(1) {
+ code 173
switch (the_var) {
+ uint(i5) >= uint(i6) {
+ code 175
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
+ }
default: {
+ code 174
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- break;
- }
- default: {
- code 177
+ code 176
switch (the_var) {
+ uint(i5) >= uint(i6) {
+ code 178
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
+ }
default: {
+ code 177
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- }
- }
- code 179
- switch (the_var) {
- uint(i4) >= uint(i5) {
- code 181
+ code 179
switch (the_var) {
+ uint(i4) >= uint(i5) {
+ code 181
+ switch (the_var) {
+ default: {
+ }
+ }
+ break;
+ }
default: {
+ code 180
+ switch (the_var) {
+ default: {
+ }
+ }
}
}
- break;
- }
- default: {
- code 180
+ code 182
switch (the_var) {
+ i2 != 0 {
+ break;
+ }
default: {
+ break L235;
}
}
}
- }
- code 182
- switch (the_var) {
- i2 != 0 {
- break;
- }
- default: {
- break L235;
- }
- }
-}
-code 183
+ code 183
diff --git a/src/relooper/testit.sh b/src/relooper/testit.sh
index 88db35fb..6e984b5a 100755
--- a/src/relooper/testit.sh
+++ b/src/relooper/testit.sh
@@ -2,61 +2,61 @@
echo "test"
./test &> test.out
-diff -U 5 test.txt test.out
+diff -w -U 5 test.txt test.out
echo "test 2"
./test2 &> test2.out
-diff -U 5 test2.txt test2.out
+diff -w -U 5 test2.txt test2.out
echo "test 3"
./test3 &> test3.out
-diff -U 5 test3.txt test3.out
+diff -w -U 5 test3.txt test3.out
echo "test debug"
./test_debug &> test_debug.out
-diff -U 5 test_debug.txt test_debug.out
+diff -w -U 5 test_debug.txt test_debug.out
echo "test dead"
./test_dead &> test_dead.out
-diff -U 5 test_dead.txt test_dead.out
+diff -w -U 5 test_dead.txt test_dead.out
echo "test 4"
./test4 &> test4.out
-diff -U 5 test4.txt test4.out
+diff -w -U 5 test4.txt test4.out
echo "test 5"
./test5 &> test5.out
-diff -U 5 test5.txt test5.out
+diff -w -U 5 test5.txt test5.out
echo "test 6"
./test6 &> test6.out
-diff -U 5 test6.txt test6.out
+diff -w -U 5 test6.txt test6.out
echo "test inf"
./test_inf &> test_inf.out
-diff -U 5 test_inf.txt test_inf.out
+diff -w -U 5 test_inf.txt test_inf.out
echo "test fuzz1"
./test_fuzz1 &> test_fuzz1.out
-diff -U 5 test_fuzz1.txt test_fuzz1.out
+diff -w -U 5 test_fuzz1.txt test_fuzz1.out
echo "test fuzz2"
./test_fuzz2 &> test_fuzz2.out
-diff -U 5 test_fuzz2.txt test_fuzz2.out
+diff -w -U 5 test_fuzz2.txt test_fuzz2.out
echo "test fuzz3"
./test_fuzz3 &> test_fuzz3.out
-diff -U 5 test_fuzz3.txt test_fuzz3.out
+diff -w -U 5 test_fuzz3.txt test_fuzz3.out
echo "test fuzz4"
./test_fuzz4 &> test_fuzz4.out
-diff -U 5 test_fuzz4.txt test_fuzz4.out
+diff -w -U 5 test_fuzz4.txt test_fuzz4.out
echo "test fuzz5"
./test_fuzz5 &> test_fuzz5.out
-diff -U 5 test_fuzz5.txt test_fuzz5.out
+diff -w -U 5 test_fuzz5.txt test_fuzz5.out
echo "test fuzz6"
./test_fuzz6 &> test_fuzz6.out
-diff -U 5 test_fuzz6.txt test_fuzz6.out
+diff -w -U 5 test_fuzz6.txt test_fuzz6.out
diff --git a/src/runtime.js b/src/runtime.js
index 8ba5d08d..cd3afb4b 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -250,7 +250,7 @@ var Runtime = {
prev = curr;
return curr;
});
- if (type.name_[0] === '[') {
+ if (type.name_ && type.name_[0] === '[') {
// arrays have 2 elements, so we get the proper difference. then we scale here. that way we avoid
// allocating a potentially huge array for [999999 x i8] etc.
type.flatSize = parseInt(type.name_.substr(1))*type.flatSize/2;
diff --git a/tests/aniso.c b/tests/aniso.c
index f1674cad..443e50aa 100644
--- a/tests/aniso.c
+++ b/tests/aniso.c
@@ -151,6 +151,11 @@ int main(int argc, char *argv[])
assert(!glGetError());
glBindFramebuffer(GL_RENDERBUFFER, 0);
assert(glGetError());
+
+ GLint out = 321;
+ assert(!glGetError());
+ glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &out); // invalid, just test output
+ assert(out == 0);
}
// Prepare and Render
diff --git a/tests/cases/longjmp_tiny_invoke_phi.ll b/tests/cases/longjmp_tiny_invoke_phi.ll
new file mode 100644
index 00000000..30c43339
--- /dev/null
+++ b/tests/cases/longjmp_tiny_invoke_phi.ll
@@ -0,0 +1,46 @@
+; ModuleID = '/tmp/emscripten_temp/src.cpp.o'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+@_ZL3buf = internal global [20 x i16] zeroinitializer, align 2
+@.str = private unnamed_addr constant [13 x i8] c"hello world\0A\00", align 1
+@.str1 = private unnamed_addr constant [6 x i8] c"more\0A\00", align 1
+@.str2 = private unnamed_addr constant [6 x i8] c"fair\0A\00", align 1
+
+define i32 @main() {
+entry:
+ %retval = alloca i32, align 4
+ store i32 0, i32* %retval
+ %call = invoke i32 @setjmp(i16* getelementptr inbounds ([20 x i16]* @_ZL3buf, i32 0, i32 0)) returns_twice
+ to label %allgood unwind label %awful
+
+allgood:
+ %p = phi i32 [0, %entry], [1, %if.else]
+ %calll = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([6 x i8]* @.str2, i32 0, i32 0))
+ %total = add i32 %p, %call
+ %tobool = icmp ne i32 %total, 10
+ br i1 %tobool, label %if.then, label %if.else
+
+if.then: ; preds = %entry
+ %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([13 x i8]* @.str, i32 0, i32 0))
+ call void @longjmp(i16* getelementptr inbounds ([20 x i16]* @_ZL3buf, i32 0, i32 0), i32 10)
+ br label %if.end
+
+if.else: ; preds = %entry
+ %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([6 x i8]* @.str1, i32 0, i32 0))
+ %chak = icmp ne i32 %call2, 1337
+ br i1 %chak, label %if.end, label %allgood
+
+if.end: ; preds = %if.else, %if.then
+ ret i32 0
+
+awful:
+ ret i32 1
+}
+
+declare i32 @setjmp(i16*) returns_twice
+
+declare i32 @printf(i8*, ...)
+
+declare void @longjmp(i16*, i32)
+
diff --git a/tests/cases/longjmp_tiny_invoke_phi.txt b/tests/cases/longjmp_tiny_invoke_phi.txt
new file mode 100644
index 00000000..aaa41d11
--- /dev/null
+++ b/tests/cases/longjmp_tiny_invoke_phi.txt
@@ -0,0 +1,4 @@
+fair
+hello world
+fair
+more
diff --git a/tests/core/closebitcasts.c b/tests/core/closebitcasts.c
new file mode 100644
index 00000000..2c9d5ab5
--- /dev/null
+++ b/tests/core/closebitcasts.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+
+int main(int argc, char **argv) {
+ float x = argc%17, y = (argc+1)*(argc+2)*(argc+3)*(argc+4)*(argc*5);
+ y *= 1<<30;
+ y *= -13;
+ if (argc == 17) { x++; y--; }
+ int *xi = (int*)&x;
+ int *yi = (int*)&y;
+ int z = *xi - *yi;
+ while (z % 15) {
+ z++;
+ }
+ printf("!%d\n", z);
+
+ double xd = x, yd = y;
+ yd = yd*yd;
+ yd = yd*yd;
+ int *xl = (int*)&xd;
+ int *xh = &((int*)&xd)[1];
+ int *yl = (int*)&yd;
+ int *yh = &((int*)&yd)[1];
+ int l = *xl - *yl;
+ int h = *xh - *yh;
+ while (l % 15) {
+ l++;
+ h += 3;
+ }
+ printf("%d,%d!\n", l, h);
+ return 0;
+}
+
diff --git a/tests/core/closebitcasts.txt b/tests/core/closebitcasts.txt
new file mode 100644
index 00000000..f97366cd
--- /dev/null
+++ b/tests/core/closebitcasts.txt
@@ -0,0 +1,2 @@
+!1787576325
+589815810,-179981561!
diff --git a/tests/cubegeom.c b/tests/cubegeom.c
index 96d56339..e749045b 100644
--- a/tests/cubegeom.c
+++ b/tests/cubegeom.c
@@ -54,9 +54,21 @@ int main(int argc, char *argv[])
// Create a texture
+ GLuint boundTex = 123;
+ assert(!glGetError());
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex);
+ assert(!glGetError());
+ assert(boundTex == 0);
+
GLuint texture;
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
+
+ assert(!glGetError());
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex);
+ assert(!glGetError());
+ assert(boundTex == texture);
+
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
GLubyte textureData[16*16*4];
diff --git a/tests/fuzz/test.sh b/tests/fuzz/test.sh
index cc77dba4..166d4bab 100755
--- a/tests/fuzz/test.sh
+++ b/tests/fuzz/test.sh
@@ -2,22 +2,38 @@
# ~/Dev/emscripten/tests/fuzz$ CSMITH=~/Dev/csmith/src/csmith CSMITH_PATH=~/Dev/csmith python ./csmith_driver.py
# to find failures, then check those out with this script
-echo "0"
-gcc $1 -I/home/alon/Dev/csmith/runtime &> /dev/null
-~/Dev/emscripten/emcc $1 -I/home/alon/Dev/csmith/runtime &> /dev/null
-./a.out > o
-mozjs a.out.js > b
-diff o b
-echo "1"
-gcc -O1 $1 -I/home/alon/Dev/csmith/runtime &> /dev/null
-~/Dev/emscripten/emcc -O1 $1 -I/home/alon/Dev/csmith/runtime &> /dev/null
-./a.out > o
-mozjs a.out.js > b
-diff o b
-echo "2"
-gcc -O2 $1 -I/home/alon/Dev/csmith/runtime &> /dev/null
-~/Dev/emscripten/emcc -O2 $1 -I/home/alon/Dev/csmith/runtime &> /dev/null
-./a.out > o
-mozjs a.out.js > b
-diff o b
+echo "builds"
+gcc $@ -I/home/alon/Dev/csmith/runtime -o n1.out &> /dev/null
+/home/alon/Dev/fastcomp/build/Release/bin/clang $@ -I/home/alon/Dev/csmith/runtime -o n2.out &> /dev/null
+/home/alon/Dev/fastcomp/build/Release/bin/clang $@ -I/home/alon/Dev/csmith/runtime -emit-llvm -c -o bc.bc &> o
+~/Dev/emscripten/emcc $@ -I/home/alon/Dev/csmith/runtime -o js.out.js &> /dev/null
+#~/Dev/emscripten/emcc $@ -s UNALIGNED_MEMORY=1 -I/home/alon/Dev/csmith/runtime -o ua.out.js &> /dev/null
+#~/Dev/emscripten/emcc $@ -s SAFE_HEAP=1 -I/home/alon/Dev/csmith/runtime -o sh.out.js &> /dev/null
+EMCC_FAST_COMPILER=1 ~/Dev/emscripten/emcc $@ -I/home/alon/Dev/csmith/runtime -o fc.out.js &> /dev/null
+echo "run n1"
+./n1.out &> n1
+echo "run n2"
+./n2.out &> n2
+echo "run bc"
+/home/alon/Dev/fastcomp/build/Release/bin/lli bc.bc &> bc
+echo "run js"
+mozjs js.out.js &> js
+echo "run ua"
+#mozjs ua.out.js &> ua
+echo "run sh"
+#mozjs sh.out.js &> sh
+echo "run fc"
+mozjs fc.out.js &> fc
+echo "n/n"
+diff n1 n2
+echo "n/bc"
+diff n1 bc
+echo "n/js"
+diff n1 js | grep -v warning
+echo "n/js-ua"
+#diff n1 ua | grep -v warning
+echo "n/js-sh"
+#diff n1 sh | grep -v warning
+echo "js/js"
+diff js fc | grep -v warning
diff --git a/tests/runner.py b/tests/runner.py
index 37e307e9..72e940cb 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -649,6 +649,7 @@ class BrowserCore(RunnerCore):
def btest(self, filename, expected=None, reference=None, force_c=False, reference_slack=0, manual_reference=False, post_build=None,
args=[], outfile='test.html', message='.'): # TODO: use in all other tests
+ if os.environ.get('EMCC_FAST_COMPILER') == '1' and 'LEGACY_GL_EMULATION=1' in args: return self.skip('no legacy gl emulation in fastcomp')
# if we are provided the source and not a path, use that
filename_is_src = '\n' in filename
src = filename if filename_is_src else ''
diff --git a/tests/sdl_canvas.c b/tests/sdl_canvas.c
index 6bd659b8..cab48985 100644
--- a/tests/sdl_canvas.c
+++ b/tests/sdl_canvas.c
@@ -62,6 +62,8 @@ int main(int argc, char **argv) {
printf("you should see two lines of text in different colors and a blue rectangle\n");
+ SDL_UnlockSurface(screen);
+
SDL_Quit();
printf("done.\n");
diff --git a/tests/test_benchmark.py b/tests/test_benchmark.py
index 60670ed4..625340ea 100644
--- a/tests/test_benchmark.py
+++ b/tests/test_benchmark.py
@@ -58,7 +58,7 @@ class NativeBenchmarker(Benchmarker):
def build(self, parent, filename, args, shared_args, emcc_args, native_args, native_exec, lib_builder):
self.parent = parent
- if lib_builder: native_args += lib_builder(self.name, native=True, env_init={ 'CC': self.cc, 'CXX': self.cxx })
+ if lib_builder: native_args = native_args + lib_builder(self.name, native=True, env_init={ 'CC': self.cc, 'CXX': self.cxx })
if not native_exec:
compiler = self.cxx if filename.endswith('cpp') else self.cc
process = Popen([compiler, '-O2', '-fno-math-errno', filename, '-o', filename+'.native'] + shared_args + native_args, stdout=PIPE, stderr=parent.stderr_redirect)
@@ -90,7 +90,7 @@ class JSBenchmarker(Benchmarker):
def build(self, parent, filename, args, shared_args, emcc_args, native_args, native_exec, lib_builder):
self.filename = filename
- if lib_builder: emcc_args += lib_builder('js', native=False, env_init={})
+ if lib_builder: emcc_args = emcc_args + lib_builder('js', native=False, env_init={})
open('hardcode.py', 'w').write('''
def process(filename):
@@ -124,7 +124,7 @@ benchmarkers = [
#NativeBenchmarker('gcc', 'gcc', 'g++'),
#JSBenchmarker('sm-f32', SPIDERMONKEY_ENGINE, ['-s', 'PRECISE_F32=2']),
JSBenchmarker('sm', SPIDERMONKEY_ENGINE),
- JSBenchmarker('sm-fc', SPIDERMONKEY_ENGINE, env={ 'EMCC_FAST_COMPILER': '1' }),
+ #JSBenchmarker('sm-fc', SPIDERMONKEY_ENGINE, env={ 'EMCC_FAST_COMPILER': '1' }),
#JSBenchmarker('sm-noasm', SPIDERMONKEY_ENGINE + ['--no-asmjs']),
#JSBenchmarker('sm-noasm-f32', SPIDERMONKEY_ENGINE + ['--no-asmjs'], ['-s', 'PRECISE_F32=2']),
#JSBenchmarker('v8', V8_ENGINE)
diff --git a/tests/test_browser.py b/tests/test_browser.py
index 920c6f8c..20b38bb5 100644
--- a/tests/test_browser.py
+++ b/tests/test_browser.py
@@ -120,6 +120,8 @@ If manually bisecting:
'''
def test_emscripten_log(self):
+ if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('fastcomp uses asm, where call stacks are sometimes less clear')
+
src = os.path.join(self.get_dir(), 'src.cpp')
open(src, 'w').write(self.with_report_result(open(path_from_root('tests', 'emscripten_log', 'emscripten_log.cpp')).read()))
@@ -680,10 +682,7 @@ If manually bisecting:
self.btest('sdl_stb_image_data.c', reference='screenshot.jpg', args=['-s', 'STB_IMAGE=1', '--preload-file', 'screenshot.not'])
def test_sdl_canvas(self):
- open(os.path.join(self.get_dir(), 'sdl_canvas.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_canvas.c')).read()))
-
- Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_canvas.c'), '-o', 'page.html', '-s', 'LEGACY_GL_EMULATION=1']).communicate()
- self.run_browser('page.html', '', '/report_result?1')
+ self.btest('sdl_canvas.c', expected='1', args=['-s', 'LEGACY_GL_EMULATION=1'])
def test_sdl_canvas_proxy(self):
def post():
@@ -1111,6 +1110,8 @@ keydown(100);keyup(100); // trigger the end
self.run_browser('page.html', '', '/report_result?1')
def test_sdl_audio_beeps(self):
+ if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo c++ exceptions in fastcomp')
+
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()))
# use closure to check for a possible bug with closure minifying away newer Audio() attributes
@@ -1194,10 +1195,7 @@ keydown(100);keyup(100); // trigger the end
self.btest('openal_buffers.c', '0', args=['--preload-file', 'the_entertainer.wav'],)
def test_glfw(self):
- open(os.path.join(self.get_dir(), 'glfw.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'glfw.c')).read()))
-
- Popen([PYTHON, EMCC, '-O2', os.path.join(self.get_dir(), 'glfw.c'), '-o', 'page.html', '-s', 'LEGACY_GL_EMULATION=1']).communicate()
- self.run_browser('page.html', '', '/report_result?1')
+ self.btest('glfw.c', '1', args=['-s', 'LEGACY_GL_EMULATION=1'])
def test_egl(self):
open(os.path.join(self.get_dir(), 'test_egl.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'test_egl.c')).read()))
@@ -1436,6 +1434,8 @@ keydown(100);keyup(100); // trigger the end
self.btest('sdl_resize.c', '1')
def test_gc(self):
+ if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('flaky in fastcomp and also non-fastcomp -O1, timing issues')
+
self.btest('browser_gc.cpp', '1')
def test_glshaderinfo(self):
@@ -1622,11 +1622,12 @@ keydown(100);keyup(100); // trigger the end
self.btest('s3tc_crunch.c', reference='s3tc_crunch.png', reference_slack=11, args=['--pre-js', 'asset_a.js', '--pre-js', 'asset_b.js', '-s', 'LEGACY_GL_EMULATION=1'])
def test_aniso(self):
- if SPIDERMONKEY_ENGINE in JS_ENGINES:
+ if SPIDERMONKEY_ENGINE in JS_ENGINES and os.environ.get('EMCC_FAST_COMPILER') != '1':
# asm.js-ification check
Popen([PYTHON, EMCC, path_from_root('tests', 'aniso.c'), '-O2', '-g2', '-s', 'LEGACY_GL_EMULATION=1']).communicate()
Settings.ASM_JS = 1
self.run_generated_code(SPIDERMONKEY_ENGINE, 'a.out.js')
+ print 'passed asm test'
shutil.copyfile(path_from_root('tests', 'water.dds'), 'water.dds')
self.btest('aniso.c', reference='aniso.png', reference_slack=2, args=['--preload-file', 'water.dds', '-s', 'LEGACY_GL_EMULATION=1'])
@@ -1681,6 +1682,8 @@ keydown(100);keyup(100); // trigger the end
self.btest('http.cpp', expected='0', args=['-I' + path_from_root('tests')])
def test_module(self):
+ if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
+
Popen([PYTHON, EMCC, path_from_root('tests', 'browser_module.cpp'), '-o', 'module.js', '-O2', '-s', 'SIDE_MODULE=1', '-s', 'DLOPEN_SUPPORT=1', '-s', 'EXPORTED_FUNCTIONS=["_one", "_two"]']).communicate()
self.btest('browser_main.cpp', args=['-O2', '-s', 'MAIN_MODULE=1', '-s', 'DLOPEN_SUPPORT=1'], expected='8')
diff --git a/tests/test_core.py b/tests/test_core.py
index 2430aa1c..6442f894 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -771,6 +771,12 @@ 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_closebitcasts(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('requires ta2')
+ test_path = path_from_root('tests', 'core', 'closebitcasts')
+ src, output = (test_path + s for s in ('.c', '.txt'))
+ self.do_run_from_file(src, output)
+
def test_fast_math(self):
if self.emcc_args is None: return self.skip('requires emcc')
Building.COMPILER_TEST_OPTS += ['-ffast-math']
@@ -931,6 +937,8 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
for named in (0, 1):
print named
+ if os.environ.get('EMCC_FAST_COMPILER') == '1' and named: continue # no named globals in fastcomp
+
Settings.NAMED_GLOBALS = named
self.do_run_from_file(src, output, ['wowie', 'too', '74'])
@@ -5026,8 +5034,8 @@ def process(filename):
'structphiparam', 'callwithstructural_ta2', 'callwithstructural64_ta2', 'structinparam', # pnacl limitations in ExpandStructRegs
'2xi40', # pnacl limitations in ExpandGetElementPtr
'legalizer_ta2', '514_ta2', # pnacl limitation in not legalizing i104, i96, etc.
- 'longjmp_tiny', 'longjmp_tiny_invoke', 'longjmp_tiny_phi', 'longjmp_tiny_phi2', 'indirectbrphi', 'ptrtoint_blockaddr', 'quoted', # current fastcomp limitations FIXME
- 'sillyfuncast', 'sillyfuncast2', 'sillybitcast', # TODO very very soon XXX
+ 'longjmp_tiny', 'longjmp_tiny_invoke', 'longjmp_tiny_phi', 'longjmp_tiny_phi2', 'longjmp_tiny_invoke_phi', 'indirectbrphi', 'ptrtoint_blockaddr', 'quoted', # current fastcomp limitations FIXME
+ 'sillyfuncast', 'sillyfuncast2', 'sillybitcast', 'atomicrmw_unaligned' # TODO XXX
]: continue
if '_ta2' in shortname and not Settings.USE_TYPED_ARRAYS == 2:
print self.skip('case "%s" only relevant for ta2' % shortname)
@@ -6085,6 +6093,7 @@ def process(filename):
self.build(src, dirname, os.path.join(dirname, 'src.cpp'), post_build=(None, post))
def test_emscripten_log(self):
+ self.banned_js_engines = [SPIDERMONKEY_ENGINE] # XXX, emscripten_log is broken in spidermonkey currently, issue #1970
if self.emcc_args is None: return self.skip('This test needs libc.')
if '-g' not in Building.COMPILER_TEST_OPTS: Building.COMPILER_TEST_OPTS.append('-g')
self.do_run('#define RUN_FROM_JS_SHELL\n' + open(path_from_root('tests', 'emscripten_log', 'emscripten_log.cpp')).read(), "Success!")
diff --git a/tests/test_other.py b/tests/test_other.py
index a6e8b533..4bdd889b 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -397,6 +397,8 @@ f.close()
self.assertContained('hello, world!', run_js(os.path.join(self.get_dir(), 'a.out.js')))
def test_unaligned_memory(self):
+ if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
+
open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r'''
#include <stdio.h>
#include <stdarg.h>
@@ -421,6 +423,8 @@ f.close()
self.assertContained('data: 67452301\ndata[0,1] 16bit: 2301\ndata[1,2] 16bit: 4523', run_js(os.path.join(self.get_dir(), 'a.out.js')))
def test_unaligned_memory_2(self):
+ if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
+
open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r'''
#include <string>
#include <stdio.h>
@@ -463,6 +467,7 @@ f.close()
assert 'function _malloc' in src
def test_dangerous_func_cast(self):
+ if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
src = r'''
#include <stdio.h>
typedef void (*voidfunc)();
@@ -522,6 +527,8 @@ f.close()
assert not os.path.exists('a.out') and not os.path.exists('a.exe'), 'Must not leave unneeded linker stubs'
def test_static_link(self):
+ if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
+
def test(name, header, main, side, expected, args=[], suffix='cpp', first=True):
print name
#t = main ; main = side ; side = t
@@ -1165,7 +1172,7 @@ f.close()
''')
Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--js-library', os.path.join(self.get_dir(), 'mylib1.js'),
- '--js-library', os.path.join(self.get_dir(), 'mylib2.js')]).communicate()
+ '--js-library', os.path.join(self.get_dir(), 'mylib2.js')]).communicate()
self.assertContained('hello from lib!\n*32*\n', run_js(os.path.join(self.get_dir(), 'a.out.js')))
def test_identical_basenames(self):
@@ -1374,60 +1381,66 @@ f.close()
assert output == ''
def test_multidynamic_link(self):
- # Linking the same dynamic library in will error, normally, since we statically link it, causing dupe symbols
- # A workaround is to use --ignore-dynamic-linking, see emcc --help for details
+ # Linking the same dynamic library in statically will error, normally, since we statically link it, causing dupe symbols
- open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
- #include <stdio.h>
- extern void printey();
- extern void printother();
- int main() {
- printf("*");
- printey();
- printf("\n");
- printother();
- printf("\n");
- printf("*");
- return 0;
- }
- ''')
+ def test(link_cmd, lib_suffix=''):
+ print link_cmd, lib_suffix
- try:
- os.makedirs(os.path.join(self.get_dir(), 'libdir'));
- except:
- pass
+ self.clear()
- open(os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), 'w').write('''
- #include <stdio.h>
- void printey() {
- printf("hello from lib");
- }
- ''')
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
+ #include <stdio.h>
+ extern void printey();
+ extern void printother();
+ int main() {
+ printf("*");
+ printey();
+ printf("\n");
+ printother();
+ printf("\n");
+ printf("*");
+ return 0;
+ }
+ ''')
- open(os.path.join(self.get_dir(), 'libdir', 'libother.cpp'), 'w').write('''
- #include <stdio.h>
- extern void printey();
- void printother() {
- printf("|");
- printey();
- printf("|");
- }
- ''')
+ try:
+ os.makedirs(os.path.join(self.get_dir(), 'libdir'));
+ except:
+ pass
- # This lets us link the same dynamic lib twice. We will need to link it in manually at the end.
- compiler = [PYTHON, EMCC, '--ignore-dynamic-linking']
+ open(os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), 'w').write('''
+ #include <stdio.h>
+ void printey() {
+ printf("hello from lib");
+ }
+ ''')
- # Build libfile normally into an .so
- Popen(compiler + [os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), '-o', os.path.join(self.get_dir(), 'libdir', 'libfile.so')]).communicate()
- # Build libother and dynamically link it to libfile - but add --ignore-dynamic-linking
- Popen(compiler + [os.path.join(self.get_dir(), 'libdir', 'libother.cpp'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile', '-o', os.path.join(self.get_dir(), 'libdir', 'libother.so')]).communicate()
- # Build the main file, linking in both the libs
- Popen(compiler + [os.path.join(self.get_dir(), 'main.cpp'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile', '-lother', '-c']).communicate()
+ open(os.path.join(self.get_dir(), 'libdir', 'libother.cpp'), 'w').write('''
+ #include <stdio.h>
+ extern void printey();
+ void printother() {
+ printf("|");
+ printey();
+ printf("|");
+ }
+ ''')
+
+ compiler = [PYTHON, EMCC]
+
+ # Build libfile normally into an .so
+ Popen(compiler + [os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), '-o', os.path.join(self.get_dir(), 'libdir', 'libfile.so' + lib_suffix)]).communicate()
+ # Build libother and dynamically link it to libfile
+ Popen(compiler + [os.path.join(self.get_dir(), 'libdir', 'libother.cpp')] + link_cmd + ['-o', os.path.join(self.get_dir(), 'libdir', 'libother.so')]).communicate()
+ # Build the main file, linking in both the libs
+ Popen(compiler + [os.path.join(self.get_dir(), 'main.cpp')] + link_cmd + ['-lother', '-c']).communicate()
+ print '...'
+ # The normal build system is over. We need to do an additional step to link in the dynamic libraries, since we ignored them before
+ Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.o')] + link_cmd + ['-lother']).communicate()
- # The normal build system is over. We need to do an additional step to link in the dynamic libraries, since we ignored them before
- Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.o'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile', '-lother']).communicate()
+ self.assertContained('*hello from lib\n|hello from lib|\n*', run_js(os.path.join(self.get_dir(), 'a.out.js')))
- self.assertContained('*hello from lib\n|hello from lib|\n*', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ test(['-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile']) # -l, auto detection from library path
+ test(['-L' + os.path.join(self.get_dir(), 'libdir'), os.path.join(self.get_dir(), 'libdir', 'libfile.so.3.1.4.1.5.9')], '.3.1.4.1.5.9') # handle libX.so.1.2.3 as well
def test_js_link(self):
open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write('''
@@ -1785,6 +1798,7 @@ f.close()
assert 'If you see this - the world is all right!' in output
def test_embind(self):
+ if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
for args, fail in [
([], True), # without --bind, we fail
(['--bind'], False),
@@ -1850,6 +1864,8 @@ seeked= file.
assert output == invalid
def test_link_s(self):
+ if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo safe heap in fastcomp')
+
# -s OPT=VALUE can conflict with -s as a linker option. We warn and ignore
open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
extern "C" {
@@ -1944,19 +1960,19 @@ seeked= file.
# crunch should not be run if a .crn exists that is more recent than the .dds
shutil.copyfile(path_from_root('tests', 'ship.dds'), 'ship.dds')
time.sleep(0.1)
- Popen([PYTHON, FILE_PACKAGER, 'test.data', '--pre-run', '--crunch=32', '--preload', 'ship.dds'], stdout=open('pre.js', 'w')).communicate()
+ Popen([PYTHON, FILE_PACKAGER, 'test.data', '--crunch=32', '--preload', 'ship.dds'], stdout=open('pre.js', 'w')).communicate()
assert os.stat('test.data').st_size < 0.25*os.stat('ship.dds').st_size, 'Compressed should be much smaller than dds'
crunch_time = os.stat('ship.crn').st_mtime
dds_time = os.stat('ship.dds').st_mtime
assert crunch_time > dds_time, 'Crunch is more recent'
# run again, should not recrunch!
time.sleep(0.1)
- Popen([PYTHON, FILE_PACKAGER, 'test.data', '--pre-run', '--crunch=32', '--preload', 'ship.dds'], stdout=open('pre.js', 'w')).communicate()
+ Popen([PYTHON, FILE_PACKAGER, 'test.data', '--crunch=32', '--preload', 'ship.dds'], stdout=open('pre.js', 'w')).communicate()
assert crunch_time == os.stat('ship.crn').st_mtime, 'Crunch is unchanged'
# update dds, so should recrunch
time.sleep(0.1)
os.utime('ship.dds', None)
- Popen([PYTHON, FILE_PACKAGER, 'test.data', '--pre-run', '--crunch=32', '--preload', 'ship.dds'], stdout=open('pre.js', 'w')).communicate()
+ Popen([PYTHON, FILE_PACKAGER, 'test.data', '--crunch=32', '--preload', 'ship.dds'], stdout=open('pre.js', 'w')).communicate()
assert crunch_time < os.stat('ship.crn').st_mtime, 'Crunch was changed'
def test_headless(self):
@@ -2133,6 +2149,8 @@ int main()
self.assertContained('File size: 722', out)
def test_simd(self):
+ if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
+
self.clear()
Popen([PYTHON, EMCC, path_from_root('tests', 'linpack.c'), '-O2', '-DSP', '--llvm-opts', '''['-O3', '-vectorize', '-vectorize-loops', '-bb-vectorize-vector-bits=128', '-force-vector-width=4']''']).communicate()
self.assertContained('Unrolled Single Precision', run_js('a.out.js'))
@@ -2181,3 +2199,12 @@ mergeInto(LibraryManager.library, {
out, err = process.communicate()
assert process.returncode is 0, 'float.h should agree with our system: ' + out + '\n\n\n' + err
+ def test_default_obj_ext(self):
+ outdir = os.path.join(self.get_dir(), 'out_dir') + '/'
+ os.mkdir(outdir)
+ process = Popen([PYTHON, EMCC, '-c', path_from_root('tests', 'hello_world.c'), '-o', outdir], stdout=PIPE, stderr=PIPE)
+ process.communicate()
+ assert(os.path.isfile(outdir + 'hello_world.o'))
+ process = Popen([PYTHON, EMCC, '-c', path_from_root('tests', 'hello_world.c'), '-o', outdir, '--default-obj-ext', 'obj'], stdout=PIPE, stderr=PIPE)
+ process.communicate()
+ assert(os.path.isfile(outdir + 'hello_world.obj'))
diff --git a/tests/test_sanity.py b/tests/test_sanity.py
index dc3d53db..e8b1f885 100644
--- a/tests/test_sanity.py
+++ b/tests/test_sanity.py
@@ -195,6 +195,34 @@ class sanity(RunnerCore):
finally:
del os.environ['EM_IGNORE_SANITY']
+ def test_llvm_fastcomp(self):
+ if os.environ.get('EMCC_FAST_COMPILER') != '1': return self.skip('not using fastcomp')
+
+ WARNING = 'fastcomp in use, but LLVM has not been built with the JavaScript backend as a target'
+
+ restore()
+
+ # Should see js backend during sanity check
+ assert check_fastcomp()
+ output = self.check_working(EMCC)
+ assert WARNING not in output, output
+
+ # Fake incorrect llc output, no mention of js backend
+ restore()
+ f = open(CONFIG_FILE, 'a')
+ f.write('LLVM_ROOT = "' + path_from_root('tests', 'fake') + '"')
+ f.close()
+
+ if not os.path.exists(path_from_root('tests', 'fake')):
+ os.makedirs(path_from_root('tests', 'fake'))
+
+ f = open(path_from_root('tests', 'fake', 'llc'), 'w')
+ f.write('#!/bin/sh\n')
+ f.write('echo "llc fake output\nRegistered Targets:\nno j-s backend for you!"')
+ f.close()
+ os.chmod(path_from_root('tests', 'fake', 'llc'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
+ output = self.check_working(EMCC, WARNING)
+
def test_node(self):
NODE_WARNING = 'node version appears too old'
NODE_WARNING_2 = 'cannot check node version'
diff --git a/tools/eliminator/asm-eliminator-test-output.js b/tools/eliminator/asm-eliminator-test-output.js
index 434fbaf9..a344fc35 100644
--- a/tools/eliminator/asm-eliminator-test-output.js
+++ b/tools/eliminator/asm-eliminator-test-output.js
@@ -280,9 +280,10 @@ function tempDouble2($46, $14, $28, $42, $20, $32, $45) {
$20 = $20 | 0;
$32 = $32 | 0;
$45 = $45 | 0;
- var $_sroa_06_0_insert_insert$1 = 0;
+ var $46 = 0, $_sroa_06_0_insert_insert$1 = 0;
+ $46 = (HEAPF32[tempDoublePtr >> 2] = ($14 < $28 ? $14 : $28) - $42, HEAP32[tempDoublePtr >> 2] | 0);
$_sroa_06_0_insert_insert$1 = (HEAPF32[tempDoublePtr >> 2] = ($20 < $32 ? $20 : $32) - $42, HEAP32[tempDoublePtr >> 2] | 0) | 0;
- HEAP32[$45 >> 2] = 0 | (HEAPF32[tempDoublePtr >> 2] = ($14 < $28 ? $14 : $28) - $42, HEAP32[tempDoublePtr >> 2] | 0);
+ HEAP32[$45 >> 2] = 0 | $46;
HEAP32[$45 + 4 >> 2] = $_sroa_06_0_insert_insert$1;
HEAP32[$45 + 8 >> 2] = $_sroa_06_0_insert_insert$1;
}
@@ -298,4 +299,9 @@ function select2($foundBase_0_off0) {
STACKTOP = sp;
return ($foundBase_0_off0 ? 0 : $call24) | 0;
}
+function binary(x) {
+ x = x | 0;
+ memset(f(x)) | 0;
+ +dmemset(f(x));
+}
diff --git a/tools/eliminator/asm-eliminator-test.js b/tools/eliminator/asm-eliminator-test.js
index 7ec277d5..4b45e4d4 100644
--- a/tools/eliminator/asm-eliminator-test.js
+++ b/tools/eliminator/asm-eliminator-test.js
@@ -370,5 +370,13 @@ function select2($foundBase_0_off0) {
STACKTOP = sp;
return $retval_0 | 0;
}
-// 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"]
+function binary(x) {
+ x = x | 0;
+ var y = 0, z = 0;
+ y = f(x);
+ memset(y) | 0;
+ z = f(x);
+ +dmemset(z);
+}
+// 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"]
diff --git a/tools/eliminator/eliminator-test-output.js b/tools/eliminator/eliminator-test-output.js
index 0171e99b..4551fb34 100644
--- a/tools/eliminator/eliminator-test-output.js
+++ b/tools/eliminator/eliminator-test-output.js
@@ -6122,4 +6122,15 @@ function intoCond() {
function math(a, b, c, d) {
print(Math_imul(d) + (Math_fround(c) + (a + Math_abs(b))));
}
+function td(x, y) {
+ HEAP32[tempDoublePtr >> 2] = x;
+ var xf = HEAPF32[tempDoublePtr >> 2];
+ HEAP32[tempDoublePtr >> 2] = y;
+ func(xf, HEAPF32[tempDoublePtr >> 2]);
+ HEAPF64[tempDoublePtr >> 3] = x;
+ var xl = HEAP32[tempDoublePtr >> 2];
+ var xh = HEAP32[tempDoublePtr >> 2];
+ HEAPF64[tempDoublePtr >> 3] = y;
+ func(xl, xh, HEAP32[tempDoublePtr >> 2], HEAP32[tempDoublePtr >> 2]);
+}
diff --git a/tools/eliminator/eliminator-test.js b/tools/eliminator/eliminator-test.js
index ef17b388..e629d9f0 100644
--- a/tools/eliminator/eliminator-test.js
+++ b/tools/eliminator/eliminator-test.js
@@ -8860,5 +8860,20 @@ function math(a, b, c, d) {
w = Math_imul(d);
print(x + y + z + w);
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "c", "f", "g", "h", "py", "r", "t", "f2", "f3", "llvm3_1", "_inflate", "_malloc", "_mallocNoU", "asm", "phi", "intoCond", "math"]
+function td(x, y) { // tempDoublePtr should invalidate each other
+ HEAP32[tempDoublePtr>>2] = x;
+ var xf = HEAPF32[tempDoublePtr>>2];
+ HEAP32[tempDoublePtr>>2] = y;
+ var yf = HEAPF32[tempDoublePtr>>2];
+ func(xf, yf);
+ //
+ HEAPF64[tempDoublePtr>>3] = x;
+ var xl = HEAP32[tempDoublePtr>>2];
+ var xh = HEAP32[tempDoublePtr>>2];
+ HEAPF64[tempDoublePtr>>3] = y;
+ var yl = HEAP32[tempDoublePtr>>2];
+ var yh = HEAP32[tempDoublePtr>>2];
+ func(xl, xh, yl, yh);
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "c", "f", "g", "h", "py", "r", "t", "f2", "f3", "llvm3_1", "_inflate", "_malloc", "_mallocNoU", "asm", "phi", "intoCond", "math", "td"]
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 9efca25f..161ed59c 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -271,6 +271,16 @@ function isEmptyNode(node) {
return node.length === 2 && node[0] === 'toplevel' && node[1].length === 0;
}
+function clearEmptyNodes(list) {
+ for (var i = 0; i < list.length;) {
+ if (isEmptyNode(list[i]) || (list[i][0] === 'stat' && isEmptyNode(list[i][1]))) {
+ list.splice(i, 1);
+ } else {
+ i++;
+ }
+ }
+}
+
// Passes
// Dump the AST. Useful for debugging. For example,
@@ -2134,14 +2144,11 @@ function registerize(ast) {
// In memSafe mode, we are more careful and assume functions can replace HEAP and FUNCTION_TABLE, which
// can happen in ALLOW_MEMORY_GROWTH mode
-var ELIMINATION_SAFE_NODES = set('var', 'assign', 'call', 'if', 'toplevel', 'do', 'return', 'label', 'switch'); // do is checked carefully, however
+var ELIMINATION_SAFE_NODES = set('var', 'assign', 'call', 'if', 'toplevel', 'do', 'return', 'label', 'switch', 'binary', 'unary-prefix'); // do is checked carefully, however
var IGNORABLE_ELIMINATOR_SCAN_NODES = set('num', 'toplevel', 'string', 'break', 'continue', 'dot'); // dot can only be STRING_TABLE.*
var ABORTING_ELIMINATOR_SCAN_NODES = set('new', 'object', 'function', 'defun', 'for', 'while', 'array', 'throw'); // we could handle some of these, TODO, but nontrivial (e.g. for while, the condition is hit multiple times after the body)
function isTempDoublePtrAccess(node) { // these are used in bitcasts; they are not really affecting memory, and should cause no invalidation
- // XXX note that we assume they have no effect. this is only true due to the compiler emitting (write, read)
- // using the comma operator, so they are not split up. Otherwise, we would need to invalidate
- // tempDoublePtr when it is used, so write; read; write; read; would not become write; write; read; read;
assert(node[0] === 'sub');
return (node[2][0] === 'name' && node[2][1] === 'tempDoublePtr') ||
(node[2][0] === 'binary' && ((node[2][2][0] === 'name' && node[2][2][1] === 'tempDoublePtr') ||
@@ -2427,7 +2434,12 @@ function eliminate(ast, memSafe) {
if (allowTracking) track(name, node[3], node);
}
} else if (target[0] === 'sub') {
- if (!isTempDoublePtrAccess(target) && !memoryInvalidated) {
+ if (isTempDoublePtrAccess(target)) {
+ if (!globalsInvalidated) {
+ invalidateGlobals();
+ globalsInvalidated = true;
+ }
+ } else if (!memoryInvalidated) {
invalidateMemory();
memoryInvalidated = true;
}
@@ -2687,6 +2699,7 @@ function eliminate(ast, memSafe) {
}
if (ifTrue[1][0] && ifTrue[1][0][0] === 'break') {
var assigns = ifFalse[1];
+ clearEmptyNodes(assigns);
var loopers = [], helpers = [];
for (var i = 0; i < assigns.length; i++) {
if (assigns[i][0] === 'stat' && assigns[i][1][0] === 'assign') {
@@ -3112,6 +3125,17 @@ function outline(ast) {
parts = [];
var curr = node;
while (1) {
+ if (!curr[3]) {
+ // we normally expect ..if (cond) { .. } else [if (nextCond) {] (in [] is what we hope to see)
+ // but are now seeing ..if (cond) { .. } with no else. This might be
+ // ..if (cond) if (nextCond) {
+ // which vacuum can generate from if (cond) {} else if (nextCond), making it
+ // if (!cond) if (nextCond)
+ // so we undo that, in hopes of making it more flattenable
+ curr[3] = curr[2];
+ curr[2] = ['block', []];
+ curr[1] = simplifyNotCompsDirect(['unary-prefix', '!', curr[1]]);
+ }
parts.push({ condition: curr[1], body: curr[2] });
curr = curr[3];
if (!curr) break;
diff --git a/tools/shared.py b/tools/shared.py
index 443ff4c7..5b02fa4c 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -286,6 +286,21 @@ def check_llvm_version():
except Exception, e:
logging.warning('Could not verify LLVM version: %s' % str(e))
+def check_fastcomp():
+ try:
+ llc_version_info = Popen([LLVM_COMPILER, '--version'], stdout=PIPE).communicate()[0]
+ pre, targets = llc_version_info.split('Registered Targets:')
+ if 'js' not in targets or 'JavaScript (asm.js, emscripten) backend' not in targets:
+ logging.critical('fastcomp in use, but LLVM has not been built with the JavaScript backend as a target, llc reports:')
+ print >> sys.stderr, '==========================================================================='
+ print >> sys.stderr, llc_version_info,
+ print >> sys.stderr, '==========================================================================='
+ return False
+ return True
+ except Exception, e:
+ logging.warning('cound not check fastcomp: %s' % str(e))
+ return True
+
EXPECTED_NODE_VERSION = (0,8,0)
def check_node_version():
@@ -322,7 +337,7 @@ def find_temp_directory():
# we re-check sanity when the settings are changed)
# We also re-check sanity and clear the cache when the version changes
-EMSCRIPTEN_VERSION = '1.7.8'
+EMSCRIPTEN_VERSION = '1.8.2'
def generate_sanity():
return EMSCRIPTEN_VERSION + '|' + get_llvm_target() + '|' + LLVM_ROOT
@@ -353,9 +368,11 @@ def check_sanity(force=False):
Cache.erase()
force = False # the check actually failed, so definitely write out the sanity file, to avoid others later seeing failures too
- # some warning, not fatal checks - do them even if EM_IGNORE_SANITY is on
+ # some warning, mostly not fatal checks - do them even if EM_IGNORE_SANITY is on
check_llvm_version()
check_node_version()
+ if os.environ.get('EMCC_FAST_COMPILER') == '1':
+ fastcomp_ok = check_fastcomp()
if os.environ.get('EM_IGNORE_SANITY'):
logging.info('EM_IGNORE_SANITY set, ignoring sanity checks')
@@ -377,6 +394,11 @@ def check_sanity(force=False):
logging.critical('Cannot find %s, check the paths in %s' % (cmd, EM_CONFIG))
sys.exit(1)
+ if os.environ.get('EMCC_FAST_COMPILER') == '1':
+ if not fastcomp_ok:
+ logging.critical('failing sanity checks due to previous fastcomp failure')
+ sys.exit(1)
+
try:
subprocess.call([JAVA, '-version'], stdout=PIPE, stderr=PIPE)
except:
@@ -682,7 +704,7 @@ def line_splitter(data):
return out
-def limit_size(string, MAX=12000*20):
+def limit_size(string, MAX=800*20):
if len(string) < MAX: return string
return string[0:MAX/2] + '\n[..]\n' + string[-MAX/2:]
@@ -1094,7 +1116,7 @@ class Building:
# 8k is a bit of an arbitrary limit, but a reasonable one
# for max command line size before we use a respose file
response_file = None
- if WINDOWS and len(' '.join(link_cmd)) > 8192:
+ if len(' '.join(link_cmd)) > 8192:
logging.debug('using response file for llvm-link')
[response_fd, response_file] = mkstemp(suffix='.response', dir=TEMP_DIR)
@@ -1438,7 +1460,7 @@ class Building:
@staticmethod
def ensure_relooper(relooper):
if os.path.exists(relooper): return
- if os.environ.get('EMCC_FAST_COMPILER'):
+ if os.environ.get('EMCC_FAST_COMPILER') == '1':
logging.debug('not building relooper to js, using it in c++ backend')
return
@@ -1513,6 +1535,8 @@ class Building:
text = m.groups(0)[0]
assert text.count('(') == 1 and text.count(')') == 1, 'must have simple expressions in emscripten_jcache_printf calls, no parens'
assert text.count('"') == 2, 'must have simple expressions in emscripten_jcache_printf calls, no strings as varargs parameters'
+ if os.environ.get('EMCC_FAST_COMPILER') == '1': # fake it in fastcomp
+ return text.replace('emscripten_jcache_printf', 'printf')
start = text.index('(')
end = text.rindex(')')
args = text[start+1:end].split(',')