diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-08-26 14:50:01 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-08-26 14:50:01 -0700 |
commit | 1cc28b8e9e94267041bc71afebfbbe3059db4a3f (patch) | |
tree | 107571ed84b48bab5bfb5aea6b7e5b01b814929f | |
parent | 06e7518718115977026830676b80c7279e924b5f (diff) | |
parent | 422d9a1f3227ae8f47fa8bd0037c2220bb2017f7 (diff) |
Merge branch 'incoming'
104 files changed, 4030 insertions, 1912 deletions
@@ -93,4 +93,6 @@ a license to everyone to use it as detailed in LICENSE.) * Yu Kobayashi <yukoba@accelart.jp> * Pin Zhang <zhangpin04@gmail.com> * Nick Bray <ncbray@chromium.org> (copyright owned by Google, Inc.) +* Aidan Hobson Sayers <aidanhs@cantab.net> +* Charlie Birks <admin@daftgames.net> @@ -1,2 +1,2 @@ @echo off -python %~dp0\em++ %*
\ No newline at end of file +python "%~dp0\em++" %*
\ No newline at end of file diff --git a/em-config.bat b/em-config.bat index 63b15ea4..52d1af0e 100644 --- a/em-config.bat +++ b/em-config.bat @@ -1,2 +1,2 @@ @echo off -python %~dp0\em-config %*
\ No newline at end of file +python "%~dp0\em-config" %*
\ No newline at end of file @@ -1,2 +1,2 @@ @echo off -python %~dp0\emar %*
\ No newline at end of file +python "%~dp0\emar" %*
\ No newline at end of file @@ -1577,6 +1577,35 @@ try: js_transform_tempfiles = [final] + if memory_init_file: + if shared.Settings.USE_TYPED_ARRAYS != 2: + if type(memory_init_file) == int: logging.warning('memory init file requires typed arrays mode 2') + else: + memfile = target + '.mem' + shared.try_delete(memfile) + def repl(m): + # handle chunking of the memory initializer + s = re.sub('[\[\]\n\(\)\. ]', '', m.groups(0)[0]) + s = s.replace('concat', ',') + if s[-1] == ',': s = s[:-1] + open(memfile, 'wb').write(''.join(map(lambda x: chr(int(x or '0')), s.split(',')))) + if DEBUG: + # Copy into temp dir as well, so can be run there too + temp_memfile = os.path.join(shared.EMSCRIPTEN_TEMP_DIR, os.path.basename(memfile)) + if os.path.abspath(memfile) != os.path.abspath(memfile): + shutil.copyfile(memfile, temp_memfile) + return 'loadMemoryInitializer("%s");' % os.path.basename(memfile) + src = re.sub(shared.JS.memory_initializer_pattern, repl, open(final).read(), count=1) + open(final + '.mem.js', 'w').write(src) + final += '.mem.js' + js_transform_tempfiles[-1] = final # simple text substitution preserves comment line number mappings + if DEBUG: + if os.path.exists(memfile): + save_intermediate('meminit') + logging.debug('wrote memory initialization to %s' % memfile) + else: + logging.debug('did not see memory initialization') + # It is useful to run several js optimizer passes together, to save on unneeded unparsing/reparsing js_optimizer_queue = [] js_optimizer_extra_info = {} @@ -1631,7 +1660,7 @@ try: if DEBUG: save_intermediate('closure') if js_opts: - if shared.Settings.OUTLINING_LIMIT > 0: + if shared.Settings.OUTLINING_LIMIT > 0 and shared.Settings.ASM_JS: js_optimizer_queue += ['outline'] js_optimizer_extra_info['sizeToOutline'] = shared.Settings.OUTLINING_LIMIT @@ -1654,35 +1683,6 @@ try: src = re.sub(r'\n+[ \n]*\n+', '\n', src) open(final, 'w').write(src) - if memory_init_file: - if shared.Settings.USE_TYPED_ARRAYS != 2: - if type(memory_init_file) == int: logging.warning('memory init file requires typed arrays mode 2') - else: - memfile = target + '.mem' - shared.try_delete(memfile) - def repl(m): - # handle chunking of the memory initializer - s = re.sub('[\[\]\n\(\)\. ]', '', m.groups(0)[0]) - s = s.replace('concat', ',') - if s[-1] == ',': s = s[:-1] - open(memfile, 'wb').write(''.join(map(lambda x: chr(int(x or '0')), s.split(',')))) - if DEBUG: - # Copy into temp dir as well, so can be run there too - temp_memfile = os.path.join(shared.EMSCRIPTEN_TEMP_DIR, os.path.basename(memfile)) - if os.path.abspath(memfile) != os.path.abspath(memfile): - shutil.copyfile(memfile, temp_memfile) - return 'loadMemoryInitializer("%s");' % os.path.basename(memfile) - src = re.sub(shared.JS.memory_initializer_pattern, repl, src, count=1) - open(final + '.mem.js', 'w').write(src) - final += '.mem.js' - js_transform_tempfiles[-1] = final # simple text substitution preserves comment line number mappings - if DEBUG: - if os.path.exists(memfile): - save_intermediate('meminit') - logging.debug('wrote memory initialization to %s' % memfile) - else: - logging.debug('did not see memory initialization') - def generate_source_map(map_file_base_name, offset=0): jsrun.run_js(shared.path_from_root('tools', 'source-maps', 'sourcemapper.js'), shared.NODE_JS, js_transform_tempfiles + @@ -1,2 +1,2 @@ @echo off -python %~dp0\emcc %*
\ No newline at end of file +python "%~dp0\emcc" %*
\ No newline at end of file diff --git a/emconfigure.bat b/emconfigure.bat index f900f407..651ccf05 100644 --- a/emconfigure.bat +++ b/emconfigure.bat @@ -1,2 +1,2 @@ @echo off -python %~dp0\emconfigure %*
\ No newline at end of file +python "%~dp0\emconfigure" %*
\ No newline at end of file diff --git a/emlibtool.bat b/emlibtool.bat index 76ce48c3..4ea705be 100644 --- a/emlibtool.bat +++ b/emlibtool.bat @@ -1,2 +1,2 @@ @echo off -python %~dp0\emlibtool %*
\ No newline at end of file +python "%~dp0\emlibtool" %*
\ No newline at end of file @@ -1,2 +1,2 @@ @echo off -python %~dp0\emmake %*
\ No newline at end of file +python "%~dp0\emmake" %*
\ No newline at end of file diff --git a/emranlib.bat b/emranlib.bat index 69bf8aa4..a8af4ef7 100644 --- a/emranlib.bat +++ b/emranlib.bat @@ -1,2 +1,2 @@ @echo off -python %~dp0\emranlib %*
\ No newline at end of file +python "%~dp0\emranlib" %*
\ No newline at end of file diff --git a/emscripten.py b/emscripten.py index a156ca73..c5e235d8 100755 --- a/emscripten.py +++ b/emscripten.py @@ -552,52 +552,52 @@ var asm = (function(global, env, buffer) { ''' + ''.join([''' var tempRet%d = 0;''' % i for i in range(10)]) + '\n' + asm_global_funcs + ''' // EMSCRIPTEN_START_FUNCS - function stackAlloc(size) { - size = size|0; - var ret = 0; - ret = STACKTOP; - STACKTOP = (STACKTOP + size)|0; +function stackAlloc(size) { + size = size|0; + var ret = 0; + ret = STACKTOP; + STACKTOP = (STACKTOP + size)|0; ''' + ('STACKTOP = ((STACKTOP + 3)>>2)<<2;' if settings['TARGET_X86'] else 'STACKTOP = ((STACKTOP + 7)>>3)<<3;') + ''' - return ret|0; - } - function stackSave() { - return STACKTOP|0; - } - function stackRestore(top) { - top = top|0; - STACKTOP = top; - } - function setThrew(threw, value) { - threw = threw|0; - value = value|0; - if ((__THREW__|0) == 0) { - __THREW__ = threw; - threwValue = value; - } - } - function copyTempFloat(ptr) { - ptr = ptr|0; - HEAP8[tempDoublePtr] = HEAP8[ptr]; - HEAP8[tempDoublePtr+1|0] = HEAP8[ptr+1|0]; - HEAP8[tempDoublePtr+2|0] = HEAP8[ptr+2|0]; - HEAP8[tempDoublePtr+3|0] = HEAP8[ptr+3|0]; - } - function copyTempDouble(ptr) { - ptr = ptr|0; - HEAP8[tempDoublePtr] = HEAP8[ptr]; - HEAP8[tempDoublePtr+1|0] = HEAP8[ptr+1|0]; - HEAP8[tempDoublePtr+2|0] = HEAP8[ptr+2|0]; - HEAP8[tempDoublePtr+3|0] = HEAP8[ptr+3|0]; - HEAP8[tempDoublePtr+4|0] = HEAP8[ptr+4|0]; - HEAP8[tempDoublePtr+5|0] = HEAP8[ptr+5|0]; - HEAP8[tempDoublePtr+6|0] = HEAP8[ptr+6|0]; - HEAP8[tempDoublePtr+7|0] = HEAP8[ptr+7|0]; + return ret|0; +} +function stackSave() { + return STACKTOP|0; +} +function stackRestore(top) { + top = top|0; + STACKTOP = top; +} +function setThrew(threw, value) { + threw = threw|0; + value = value|0; + if ((__THREW__|0) == 0) { + __THREW__ = threw; + threwValue = value; } +} +function copyTempFloat(ptr) { + ptr = ptr|0; + HEAP8[tempDoublePtr] = HEAP8[ptr]; + HEAP8[tempDoublePtr+1|0] = HEAP8[ptr+1|0]; + HEAP8[tempDoublePtr+2|0] = HEAP8[ptr+2|0]; + HEAP8[tempDoublePtr+3|0] = HEAP8[ptr+3|0]; +} +function copyTempDouble(ptr) { + ptr = ptr|0; + HEAP8[tempDoublePtr] = HEAP8[ptr]; + HEAP8[tempDoublePtr+1|0] = HEAP8[ptr+1|0]; + HEAP8[tempDoublePtr+2|0] = HEAP8[ptr+2|0]; + HEAP8[tempDoublePtr+3|0] = HEAP8[ptr+3|0]; + HEAP8[tempDoublePtr+4|0] = HEAP8[ptr+4|0]; + HEAP8[tempDoublePtr+5|0] = HEAP8[ptr+5|0]; + HEAP8[tempDoublePtr+6|0] = HEAP8[ptr+6|0]; + HEAP8[tempDoublePtr+7|0] = HEAP8[ptr+7|0]; +} ''' + ''.join([''' - function setTempRet%d(value) { - value = value|0; - tempRet%d = value; - } +function setTempRet%d(value) { + value = value|0; + tempRet%d = value; +} ''' % (i, i) for i in range(10)])] + [PostSets.js + '\n'] + funcs_js + [''' %s diff --git a/src/compiler.js b/src/compiler.js index 2390f4c9..0baec95e 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -185,8 +185,7 @@ if (ASM_JS) { assert(!ALLOW_MEMORY_GROWTH, 'Cannot grow asm.js heap'); assert((TOTAL_MEMORY&(TOTAL_MEMORY-1)) == 0, 'asm.js heap must be power of 2'); } -assert(!BUILD_AS_SHARED_LIB, 'shared libs are deprecated'); -//assert(!(!NAMED_GLOBALS && BUILD_AS_SHARED_LIB), 'shared libraries must have named globals'); +assert(!(!NAMED_GLOBALS && BUILD_AS_SHARED_LIB), 'shared libraries must have named globals'); // Output some info and warnings based on settings diff --git a/src/headless.js b/src/headless.js index 097a42f7..e5458641 100644 --- a/src/headless.js +++ b/src/headless.js @@ -1,54 +1,50 @@ //== HEADLESS ==// -// TODO: sync from bananabread headless.js +var headlessPrint = function(x) { + //print(x); +} var window = { - eventListeners: {}, - addEventListener: function(id, func) { - var listeners = this.eventListeners[id]; - if (!listeners) { - listeners = this.eventListeners[id] = []; - } - listeners.push(func); - }, - callEventListeners: function(id) { - var listeners = this.eventListeners[id]; - if (listeners) { - listeners.forEach(function(listener) { listener() }); - } - }, + // adjustable parameters location: { toString: function() { return '%s'; }, search: '?%s', + pathname: '%s', }, + onIdle: function(){ headlessPrint('triggering click'); document.querySelector('.fullscreen-button.low-res').callEventListeners('click'); window.onIdle = null; }, + dirsToDrop: 0, // go back to root dir if first_js is in a subdir + // + + headless: true, + + stopped: false, fakeNow: 0, // we don't use Date.now() rafs: [], timeouts: [], uid: 0, requestAnimationFrame: function(func) { func.uid = window.uid++; - print('adding raf ' + func.uid); + headlessPrint('adding raf ' + func.uid); window.rafs.push(func); }, setTimeout: function(func, ms) { func.uid = window.uid++; - print('adding timeout ' + func.uid); + headlessPrint('adding timeout ' + func.uid); window.timeouts.push({ func: func, when: window.fakeNow + (ms || 0) }); window.timeouts.sort(function(x, y) { return y.when - x.when }); }, - onIdle: %s, runEventLoop: function() { // run forever until an exception stops this replay var iter = 0; - while (1) { - var start = Recorder.dnow(); - print('event loop: ' + (iter++)); + while (!this.stopped) { + var start = Date.realNow(); + headlessPrint('event loop: ' + (iter++)); if (window.rafs.length == 0 && window.timeouts.length == 0) { if (window.onIdle) { window.onIdle(); @@ -61,7 +57,7 @@ var window = { window.rafs = []; for (var i = 0; i < currRafs.length; i++) { var raf = currRafs[i]; - print('calling raf: ' + raf.uid);// + ': ' + raf.toString().substring(0, 50)); + headlessPrint('calling raf: ' + raf.uid);// + ': ' + raf.toString().substring(0, 50)); raf(); } // timeouts @@ -70,23 +66,14 @@ var window = { window.timeouts = []; while (timeouts.length && timeouts[timeouts.length-1].when <= now) { var timeout = timeouts.pop(); - print('calling timeout: ' + timeout.func.uid);// + ': ' + timeout.func.toString().substring(0, 50)); + headlessPrint('calling timeout: ' + timeout.func.uid);// + ': ' + timeout.func.toString().substring(0, 50)); timeout.func(); } // increment 'time' window.fakeNow += 16.666; - print('main event loop iteration took ' + (Recorder.dnow() - start) + ' ms'); + headlessPrint('main event loop iteration took ' + (Date.realNow() - start) + ' ms'); } }, - URL: { - createObjectURL: function(x) { - return x; // the blob itself is returned - }, - revokeObjectURL: function(x) {}, - }, -}; -var setTimeout = window.setTimeout; -var document = { eventListeners: {}, addEventListener: function(id, func) { var listeners = this.eventListeners[id]; @@ -101,619 +88,25 @@ var document = { listeners.forEach(function(listener) { listener() }); } }, + URL: { + createObjectURL: function(x) { + return x; // the blob itself is returned + }, + revokeObjectURL: function(x) {}, + }, + encodeURIComponent: function(x) { return x }, +}; +var setTimeout = window.setTimeout; +var document = { + headless: true, + eventListeners: {}, + addEventListener: window.addEventListener, + callEventListeners: window.callEventListeners, getElementById: function(id) { switch(id) { case 'canvas': { if (this.canvas) return this.canvas; - return this.canvas = { - getContext: function(which) { - switch(which) { - case 'experimental-webgl': { - return { - /* ClearBufferMask */ - DEPTH_BUFFER_BIT : 0x00000100, - STENCIL_BUFFER_BIT : 0x00000400, - COLOR_BUFFER_BIT : 0x00004000, - - /* BeginMode */ - POINTS : 0x0000, - LINES : 0x0001, - LINE_LOOP : 0x0002, - LINE_STRIP : 0x0003, - TRIANGLES : 0x0004, - TRIANGLE_STRIP : 0x0005, - TRIANGLE_FAN : 0x0006, - - /* AlphaFunction (not supported in ES20) */ - /* NEVER */ - /* LESS */ - /* EQUAL */ - /* LEQUAL */ - /* GREATER */ - /* NOTEQUAL */ - /* GEQUAL */ - /* ALWAYS */ - - /* BlendingFactorDest */ - ZERO : 0, - ONE : 1, - SRC_COLOR : 0x0300, - ONE_MINUS_SRC_COLOR : 0x0301, - SRC_ALPHA : 0x0302, - ONE_MINUS_SRC_ALPHA : 0x0303, - DST_ALPHA : 0x0304, - ONE_MINUS_DST_ALPHA : 0x0305, - - /* BlendingFactorSrc */ - /* ZERO */ - /* ONE */ - DST_COLOR : 0x0306, - ONE_MINUS_DST_COLOR : 0x0307, - SRC_ALPHA_SATURATE : 0x0308, - /* SRC_ALPHA */ - /* ONE_MINUS_SRC_ALPHA */ - /* DST_ALPHA */ - /* ONE_MINUS_DST_ALPHA */ - - /* BlendEquationSeparate */ - FUNC_ADD : 0x8006, - BLEND_EQUATION : 0x8009, - BLEND_EQUATION_RGB : 0x8009, /* same as BLEND_EQUATION */ - BLEND_EQUATION_ALPHA : 0x883D, - - /* BlendSubtract */ - FUNC_SUBTRACT : 0x800A, - FUNC_REVERSE_SUBTRACT : 0x800B, - - /* Separate Blend Functions */ - BLEND_DST_RGB : 0x80C8, - BLEND_SRC_RGB : 0x80C9, - BLEND_DST_ALPHA : 0x80CA, - BLEND_SRC_ALPHA : 0x80CB, - CONSTANT_COLOR : 0x8001, - ONE_MINUS_CONSTANT_COLOR : 0x8002, - CONSTANT_ALPHA : 0x8003, - ONE_MINUS_CONSTANT_ALPHA : 0x8004, - BLEND_COLOR : 0x8005, - - /* Buffer Objects */ - ARRAY_BUFFER : 0x8892, - ELEMENT_ARRAY_BUFFER : 0x8893, - ARRAY_BUFFER_BINDING : 0x8894, - ELEMENT_ARRAY_BUFFER_BINDING : 0x8895, - - STREAM_DRAW : 0x88E0, - STATIC_DRAW : 0x88E4, - DYNAMIC_DRAW : 0x88E8, - - BUFFER_SIZE : 0x8764, - BUFFER_USAGE : 0x8765, - - CURRENT_VERTEX_ATTRIB : 0x8626, - - /* CullFaceMode */ - FRONT : 0x0404, - BACK : 0x0405, - FRONT_AND_BACK : 0x0408, - - /* DepthFunction */ - /* NEVER */ - /* LESS */ - /* EQUAL */ - /* LEQUAL */ - /* GREATER */ - /* NOTEQUAL */ - /* GEQUAL */ - /* ALWAYS */ - - /* EnableCap */ - /* TEXTURE_2D */ - CULL_FACE : 0x0B44, - BLEND : 0x0BE2, - DITHER : 0x0BD0, - STENCIL_TEST : 0x0B90, - DEPTH_TEST : 0x0B71, - SCISSOR_TEST : 0x0C11, - POLYGON_OFFSET_FILL : 0x8037, - SAMPLE_ALPHA_TO_COVERAGE : 0x809E, - SAMPLE_COVERAGE : 0x80A0, - - /* ErrorCode */ - NO_ERROR : 0, - INVALID_ENUM : 0x0500, - INVALID_VALUE : 0x0501, - INVALID_OPERATION : 0x0502, - OUT_OF_MEMORY : 0x0505, - - /* FrontFaceDirection */ - CW : 0x0900, - CCW : 0x0901, - - /* GetPName */ - LINE_WIDTH : 0x0B21, - ALIASED_POINT_SIZE_RANGE : 0x846D, - ALIASED_LINE_WIDTH_RANGE : 0x846E, - CULL_FACE_MODE : 0x0B45, - FRONT_FACE : 0x0B46, - DEPTH_RANGE : 0x0B70, - DEPTH_WRITEMASK : 0x0B72, - DEPTH_CLEAR_VALUE : 0x0B73, - DEPTH_FUNC : 0x0B74, - STENCIL_CLEAR_VALUE : 0x0B91, - STENCIL_FUNC : 0x0B92, - STENCIL_FAIL : 0x0B94, - STENCIL_PASS_DEPTH_FAIL : 0x0B95, - STENCIL_PASS_DEPTH_PASS : 0x0B96, - STENCIL_REF : 0x0B97, - STENCIL_VALUE_MASK : 0x0B93, - STENCIL_WRITEMASK : 0x0B98, - STENCIL_BACK_FUNC : 0x8800, - STENCIL_BACK_FAIL : 0x8801, - STENCIL_BACK_PASS_DEPTH_FAIL : 0x8802, - STENCIL_BACK_PASS_DEPTH_PASS : 0x8803, - STENCIL_BACK_REF : 0x8CA3, - STENCIL_BACK_VALUE_MASK : 0x8CA4, - STENCIL_BACK_WRITEMASK : 0x8CA5, - VIEWPORT : 0x0BA2, - SCISSOR_BOX : 0x0C10, - /* SCISSOR_TEST */ - COLOR_CLEAR_VALUE : 0x0C22, - COLOR_WRITEMASK : 0x0C23, - UNPACK_ALIGNMENT : 0x0CF5, - PACK_ALIGNMENT : 0x0D05, - MAX_TEXTURE_SIZE : 0x0D33, - MAX_VIEWPORT_DIMS : 0x0D3A, - SUBPIXEL_BITS : 0x0D50, - RED_BITS : 0x0D52, - GREEN_BITS : 0x0D53, - BLUE_BITS : 0x0D54, - ALPHA_BITS : 0x0D55, - DEPTH_BITS : 0x0D56, - STENCIL_BITS : 0x0D57, - POLYGON_OFFSET_UNITS : 0x2A00, - /* POLYGON_OFFSET_FILL */ - POLYGON_OFFSET_FACTOR : 0x8038, - TEXTURE_BINDING_2D : 0x8069, - SAMPLE_BUFFERS : 0x80A8, - SAMPLES : 0x80A9, - SAMPLE_COVERAGE_VALUE : 0x80AA, - SAMPLE_COVERAGE_INVERT : 0x80AB, - - /* GetTextureParameter */ - /* TEXTURE_MAG_FILTER */ - /* TEXTURE_MIN_FILTER */ - /* TEXTURE_WRAP_S */ - /* TEXTURE_WRAP_T */ - - COMPRESSED_TEXTURE_FORMATS : 0x86A3, - - /* HintMode */ - DONT_CARE : 0x1100, - FASTEST : 0x1101, - NICEST : 0x1102, - - /* HintTarget */ - GENERATE_MIPMAP_HINT : 0x8192, - - /* DataType */ - BYTE : 0x1400, - UNSIGNED_BYTE : 0x1401, - SHORT : 0x1402, - UNSIGNED_SHORT : 0x1403, - INT : 0x1404, - UNSIGNED_INT : 0x1405, - FLOAT : 0x1406, - - /* PixelFormat */ - DEPTH_COMPONENT : 0x1902, - ALPHA : 0x1906, - RGB : 0x1907, - RGBA : 0x1908, - LUMINANCE : 0x1909, - LUMINANCE_ALPHA : 0x190A, - - /* PixelType */ - /* UNSIGNED_BYTE */ - UNSIGNED_SHORT_4_4_4_4 : 0x8033, - UNSIGNED_SHORT_5_5_5_1 : 0x8034, - UNSIGNED_SHORT_5_6_5 : 0x8363, - - /* Shaders */ - FRAGMENT_SHADER : 0x8B30, - VERTEX_SHADER : 0x8B31, - MAX_VERTEX_ATTRIBS : 0x8869, - MAX_VERTEX_UNIFORM_VECTORS : 0x8DFB, - MAX_VARYING_VECTORS : 0x8DFC, - MAX_COMBINED_TEXTURE_IMAGE_UNITS : 0x8B4D, - MAX_VERTEX_TEXTURE_IMAGE_UNITS : 0x8B4C, - MAX_TEXTURE_IMAGE_UNITS : 0x8872, - MAX_FRAGMENT_UNIFORM_VECTORS : 0x8DFD, - SHADER_TYPE : 0x8B4F, - DELETE_STATUS : 0x8B80, - LINK_STATUS : 0x8B82, - VALIDATE_STATUS : 0x8B83, - ATTACHED_SHADERS : 0x8B85, - ACTIVE_UNIFORMS : 0x8B86, - ACTIVE_ATTRIBUTES : 0x8B89, - SHADING_LANGUAGE_VERSION : 0x8B8C, - CURRENT_PROGRAM : 0x8B8D, - - /* StencilFunction */ - NEVER : 0x0200, - LESS : 0x0201, - EQUAL : 0x0202, - LEQUAL : 0x0203, - GREATER : 0x0204, - NOTEQUAL : 0x0205, - GEQUAL : 0x0206, - ALWAYS : 0x0207, - - /* StencilOp */ - /* ZERO */ - KEEP : 0x1E00, - REPLACE : 0x1E01, - INCR : 0x1E02, - DECR : 0x1E03, - INVERT : 0x150A, - INCR_WRAP : 0x8507, - DECR_WRAP : 0x8508, - - /* StringName */ - VENDOR : 0x1F00, - RENDERER : 0x1F01, - VERSION : 0x1F02, - - /* TextureMagFilter */ - NEAREST : 0x2600, - LINEAR : 0x2601, - - /* TextureMinFilter */ - /* NEAREST */ - /* LINEAR */ - NEAREST_MIPMAP_NEAREST : 0x2700, - LINEAR_MIPMAP_NEAREST : 0x2701, - NEAREST_MIPMAP_LINEAR : 0x2702, - LINEAR_MIPMAP_LINEAR : 0x2703, - - /* TextureParameterName */ - TEXTURE_MAG_FILTER : 0x2800, - TEXTURE_MIN_FILTER : 0x2801, - TEXTURE_WRAP_S : 0x2802, - TEXTURE_WRAP_T : 0x2803, - - /* TextureTarget */ - TEXTURE_2D : 0x0DE1, - TEXTURE : 0x1702, - - TEXTURE_CUBE_MAP : 0x8513, - TEXTURE_BINDING_CUBE_MAP : 0x8514, - TEXTURE_CUBE_MAP_POSITIVE_X : 0x8515, - TEXTURE_CUBE_MAP_NEGATIVE_X : 0x8516, - TEXTURE_CUBE_MAP_POSITIVE_Y : 0x8517, - TEXTURE_CUBE_MAP_NEGATIVE_Y : 0x8518, - TEXTURE_CUBE_MAP_POSITIVE_Z : 0x8519, - TEXTURE_CUBE_MAP_NEGATIVE_Z : 0x851A, - MAX_CUBE_MAP_TEXTURE_SIZE : 0x851C, - - /* TextureUnit */ - TEXTURE0 : 0x84C0, - TEXTURE1 : 0x84C1, - TEXTURE2 : 0x84C2, - TEXTURE3 : 0x84C3, - TEXTURE4 : 0x84C4, - TEXTURE5 : 0x84C5, - TEXTURE6 : 0x84C6, - TEXTURE7 : 0x84C7, - TEXTURE8 : 0x84C8, - TEXTURE9 : 0x84C9, - TEXTURE10 : 0x84CA, - TEXTURE11 : 0x84CB, - TEXTURE12 : 0x84CC, - TEXTURE13 : 0x84CD, - TEXTURE14 : 0x84CE, - TEXTURE15 : 0x84CF, - TEXTURE16 : 0x84D0, - TEXTURE17 : 0x84D1, - TEXTURE18 : 0x84D2, - TEXTURE19 : 0x84D3, - TEXTURE20 : 0x84D4, - TEXTURE21 : 0x84D5, - TEXTURE22 : 0x84D6, - TEXTURE23 : 0x84D7, - TEXTURE24 : 0x84D8, - TEXTURE25 : 0x84D9, - TEXTURE26 : 0x84DA, - TEXTURE27 : 0x84DB, - TEXTURE28 : 0x84DC, - TEXTURE29 : 0x84DD, - TEXTURE30 : 0x84DE, - TEXTURE31 : 0x84DF, - ACTIVE_TEXTURE : 0x84E0, - - /* TextureWrapMode */ - REPEAT : 0x2901, - CLAMP_TO_EDGE : 0x812F, - MIRRORED_REPEAT : 0x8370, - - /* Uniform Types */ - FLOAT_VEC2 : 0x8B50, - FLOAT_VEC3 : 0x8B51, - FLOAT_VEC4 : 0x8B52, - INT_VEC2 : 0x8B53, - INT_VEC3 : 0x8B54, - INT_VEC4 : 0x8B55, - BOOL : 0x8B56, - BOOL_VEC2 : 0x8B57, - BOOL_VEC3 : 0x8B58, - BOOL_VEC4 : 0x8B59, - FLOAT_MAT2 : 0x8B5A, - FLOAT_MAT3 : 0x8B5B, - FLOAT_MAT4 : 0x8B5C, - SAMPLER_2D : 0x8B5E, - SAMPLER_CUBE : 0x8B60, - - /* Vertex Arrays */ - VERTEX_ATTRIB_ARRAY_ENABLED : 0x8622, - VERTEX_ATTRIB_ARRAY_SIZE : 0x8623, - VERTEX_ATTRIB_ARRAY_STRIDE : 0x8624, - VERTEX_ATTRIB_ARRAY_TYPE : 0x8625, - VERTEX_ATTRIB_ARRAY_NORMALIZED : 0x886A, - VERTEX_ATTRIB_ARRAY_POINTER : 0x8645, - VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : 0x889F, - - /* Shader Source */ - COMPILE_STATUS : 0x8B81, - - /* Shader Precision-Specified Types */ - LOW_FLOAT : 0x8DF0, - MEDIUM_FLOAT : 0x8DF1, - HIGH_FLOAT : 0x8DF2, - LOW_INT : 0x8DF3, - MEDIUM_INT : 0x8DF4, - HIGH_INT : 0x8DF5, - - /* Framebuffer Object. */ - FRAMEBUFFER : 0x8D40, - RENDERBUFFER : 0x8D41, - - RGBA4 : 0x8056, - RGB5_A1 : 0x8057, - RGB565 : 0x8D62, - DEPTH_COMPONENT16 : 0x81A5, - STENCIL_INDEX : 0x1901, - STENCIL_INDEX8 : 0x8D48, - DEPTH_STENCIL : 0x84F9, - - RENDERBUFFER_WIDTH : 0x8D42, - RENDERBUFFER_HEIGHT : 0x8D43, - RENDERBUFFER_INTERNAL_FORMAT : 0x8D44, - RENDERBUFFER_RED_SIZE : 0x8D50, - RENDERBUFFER_GREEN_SIZE : 0x8D51, - RENDERBUFFER_BLUE_SIZE : 0x8D52, - RENDERBUFFER_ALPHA_SIZE : 0x8D53, - RENDERBUFFER_DEPTH_SIZE : 0x8D54, - RENDERBUFFER_STENCIL_SIZE : 0x8D55, - - FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE : 0x8CD0, - FRAMEBUFFER_ATTACHMENT_OBJECT_NAME : 0x8CD1, - FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL : 0x8CD2, - FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE : 0x8CD3, - - COLOR_ATTACHMENT0 : 0x8CE0, - DEPTH_ATTACHMENT : 0x8D00, - STENCIL_ATTACHMENT : 0x8D20, - DEPTH_STENCIL_ATTACHMENT : 0x821A, - - NONE : 0, - - FRAMEBUFFER_COMPLETE : 0x8CD5, - FRAMEBUFFER_INCOMPLETE_ATTACHMENT : 0x8CD6, - FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT : 0x8CD7, - FRAMEBUFFER_INCOMPLETE_DIMENSIONS : 0x8CD9, - FRAMEBUFFER_UNSUPPORTED : 0x8CDD, - - FRAMEBUFFER_BINDING : 0x8CA6, - RENDERBUFFER_BINDING : 0x8CA7, - MAX_RENDERBUFFER_SIZE : 0x84E8, - - INVALID_FRAMEBUFFER_OPERATION : 0x0506, - - /* WebGL-specific enums */ - UNPACK_FLIP_Y_WEBGL : 0x9240, - UNPACK_PREMULTIPLY_ALPHA_WEBGL : 0x9241, - CONTEXT_LOST_WEBGL : 0x9242, - UNPACK_COLORSPACE_CONVERSION_WEBGL : 0x9243, - BROWSER_DEFAULT_WEBGL : 0x9244, - - items: {}, - id: 0, - getExtension: function() { return 1 }, - createBuffer: function() { - var id = this.id++; - this.items[id] = { - which: 'buffer', - }; - return id; - }, - deleteBuffer: function(){}, - bindBuffer: function(){}, - bufferData: function(){}, - getParameter: function(pname) { - switch(pname) { - case /* GL_VENDOR */ 0x1F00: return 'FakeShellGLVendor'; - case /* GL_RENDERER */ 0x1F01: return 'FakeShellGLRenderer'; - case /* GL_VERSION */ 0x1F02: return '0.0.1'; - case /* GL_MAX_TEXTURE_SIZE */ 0x0D33: return 16384; - case /* GL_MAX_CUBE_MAP_TEXTURE_SIZE */ 0x851C: return 16384; - case /* GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT */ 0x84FF: return 16; - case /* GL_MAX_TEXTURE_IMAGE_UNITS_NV */ 0x8872: return 16; - case /* GL_MAX_VERTEX_UNIFORM_VECTORS */ 0x8DFB: return 4096; - case /* GL_MAX_FRAGMENT_UNIFORM_VECTORS */ 0x8DFD: return 4096; - case /* GL_MAX_VARYING_VECTORS */ 0x8DFC: return 32; - case /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS */ 0x8B4D: return 32; - default: console.log('getParameter ' + pname + '?'); return 0; - } - }, - getSupportedExtensions: function() { - return ["OES_texture_float", "OES_standard_derivatives", "EXT_texture_filter_anisotropic", "MOZ_EXT_texture_filter_anisotropic", "MOZ_WEBGL_lose_context", "MOZ_WEBGL_compressed_texture_s3tc", "MOZ_WEBGL_depth_texture"]; - }, - createShader: function(type) { - var id = this.id++; - this.items[id] = { - which: 'shader', - type: type, - }; - return id; - }, - getShaderParameter: function(shader, pname) { - switch(pname) { - case /* GL_SHADER_TYPE */ 0x8B4F: return this.items[shader].type; - case /* GL_COMPILE_STATUS */ 0x8B81: return true; - default: throw 'getShaderParameter ' + pname; - } - }, - shaderSource: function(){}, - compileShader: function(){}, - createProgram: function() { - var id = this.id++; - this.items[id] = { - which: 'program', - shaders: [], - }; - return id; - }, - attachShader: function(program, shader) { - this.items[program].shaders.push(shader); - }, - bindAttribLocation: function(){}, - linkProgram: function(){}, - getProgramParameter: function(program, pname) { - switch(pname) { - case /* LINK_STATUS */ 0x8B82: return true; - case /* ACTIVE_UNIFORMS */ 0x8B86: return 4; - default: throw 'getProgramParameter ' + pname; - } - }, - deleteShader: function(){}, - deleteProgram: function(){}, - viewport: function(){}, - clearColor: function(){}, - clearDepth: function(){}, - depthFunc: function(){}, - enable: function(){}, - disable: function(){}, - frontFace: function(){}, - cullFace: function(){}, - activeTexture: function(){}, - createTexture: function() { - var id = this.id++; - this.items[id] = { - which: 'texture', - }; - return id; - }, - deleteTexture: function(){}, - boundTextures: {}, - bindTexture: function(target, texture) { - this.boundTextures[target] = texture; - }, - texParameteri: function(){}, - pixelStorei: function(){}, - texImage2D: function(){}, - compressedTexImage2D: function(){}, - useProgram: function(){}, - getUniformLocation: function() { - return null; - }, - getActiveUniform: function(program, index) { - return { - size: 1, - type: /* INT_VEC3 */ 0x8B54, - name: 'activeUniform' + index, - }; - }, - clear: function(){}, - uniform4fv: function(){}, - uniform1i: function(){}, - getAttribLocation: function() { return 1 }, - vertexAttribPointer: function(){}, - enableVertexAttribArray: function(){}, - disableVertexAttribArray: function(){}, - drawElements: function(){}, - drawArrays: function(){}, - depthMask: function(){}, - depthRange: function(){}, - bufferSubData: function(){}, - blendFunc: function(){}, - createFramebuffer: function() { - var id = this.id++; - this.items[id] = { - which: 'framebuffer', - shaders: [], - }; - return id; - }, - bindFramebuffer: function(){}, - framebufferTexture2D: function(){}, - checkFramebufferStatus: function() { - return /* FRAMEBUFFER_COMPLETE */ 0x8CD5; - }, - createRenderbuffer: function() { - var id = this.id++; - this.items[id] = { - which: 'renderbuffer', - shaders: [], - }; - return id; - }, - bindRenderbuffer: function(){}, - renderbufferStorage: function(){}, - framebufferRenderbuffer: function(){}, - scissor: function(){}, - colorMask: function(){}, - lineWidth: function(){}, - }; - } - case '2d': { - return { - drawImage: function(){}, - getImageData: function(x, y, w, h) { - return { - width: w, - height: h, - data: new Uint8ClampedArray(w*h), - }; - }, - save: function(){}, - restore: function(){}, - fillRect: function(){}, - measureText: function() { return 10 }, - fillText: function(){}, - }; - } - default: throw 'canvas.getContext: ' + which; - } - }, - requestPointerLock: function() { - document.pointerLockElement = document.getElementById('canvas'); - window.setTimeout(function() { - document.callEventListeners('pointerlockchange'); - }); - }, - exitPointerLock: function(){}, - style: {}, - eventListeners: {}, - addEventListener: document.addEventListener, - callEventListeners: document.callEventListeners, - requestFullScreen: function() { - document.fullscreenElement = document.getElementById('canvas'); - window.setTimeout(function() { - document.callEventListeners('fullscreenchange'); - }); - }, - offsetTop: 0, - offsetLeft: 0, - }; + return this.canvas = headlessCanvas(); } case 'status-text': case 'progress': { return {}; @@ -727,9 +120,9 @@ var document = { case 'script': { var ret = {}; window.setTimeout(function() { - print('loading script: ' + ret.src); + headlessPrint('loading script: ' + ret.src); load(ret.src); - print(' script loaded.'); + headlessPrint(' script loaded.'); if (ret.onload) { window.setTimeout(function() { ret.onload(); // yeah yeah this might vanish @@ -769,16 +162,14 @@ var document = { var alert = function(x) { print(x); }; -var originalDateNow = Date.now; var performance = { now: function() { - return originalDateNow.call(Date); + return Date.now(); }, }; function fixPath(path) { if (path[0] == '/') path = path.substring(1); - var dirsToDrop = %d; // go back to root dir if first_js is in a subdir - for (var i = 0; i < dirsToDrop; i++) { + for (var i = 0; i < window.dirsToDrop; i++) { path = '../' + path; } return path @@ -833,11 +224,11 @@ var Worker = function(workerPath) { workerPath = fixPath(workerPath); var workerCode = read(workerPath); workerCode = workerCode.replace(/Module/g, 'zzModuleyy' + (Worker.id++)). // prevent collision with the global Module object. Note that this becomes global, so we need unique ids - replace(/Date.now/g, 'Recorder.dnow'). // recorded values are just for the "main thread" - workers were not recorded, and should not consume - replace(/performance.now/g, 'Recorder.pnow'). - replace(/Math.random/g, 'Recorder.random'). + //replace(/Date.now/g, 'Recorder.dnow'). // recorded values are just for the "main thread" - workers were not recorded, and should not consume + //replace(/performance.now/g, 'Recorder.pnow'). + //replace(/Math.random/g, 'Recorder.random'). replace(/\nonmessage = /, '\nvar onmessage = '); // workers commonly do "onmessage = ", we need to varify that to sandbox - print('loading worker ' + workerPath + ' : ' + workerCode.substring(0, 50)); + headlessPrint('loading worker ' + workerPath + ' : ' + workerCode.substring(0, 50)); eval(workerCode); // will implement onmessage() function duplicateJSON(json) { @@ -852,18 +243,18 @@ var Worker = function(workerPath) { this.terminate = function(){}; this.postMessage = function(msg) { msg.messageId = Worker.messageId++; - print('main thread sending message ' + msg.messageId + ' to worker ' + workerPath); + headlessPrint('main thread sending message ' + msg.messageId + ' to worker ' + workerPath); window.setTimeout(function() { - print('worker ' + workerPath + ' receiving message ' + msg.messageId); + headlessPrint('worker ' + workerPath + ' receiving message ' + msg.messageId); onmessage({ data: duplicateJSON(msg) }); }); }; var thisWorker = this; var postMessage = function(msg) { msg.messageId = Worker.messageId++; - print('worker ' + workerPath + ' sending message ' + msg.messageId); + headlessPrint('worker ' + workerPath + ' sending message ' + msg.messageId); window.setTimeout(function() { - print('main thread receiving message ' + msg.messageId + ' from ' + workerPath); + headlessPrint('main thread receiving message ' + msg.messageId + ' from ' + workerPath); thisWorker.onmessage({ data: duplicateJSON(msg) }); }); }; diff --git a/src/headlessCanvas.js b/src/headlessCanvas.js new file mode 100644 index 00000000..4951aed8 --- /dev/null +++ b/src/headlessCanvas.js @@ -0,0 +1,618 @@ +function headlessCanvas() { + return { + headless: true, + getContext: function(which) { + switch(which) { + case 'experimental-webgl': { + return { + /* ClearBufferMask */ + DEPTH_BUFFER_BIT : 0x00000100, + STENCIL_BUFFER_BIT : 0x00000400, + COLOR_BUFFER_BIT : 0x00004000, + + /* BeginMode */ + POINTS : 0x0000, + LINES : 0x0001, + LINE_LOOP : 0x0002, + LINE_STRIP : 0x0003, + TRIANGLES : 0x0004, + TRIANGLE_STRIP : 0x0005, + TRIANGLE_FAN : 0x0006, + + /* AlphaFunction (not supported in ES20) */ + /* NEVER */ + /* LESS */ + /* EQUAL */ + /* LEQUAL */ + /* GREATER */ + /* NOTEQUAL */ + /* GEQUAL */ + /* ALWAYS */ + + /* BlendingFactorDest */ + ZERO : 0, + ONE : 1, + SRC_COLOR : 0x0300, + ONE_MINUS_SRC_COLOR : 0x0301, + SRC_ALPHA : 0x0302, + ONE_MINUS_SRC_ALPHA : 0x0303, + DST_ALPHA : 0x0304, + ONE_MINUS_DST_ALPHA : 0x0305, + + /* BlendingFactorSrc */ + /* ZERO */ + /* ONE */ + DST_COLOR : 0x0306, + ONE_MINUS_DST_COLOR : 0x0307, + SRC_ALPHA_SATURATE : 0x0308, + /* SRC_ALPHA */ + /* ONE_MINUS_SRC_ALPHA */ + /* DST_ALPHA */ + /* ONE_MINUS_DST_ALPHA */ + + /* BlendEquationSeparate */ + FUNC_ADD : 0x8006, + BLEND_EQUATION : 0x8009, + BLEND_EQUATION_RGB : 0x8009, /* same as BLEND_EQUATION */ + BLEND_EQUATION_ALPHA : 0x883D, + + /* BlendSubtract */ + FUNC_SUBTRACT : 0x800A, + FUNC_REVERSE_SUBTRACT : 0x800B, + + /* Separate Blend Functions */ + BLEND_DST_RGB : 0x80C8, + BLEND_SRC_RGB : 0x80C9, + BLEND_DST_ALPHA : 0x80CA, + BLEND_SRC_ALPHA : 0x80CB, + CONSTANT_COLOR : 0x8001, + ONE_MINUS_CONSTANT_COLOR : 0x8002, + CONSTANT_ALPHA : 0x8003, + ONE_MINUS_CONSTANT_ALPHA : 0x8004, + BLEND_COLOR : 0x8005, + + /* Buffer Objects */ + ARRAY_BUFFER : 0x8892, + ELEMENT_ARRAY_BUFFER : 0x8893, + ARRAY_BUFFER_BINDING : 0x8894, + ELEMENT_ARRAY_BUFFER_BINDING : 0x8895, + + STREAM_DRAW : 0x88E0, + STATIC_DRAW : 0x88E4, + DYNAMIC_DRAW : 0x88E8, + + BUFFER_SIZE : 0x8764, + BUFFER_USAGE : 0x8765, + + CURRENT_VERTEX_ATTRIB : 0x8626, + + /* CullFaceMode */ + FRONT : 0x0404, + BACK : 0x0405, + FRONT_AND_BACK : 0x0408, + + /* DepthFunction */ + /* NEVER */ + /* LESS */ + /* EQUAL */ + /* LEQUAL */ + /* GREATER */ + /* NOTEQUAL */ + /* GEQUAL */ + /* ALWAYS */ + + /* EnableCap */ + /* TEXTURE_2D */ + CULL_FACE : 0x0B44, + BLEND : 0x0BE2, + DITHER : 0x0BD0, + STENCIL_TEST : 0x0B90, + DEPTH_TEST : 0x0B71, + SCISSOR_TEST : 0x0C11, + POLYGON_OFFSET_FILL : 0x8037, + SAMPLE_ALPHA_TO_COVERAGE : 0x809E, + SAMPLE_COVERAGE : 0x80A0, + + /* ErrorCode */ + NO_ERROR : 0, + INVALID_ENUM : 0x0500, + INVALID_VALUE : 0x0501, + INVALID_OPERATION : 0x0502, + OUT_OF_MEMORY : 0x0505, + + /* FrontFaceDirection */ + CW : 0x0900, + CCW : 0x0901, + + /* GetPName */ + LINE_WIDTH : 0x0B21, + ALIASED_POINT_SIZE_RANGE : 0x846D, + ALIASED_LINE_WIDTH_RANGE : 0x846E, + CULL_FACE_MODE : 0x0B45, + FRONT_FACE : 0x0B46, + DEPTH_RANGE : 0x0B70, + DEPTH_WRITEMASK : 0x0B72, + DEPTH_CLEAR_VALUE : 0x0B73, + DEPTH_FUNC : 0x0B74, + STENCIL_CLEAR_VALUE : 0x0B91, + STENCIL_FUNC : 0x0B92, + STENCIL_FAIL : 0x0B94, + STENCIL_PASS_DEPTH_FAIL : 0x0B95, + STENCIL_PASS_DEPTH_PASS : 0x0B96, + STENCIL_REF : 0x0B97, + STENCIL_VALUE_MASK : 0x0B93, + STENCIL_WRITEMASK : 0x0B98, + STENCIL_BACK_FUNC : 0x8800, + STENCIL_BACK_FAIL : 0x8801, + STENCIL_BACK_PASS_DEPTH_FAIL : 0x8802, + STENCIL_BACK_PASS_DEPTH_PASS : 0x8803, + STENCIL_BACK_REF : 0x8CA3, + STENCIL_BACK_VALUE_MASK : 0x8CA4, + STENCIL_BACK_WRITEMASK : 0x8CA5, + VIEWPORT : 0x0BA2, + SCISSOR_BOX : 0x0C10, + /* SCISSOR_TEST */ + COLOR_CLEAR_VALUE : 0x0C22, + COLOR_WRITEMASK : 0x0C23, + UNPACK_ALIGNMENT : 0x0CF5, + PACK_ALIGNMENT : 0x0D05, + MAX_TEXTURE_SIZE : 0x0D33, + MAX_VIEWPORT_DIMS : 0x0D3A, + SUBPIXEL_BITS : 0x0D50, + RED_BITS : 0x0D52, + GREEN_BITS : 0x0D53, + BLUE_BITS : 0x0D54, + ALPHA_BITS : 0x0D55, + DEPTH_BITS : 0x0D56, + STENCIL_BITS : 0x0D57, + POLYGON_OFFSET_UNITS : 0x2A00, + /* POLYGON_OFFSET_FILL */ + POLYGON_OFFSET_FACTOR : 0x8038, + TEXTURE_BINDING_2D : 0x8069, + SAMPLE_BUFFERS : 0x80A8, + SAMPLES : 0x80A9, + SAMPLE_COVERAGE_VALUE : 0x80AA, + SAMPLE_COVERAGE_INVERT : 0x80AB, + + /* GetTextureParameter */ + /* TEXTURE_MAG_FILTER */ + /* TEXTURE_MIN_FILTER */ + /* TEXTURE_WRAP_S */ + /* TEXTURE_WRAP_T */ + + COMPRESSED_TEXTURE_FORMATS : 0x86A3, + + /* HintMode */ + DONT_CARE : 0x1100, + FASTEST : 0x1101, + NICEST : 0x1102, + + /* HintTarget */ + GENERATE_MIPMAP_HINT : 0x8192, + + /* DataType */ + BYTE : 0x1400, + UNSIGNED_BYTE : 0x1401, + SHORT : 0x1402, + UNSIGNED_SHORT : 0x1403, + INT : 0x1404, + UNSIGNED_INT : 0x1405, + FLOAT : 0x1406, + + /* PixelFormat */ + DEPTH_COMPONENT : 0x1902, + ALPHA : 0x1906, + RGB : 0x1907, + RGBA : 0x1908, + LUMINANCE : 0x1909, + LUMINANCE_ALPHA : 0x190A, + + /* PixelType */ + /* UNSIGNED_BYTE */ + UNSIGNED_SHORT_4_4_4_4 : 0x8033, + UNSIGNED_SHORT_5_5_5_1 : 0x8034, + UNSIGNED_SHORT_5_6_5 : 0x8363, + + /* Shaders */ + FRAGMENT_SHADER : 0x8B30, + VERTEX_SHADER : 0x8B31, + MAX_VERTEX_ATTRIBS : 0x8869, + MAX_VERTEX_UNIFORM_VECTORS : 0x8DFB, + MAX_VARYING_VECTORS : 0x8DFC, + MAX_COMBINED_TEXTURE_IMAGE_UNITS : 0x8B4D, + MAX_VERTEX_TEXTURE_IMAGE_UNITS : 0x8B4C, + MAX_TEXTURE_IMAGE_UNITS : 0x8872, + MAX_FRAGMENT_UNIFORM_VECTORS : 0x8DFD, + SHADER_TYPE : 0x8B4F, + DELETE_STATUS : 0x8B80, + LINK_STATUS : 0x8B82, + VALIDATE_STATUS : 0x8B83, + ATTACHED_SHADERS : 0x8B85, + ACTIVE_UNIFORMS : 0x8B86, + ACTIVE_ATTRIBUTES : 0x8B89, + SHADING_LANGUAGE_VERSION : 0x8B8C, + CURRENT_PROGRAM : 0x8B8D, + + /* StencilFunction */ + NEVER : 0x0200, + LESS : 0x0201, + EQUAL : 0x0202, + LEQUAL : 0x0203, + GREATER : 0x0204, + NOTEQUAL : 0x0205, + GEQUAL : 0x0206, + ALWAYS : 0x0207, + + /* StencilOp */ + /* ZERO */ + KEEP : 0x1E00, + REPLACE : 0x1E01, + INCR : 0x1E02, + DECR : 0x1E03, + INVERT : 0x150A, + INCR_WRAP : 0x8507, + DECR_WRAP : 0x8508, + + /* StringName */ + VENDOR : 0x1F00, + RENDERER : 0x1F01, + VERSION : 0x1F02, + + /* TextureMagFilter */ + NEAREST : 0x2600, + LINEAR : 0x2601, + + /* TextureMinFilter */ + /* NEAREST */ + /* LINEAR */ + NEAREST_MIPMAP_NEAREST : 0x2700, + LINEAR_MIPMAP_NEAREST : 0x2701, + NEAREST_MIPMAP_LINEAR : 0x2702, + LINEAR_MIPMAP_LINEAR : 0x2703, + + /* TextureParameterName */ + TEXTURE_MAG_FILTER : 0x2800, + TEXTURE_MIN_FILTER : 0x2801, + TEXTURE_WRAP_S : 0x2802, + TEXTURE_WRAP_T : 0x2803, + + /* TextureTarget */ + TEXTURE_2D : 0x0DE1, + TEXTURE : 0x1702, + + TEXTURE_CUBE_MAP : 0x8513, + TEXTURE_BINDING_CUBE_MAP : 0x8514, + TEXTURE_CUBE_MAP_POSITIVE_X : 0x8515, + TEXTURE_CUBE_MAP_NEGATIVE_X : 0x8516, + TEXTURE_CUBE_MAP_POSITIVE_Y : 0x8517, + TEXTURE_CUBE_MAP_NEGATIVE_Y : 0x8518, + TEXTURE_CUBE_MAP_POSITIVE_Z : 0x8519, + TEXTURE_CUBE_MAP_NEGATIVE_Z : 0x851A, + MAX_CUBE_MAP_TEXTURE_SIZE : 0x851C, + + /* TextureUnit */ + TEXTURE0 : 0x84C0, + TEXTURE1 : 0x84C1, + TEXTURE2 : 0x84C2, + TEXTURE3 : 0x84C3, + TEXTURE4 : 0x84C4, + TEXTURE5 : 0x84C5, + TEXTURE6 : 0x84C6, + TEXTURE7 : 0x84C7, + TEXTURE8 : 0x84C8, + TEXTURE9 : 0x84C9, + TEXTURE10 : 0x84CA, + TEXTURE11 : 0x84CB, + TEXTURE12 : 0x84CC, + TEXTURE13 : 0x84CD, + TEXTURE14 : 0x84CE, + TEXTURE15 : 0x84CF, + TEXTURE16 : 0x84D0, + TEXTURE17 : 0x84D1, + TEXTURE18 : 0x84D2, + TEXTURE19 : 0x84D3, + TEXTURE20 : 0x84D4, + TEXTURE21 : 0x84D5, + TEXTURE22 : 0x84D6, + TEXTURE23 : 0x84D7, + TEXTURE24 : 0x84D8, + TEXTURE25 : 0x84D9, + TEXTURE26 : 0x84DA, + TEXTURE27 : 0x84DB, + TEXTURE28 : 0x84DC, + TEXTURE29 : 0x84DD, + TEXTURE30 : 0x84DE, + TEXTURE31 : 0x84DF, + ACTIVE_TEXTURE : 0x84E0, + + /* TextureWrapMode */ + REPEAT : 0x2901, + CLAMP_TO_EDGE : 0x812F, + MIRRORED_REPEAT : 0x8370, + + /* Uniform Types */ + FLOAT_VEC2 : 0x8B50, + FLOAT_VEC3 : 0x8B51, + FLOAT_VEC4 : 0x8B52, + INT_VEC2 : 0x8B53, + INT_VEC3 : 0x8B54, + INT_VEC4 : 0x8B55, + BOOL : 0x8B56, + BOOL_VEC2 : 0x8B57, + BOOL_VEC3 : 0x8B58, + BOOL_VEC4 : 0x8B59, + FLOAT_MAT2 : 0x8B5A, + FLOAT_MAT3 : 0x8B5B, + FLOAT_MAT4 : 0x8B5C, + SAMPLER_2D : 0x8B5E, + SAMPLER_CUBE : 0x8B60, + + /* Vertex Arrays */ + VERTEX_ATTRIB_ARRAY_ENABLED : 0x8622, + VERTEX_ATTRIB_ARRAY_SIZE : 0x8623, + VERTEX_ATTRIB_ARRAY_STRIDE : 0x8624, + VERTEX_ATTRIB_ARRAY_TYPE : 0x8625, + VERTEX_ATTRIB_ARRAY_NORMALIZED : 0x886A, + VERTEX_ATTRIB_ARRAY_POINTER : 0x8645, + VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : 0x889F, + + /* Shader Source */ + COMPILE_STATUS : 0x8B81, + + /* Shader Precision-Specified Types */ + LOW_FLOAT : 0x8DF0, + MEDIUM_FLOAT : 0x8DF1, + HIGH_FLOAT : 0x8DF2, + LOW_INT : 0x8DF3, + MEDIUM_INT : 0x8DF4, + HIGH_INT : 0x8DF5, + + /* Framebuffer Object. */ + FRAMEBUFFER : 0x8D40, + RENDERBUFFER : 0x8D41, + + RGBA4 : 0x8056, + RGB5_A1 : 0x8057, + RGB565 : 0x8D62, + DEPTH_COMPONENT16 : 0x81A5, + STENCIL_INDEX : 0x1901, + STENCIL_INDEX8 : 0x8D48, + DEPTH_STENCIL : 0x84F9, + + RENDERBUFFER_WIDTH : 0x8D42, + RENDERBUFFER_HEIGHT : 0x8D43, + RENDERBUFFER_INTERNAL_FORMAT : 0x8D44, + RENDERBUFFER_RED_SIZE : 0x8D50, + RENDERBUFFER_GREEN_SIZE : 0x8D51, + RENDERBUFFER_BLUE_SIZE : 0x8D52, + RENDERBUFFER_ALPHA_SIZE : 0x8D53, + RENDERBUFFER_DEPTH_SIZE : 0x8D54, + RENDERBUFFER_STENCIL_SIZE : 0x8D55, + + FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE : 0x8CD0, + FRAMEBUFFER_ATTACHMENT_OBJECT_NAME : 0x8CD1, + FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL : 0x8CD2, + FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE : 0x8CD3, + + COLOR_ATTACHMENT0 : 0x8CE0, + DEPTH_ATTACHMENT : 0x8D00, + STENCIL_ATTACHMENT : 0x8D20, + DEPTH_STENCIL_ATTACHMENT : 0x821A, + + NONE : 0, + + FRAMEBUFFER_COMPLETE : 0x8CD5, + FRAMEBUFFER_INCOMPLETE_ATTACHMENT : 0x8CD6, + FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT : 0x8CD7, + FRAMEBUFFER_INCOMPLETE_DIMENSIONS : 0x8CD9, + FRAMEBUFFER_UNSUPPORTED : 0x8CDD, + + FRAMEBUFFER_BINDING : 0x8CA6, + RENDERBUFFER_BINDING : 0x8CA7, + MAX_RENDERBUFFER_SIZE : 0x84E8, + + INVALID_FRAMEBUFFER_OPERATION : 0x0506, + + /* WebGL-specific enums */ + UNPACK_FLIP_Y_WEBGL : 0x9240, + UNPACK_PREMULTIPLY_ALPHA_WEBGL : 0x9241, + CONTEXT_LOST_WEBGL : 0x9242, + UNPACK_COLORSPACE_CONVERSION_WEBGL : 0x9243, + BROWSER_DEFAULT_WEBGL : 0x9244, + + items: {}, + id: 0, + getExtension: function() { return 1 }, + createBuffer: function() { + var id = this.id++; + this.items[id] = { + which: 'buffer', + }; + return id; + }, + deleteBuffer: function(){}, + bindBuffer: function(){}, + bufferData: function(){}, + getParameter: function(pname) { + switch(pname) { + case /* GL_VENDOR */ 0x1F00: return 'FakeShellGLVendor'; + case /* GL_RENDERER */ 0x1F01: return 'FakeShellGLRenderer'; + case /* GL_VERSION */ 0x1F02: return '0.0.1'; + case /* GL_MAX_TEXTURE_SIZE */ 0x0D33: return 16384; + case /* GL_MAX_CUBE_MAP_TEXTURE_SIZE */ 0x851C: return 16384; + case /* GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT */ 0x84FF: return 16; + case /* GL_MAX_TEXTURE_IMAGE_UNITS_NV */ 0x8872: return 16; + case /* GL_MAX_VERTEX_UNIFORM_VECTORS */ 0x8DFB: return 4096; + case /* GL_MAX_FRAGMENT_UNIFORM_VECTORS */ 0x8DFD: return 4096; + case /* GL_MAX_VARYING_VECTORS */ 0x8DFC: return 32; + case /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS */ 0x8B4D: return 32; + default: console.log('getParameter ' + pname + '?'); return 0; + } + }, + getSupportedExtensions: function() { + return ["OES_texture_float", "OES_standard_derivatives", "EXT_texture_filter_anisotropic", "MOZ_EXT_texture_filter_anisotropic", "MOZ_WEBGL_lose_context", "MOZ_WEBGL_compressed_texture_s3tc", "MOZ_WEBGL_depth_texture"]; + }, + createShader: function(type) { + var id = this.id++; + this.items[id] = { + which: 'shader', + type: type, + }; + return id; + }, + getShaderParameter: function(shader, pname) { + switch(pname) { + case /* GL_SHADER_TYPE */ 0x8B4F: return this.items[shader].type; + case /* GL_COMPILE_STATUS */ 0x8B81: return true; + default: throw 'getShaderParameter ' + pname; + } + }, + shaderSource: function(){}, + compileShader: function(){}, + createProgram: function() { + var id = this.id++; + this.items[id] = { + which: 'program', + shaders: [], + }; + return id; + }, + attachShader: function(program, shader) { + this.items[program].shaders.push(shader); + }, + bindAttribLocation: function(){}, + linkProgram: function(){}, + getProgramParameter: function(program, pname) { + switch(pname) { + case /* LINK_STATUS */ 0x8B82: return true; + case /* ACTIVE_UNIFORMS */ 0x8B86: return 4; + default: throw 'getProgramParameter ' + pname; + } + }, + deleteShader: function(){}, + deleteProgram: function(){}, + viewport: function(){}, + clearColor: function(){}, + clearDepth: function(){}, + depthFunc: function(){}, + enable: function(){}, + disable: function(){}, + frontFace: function(){}, + cullFace: function(){}, + activeTexture: function(){}, + createTexture: function() { + var id = this.id++; + this.items[id] = { + which: 'texture', + }; + return id; + }, + deleteTexture: function(){}, + boundTextures: {}, + bindTexture: function(target, texture) { + this.boundTextures[target] = texture; + }, + texParameteri: function(){}, + pixelStorei: function(){}, + texImage2D: function(){}, + compressedTexImage2D: function(){}, + useProgram: function(){}, + getUniformLocation: function() { + return null; + }, + getActiveUniform: function(program, index) { + return { + size: 1, + type: /* INT_VEC3 */ 0x8B54, + name: 'activeUniform' + index, + }; + }, + clear: function(){}, + uniform4fv: function(){}, + uniform1i: function(){}, + getAttribLocation: function() { return 1 }, + vertexAttribPointer: function(){}, + enableVertexAttribArray: function(){}, + disableVertexAttribArray: function(){}, + drawElements: function(){}, + drawArrays: function(){}, + depthMask: function(){}, + depthRange: function(){}, + bufferSubData: function(){}, + blendFunc: function(){}, + createFramebuffer: function() { + var id = this.id++; + this.items[id] = { + which: 'framebuffer', + shaders: [], + }; + return id; + }, + bindFramebuffer: function(){}, + framebufferTexture2D: function(){}, + checkFramebufferStatus: function() { + return /* FRAMEBUFFER_COMPLETE */ 0x8CD5; + }, + createRenderbuffer: function() { + var id = this.id++; + this.items[id] = { + which: 'renderbuffer', + shaders: [], + }; + return id; + }, + bindRenderbuffer: function(){}, + renderbufferStorage: function(){}, + framebufferRenderbuffer: function(){}, + scissor: function(){}, + colorMask: function(){}, + lineWidth: function(){}, + vertexAttrib4fv: function(){}, + }; + } + case '2d': { + return { + drawImage: function(){}, + getImageData: function(x, y, w, h) { + return { + width: w, + height: h, + data: new Uint8ClampedArray(w*h), + }; + }, + save: function(){}, + restore: function(){}, + fillRect: function(){}, + measureText: function() { return 10 }, + fillText: function(){}, + }; + } + default: throw 'canvas.getContext: ' + which; + } + }, + requestPointerLock: function() { + document.pointerLockElement = document.getElementById('canvas'); + window.setTimeout(function() { + document.callEventListeners('pointerlockchange'); + }); + }, + exitPointerLock: function(){}, + style: {}, + eventListeners: {}, + addEventListener: function(){}, + requestFullScreen: function() { + document.fullscreenElement = document.getElementById('canvas'); + window.setTimeout(function() { + document.callEventListeners('fullscreenchange'); + }); + }, + offsetTop: 0, + offsetLeft: 0, + // generics + classList: { + add: function(){}, + remove: function(){}, + }, + }; +} + diff --git a/src/jsifier.js b/src/jsifier.js index 8ed19194..179a910a 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -280,7 +280,7 @@ function JSify(data, functionsOnly, givenFunctions) { // they would shadow similarly-named globals in the parent. item.JS = ''; } else { - item.JS = makeGlobalDef(item.ident); + item.JS = makeGlobalDef(item.ident); } if (!NAMED_GLOBALS && isIndexableGlobal(item.ident)) { @@ -795,7 +795,13 @@ function JSify(data, functionsOnly, givenFunctions) { var label = block.labels[i]; var content = getLabelLines(label, '', true); //printErr(func.ident + ' : ' + label.ident + ' : ' + content + '\n'); - blockMap[label.ident] = Relooper.addBlock(content); + var last = label.lines[label.lines.length-1]; + if (!last.signedIdent) { + blockMap[label.ident] = Relooper.addBlock(content); + } else { + assert(last.intertype == 'switch'); + blockMap[label.ident] = Relooper.addBlock(content, last.signedIdent); + } } // add branchings function relevant(x) { return x && x.length > 2 ? x : 0 } // ignores ';' which valueJS and label*JS can be if empty @@ -1125,7 +1131,19 @@ function JSify(data, functionsOnly, givenFunctions) { } }); makeFuncLineActor('switch', function(item) { - var useIfs = RELOOP || item.switchLabels.length < 1024; // with a huge number of cases, if-else which looks nested to js parsers can cause problems + // use a switch if the range is not too big or sparse + var minn = Infinity, maxx = -Infinity; + item.switchLabels.forEach(function(switchLabel) { + var curr = Math.abs(parseInt(switchLabel.value)); + minn = Math.min(minn, curr); + maxx = Math.max(maxx, curr); + }); + var range = maxx - minn; + var useIfs = (item.switchLabels.length+1) < 6 || range > 10*1024 || (range/item.switchLabels.length) > 1024; // heuristics + if (VERBOSE && useIfs && item.switchLabels.length > 2) { + warn('not optimizing llvm switch into js switch because ' + [range, range/item.switchLabels.length]); + } + var phiSets = calcPhiSets(item); // Consolidate checks that go to the same label. This is important because it makes the relooper simpler and faster. var targetLabels = {}; // for each target label, the list of values going to it @@ -1139,7 +1157,8 @@ function JSify(data, functionsOnly, givenFunctions) { }); var ret = ''; var first = true; - var signedIdent = makeSignOp(item.ident, item.type, 're'); // we need to standardize for purpose of comparison + signedIdent = makeSignOp(item.ident, item.type, 're'); // we need to standardize for purpose of comparison + if (!useIfs) item.signedIdent = signedIdent; if (RELOOP) { item.groupedLabels = []; } @@ -1635,7 +1654,7 @@ function JSify(data, functionsOnly, givenFunctions) { // if (!mainPass) { - if (phase == 'pre' && !Variables.generatedGlobalBase) { + if (phase == 'pre' && !Variables.generatedGlobalBase && !BUILD_AS_SHARED_LIB) { Variables.generatedGlobalBase = true; // Globals are done, here is the rest of static memory assert((TARGET_LE32 && Runtime.GLOBAL_BASE == 8) || (TARGET_X86 && Runtime.GLOBAL_BASE == 4)); // this is assumed in e.g. relocations for linkable modules @@ -1679,24 +1698,26 @@ function JSify(data, functionsOnly, givenFunctions) { print('}\n'); if (USE_TYPED_ARRAYS == 2) { - print('var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8);\n'); - print('assert(tempDoublePtr % 8 == 0);\n'); - print('function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much\n'); - print(' HEAP8[tempDoublePtr] = HEAP8[ptr];\n'); - print(' HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];\n'); - print(' HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];\n'); - print(' HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];\n'); - print('}\n'); - print('function copyTempDouble(ptr) {\n'); - print(' HEAP8[tempDoublePtr] = HEAP8[ptr];\n'); - print(' HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];\n'); - print(' HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];\n'); - print(' HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];\n'); - print(' HEAP8[tempDoublePtr+4] = HEAP8[ptr+4];\n'); - print(' HEAP8[tempDoublePtr+5] = HEAP8[ptr+5];\n'); - print(' HEAP8[tempDoublePtr+6] = HEAP8[ptr+6];\n'); - print(' HEAP8[tempDoublePtr+7] = HEAP8[ptr+7];\n'); - print('}\n'); + if (!BUILD_AS_SHARED_LIB) { + print('var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8);\n'); + print('assert(tempDoublePtr % 8 == 0);\n'); + print('function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much\n'); + print(' HEAP8[tempDoublePtr] = HEAP8[ptr];\n'); + print(' HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];\n'); + print(' HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];\n'); + print(' HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];\n'); + print('}\n'); + print('function copyTempDouble(ptr) {\n'); + print(' HEAP8[tempDoublePtr] = HEAP8[ptr];\n'); + print(' HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];\n'); + print(' HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];\n'); + print(' HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];\n'); + print(' HEAP8[tempDoublePtr+4] = HEAP8[ptr+4];\n'); + print(' HEAP8[tempDoublePtr+5] = HEAP8[ptr+5];\n'); + print(' HEAP8[tempDoublePtr+6] = HEAP8[ptr+6];\n'); + print(' HEAP8[tempDoublePtr+7] = HEAP8[ptr+7];\n'); + print('}\n'); + } } } @@ -1731,11 +1752,13 @@ function JSify(data, functionsOnly, givenFunctions) { legalizedI64s = legalizedI64sDefault; - print('STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP);\n'); - 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'); + if (!BUILD_AS_SHARED_LIB) { + print('STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP);\n'); + 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'); + } if (asmLibraryFunctions.length > 0) { print('// ASM_LIBRARY FUNCTIONS'); @@ -1802,7 +1825,9 @@ function JSify(data, functionsOnly, givenFunctions) { } if (HEADLESS) { print('if (!ENVIRONMENT_IS_WEB) {'); - print(read('headless.js').replace("'%s'", "'http://emscripten.org'").replace("'?%s'", "''").replace('%s,', 'null,').replace('%d', '0')); + print(read('headlessCanvas.js')); + print('\n'); + print(read('headless.js').replace("'%s'", "'http://emscripten.org'").replace("'?%s'", "''").replace("'?%s'", "'/'").replace('%s,', 'null,').replace('%d', '0')); print('}'); } if (RUNTIME_TYPE_INFO) { diff --git a/src/library.js b/src/library.js index 9e78db13..3ba2f56b 100644 --- a/src/library.js +++ b/src/library.js @@ -6808,24 +6808,38 @@ LibraryManager.library = { _pthread_once.seen[ptr] = 1; }, + $PTHREAD_SPECIFIC: {}, + $PTHREAD_SPECIFIC_NEXT_KEY: 1, + pthread_key_create__deps: ['$PTHREAD_SPECIFIC', '$PTHREAD_SPECIFIC_NEXT_KEY', '$ERRNO_CODES'], pthread_key_create: function(key, destructor) { - if (!_pthread_key_create.keys) _pthread_key_create.keys = {}; + if (key == 0) { + return ERRNO_CODES.EINVAL; + } + {{{ makeSetValue('key', '0', 'PTHREAD_SPECIFIC_NEXT_KEY', 'i32*') }}} // values start at 0 - _pthread_key_create.keys[key] = 0; + PTHREAD_SPECIFIC[PTHREAD_SPECIFIC_NEXT_KEY] = 0; + PTHREAD_SPECIFIC_NEXT_KEY++; + return 0; }, + pthread_getspecific__deps: ['$PTHREAD_SPECIFIC'], pthread_getspecific: function(key) { - return _pthread_key_create.keys[key] || 0; + return PTHREAD_SPECIFIC[key] || 0; }, + pthread_setspecific__deps: ['$PTHREAD_SPECIFIC', '$ERRNO_CODES'], pthread_setspecific: function(key, value) { - _pthread_key_create.keys[key] = value; + if (value == 0) { + return ERRNO_CODES.EINVAL; + } + PTHREAD_SPECIFIC[key] = value; + return 0; }, - pthread_key_delete: ['$ERRNO_CODES'], + pthread_key_delete__deps: ['$PTHREAD_SPECIFIC', '$ERRNO_CODES'], pthread_key_delete: function(key) { - if (_pthread_key_create.keys[key]) { - delete _pthread_key_create.keys[key]; + if (key in PTHREAD_SPECIFIC) { + delete PTHREAD_SPECIFIC[key]; return 0; } return ERRNO_CODES.EINVAL; diff --git a/src/library_browser.js b/src/library_browser.js index 511e158e..591a3c11 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -452,8 +452,21 @@ mergeInto(LibraryManager.library, { // Otherwise, calculate the movement based on the changes // in the coordinates. var rect = Module["canvas"].getBoundingClientRect(); - var x = event.pageX - (window.scrollX + rect.left); - var y = event.pageY - (window.scrollY + rect.top); + var x, y; + if (event.type == 'touchstart' || + event.type == 'touchend' || + event.type == 'touchmove') { + var t = event.touches.item(0); + if (t) { + x = t.pageX - (window.scrollX + rect.left); + y = t.pageY - (window.scrollY + rect.top); + } else { + return; + } + } else { + x = event.pageX - (window.scrollX + rect.left); + y = event.pageY - (window.scrollY + rect.top); + } // the canvas might be CSS-scaled compared to its backbuffer; // SDL-using content will want mouse coordinates in terms @@ -808,6 +821,13 @@ mergeInto(LibraryManager.library, { emscripten_set_canvas_size: function(width, height) { Browser.setCanvasSize(width, height); }, + + emscripten_get_canvas_size: function(width, height, isFullscreen) { + var canvas = Module['canvas']; + {{{ makeSetValue('width', '0', 'canvas.width', 'i32') }}}; + {{{ makeSetValue('height', '0', 'canvas.height', 'i32') }}}; + {{{ makeSetValue('isFullscreen', '0', 'Browser.isFullScreen ? 1 : 0', 'i32') }}}; + }, emscripten_get_now: function() { if (ENVIRONMENT_IS_NODE) { diff --git a/src/library_fs.js b/src/library_fs.js index 9d1f0cfd..e1397356 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -509,7 +509,7 @@ mergeInto(LibraryManager.library, { var mode = FS.getMode(canRead, canWrite); return FS.create(path, mode); }, - createDataFile: function(parent, name, data, canRead, canWrite) { + createDataFile: function(parent, name, data, canRead, canWrite, canOwn) { var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name); var mode = FS.getMode(canRead, canWrite); var node = FS.create(path, mode); @@ -522,7 +522,7 @@ mergeInto(LibraryManager.library, { // make sure we can write to the file FS.chmod(path, mode | {{{ cDefine('S_IWUGO') }}}); var stream = FS.open(path, 'w'); - FS.write(stream, data, 0, data.length, 0); + FS.write(stream, data, 0, data.length, 0, canOwn); FS.close(stream); FS.chmod(path, mode); } @@ -766,7 +766,7 @@ mergeInto(LibraryManager.library, { // You can also call this with a typed array instead of a url. It will then // do preloading for the Image/Audio part, as if the typed array were the // result of an XHR that you did manually. - createPreloadedFile: function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile) { + createPreloadedFile: function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn) { Browser.init(); // TODO we should allow people to just pass in a complete filename instead // of parent and name being that we just join them anyways @@ -774,7 +774,7 @@ mergeInto(LibraryManager.library, { function processData(byteArray) { function finish(byteArray) { if (!dontCreateFile) { - FS.createDataFile(parent, name, byteArray, canRead, canWrite); + FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); } if (onload) onload(); removeRunDependency('cp ' + fullname); @@ -1323,7 +1323,7 @@ mergeInto(LibraryManager.library, { if (!seeking) stream.position += bytesRead; return bytesRead; }, - write: function(stream, buffer, offset, length, position) { + write: function(stream, buffer, offset, length, position, canOwn) { if (length < 0 || position < 0) { throw new FS.ErrnoError(ERRNO_CODES.EINVAL); } @@ -1347,7 +1347,7 @@ mergeInto(LibraryManager.library, { // seek to the end before writing in append mode FS.llseek(stream, 0, {{{ cDefine('SEEK_END') }}}); } - var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position); + var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn); if (!seeking) stream.position += bytesWritten; return bytesWritten; }, diff --git a/src/library_glut.js b/src/library_glut.js index 29957e6f..60dc6540 100644 --- a/src/library_glut.js +++ b/src/library_glut.js @@ -267,11 +267,19 @@ var LibraryGLUT = { // Ignore arguments GLUT.initTime = Date.now(); + var isTouchDevice = 'ontouchstart' in document.documentElement; + window.addEventListener("keydown", GLUT.onKeydown, true); window.addEventListener("keyup", GLUT.onKeyup, true); - window.addEventListener("mousemove", GLUT.onMousemove, true); - window.addEventListener("mousedown", GLUT.onMouseButtonDown, true); - window.addEventListener("mouseup", GLUT.onMouseButtonUp, true); + if (isTouchDevice) { + window.addEventListener("touchmove", GLUT.onMousemove, true); + window.addEventListener("touchstart", GLUT.onMouseButtonDown, true); + window.addEventListener("touchend", GLUT.onMouseButtonUp, true); + } else { + window.addEventListener("mousemove", GLUT.onMousemove, true); + window.addEventListener("mousedown", GLUT.onMouseButtonDown, true); + window.addEventListener("mouseup", GLUT.onMouseButtonUp, true); + } Browser.resizeListeners.push(function(width, height) { if (GLUT.reshapeFunc) { @@ -282,9 +290,15 @@ var LibraryGLUT = { __ATEXIT__.push({ func: function() { window.removeEventListener("keydown", GLUT.onKeydown, true); window.removeEventListener("keyup", GLUT.onKeyup, true); - window.removeEventListener("mousemove", GLUT.onMousemove, true); - window.removeEventListener("mousedown", GLUT.onMouseButtonDown, true); - window.removeEventListener("mouseup", GLUT.onMouseButtonUp, true); + if (isTouchDevice) { + window.removeEventListener("touchmove", GLUT.onMousemove, true); + window.removeEventListener("touchstart", GLUT.onMouseButtonDown, true); + window.removeEventListener("touchend", GLUT.onMouseButtonUp, true); + } else { + window.removeEventListener("mousemove", GLUT.onMousemove, true); + window.removeEventListener("mousedown", GLUT.onMouseButtonDown, true); + window.removeEventListener("mouseup", GLUT.onMouseButtonUp, true); + } Module["canvas"].width = Module["canvas"].height = 1; } }); }, diff --git a/src/library_memfs.js b/src/library_memfs.js index 0fa6cdfb..63326c42 100644 --- a/src/library_memfs.js +++ b/src/library_memfs.js @@ -1,6 +1,22 @@ mergeInto(LibraryManager.library, { $MEMFS__deps: ['$FS'], $MEMFS: { + // content modes + CONTENT_OWNING: 1, // contains a subarray into the heap, and we own it - need to free() when no longer needed + CONTENT_FLEXIBLE: 2, // has been modified or never set to anything, and is a flexible js array that can grow/shrink + CONTENT_FIXED: 3, // contains some fixed-size content written into it, in a typed array + ensureFlexible: function(node) { + if (node.contentMode !== MEMFS.CONTENT_FLEXIBLE) { + var contents = node.contents; + node.contents = Array.prototype.slice.call(contents); + if (node.contentMode === MEMFS.CONTENT_OWNING) { + assert(contents.byteOffset); + Module['_free'](contents.byteOffset); + } + node.contentMode = MEMFS.CONTENT_FLEXIBLE; + } + }, + mount: function(mount) { return MEMFS.create_node(null, '/', {{{ cDefine('S_IFDIR') }}} | 0777, 0); }, @@ -40,6 +56,7 @@ mergeInto(LibraryManager.library, { mmap: MEMFS.stream_ops.mmap }; node.contents = []; + node.contentMode = MEMFS.CONTENT_FLEXIBLE; } else if (FS.isLink(node.mode)) { node.node_ops = { getattr: MEMFS.node_ops.getattr, @@ -98,6 +115,7 @@ mergeInto(LibraryManager.library, { node.timestamp = attr.timestamp; } if (attr.size !== undefined) { + MEMFS.ensureFlexible(node); var contents = node.contents; if (attr.size < contents.length) contents.length = attr.size; else while (attr.size > contents.length) contents.push(0); @@ -165,7 +183,7 @@ mergeInto(LibraryManager.library, { var contents = stream.node.contents; var size = Math.min(contents.length - position, length); #if USE_TYPED_ARRAYS == 2 - if (contents.subarray) { // typed array + if (size > 8 && contents.subarray) { // non-trivial, and typed array buffer.set(contents.subarray(position, position + size), offset); } else #endif @@ -176,13 +194,30 @@ mergeInto(LibraryManager.library, { } return size; }, - write: function(stream, buffer, offset, length, position) { - var contents = stream.node.contents; + write: function(stream, buffer, offset, length, position, canOwn) { + var node = stream.node; + node.timestamp = Date.now(); + var contents = node.contents; +#if USE_TYPED_ARRAYS == 2 + if (length && contents.length === 0 && position === 0 && buffer.subarray) { + // just replace it with the new data + assert(buffer.length); + if (canOwn && buffer.buffer === HEAP8.buffer && offset === 0) { + node.contents = buffer; // this is a subarray of the heap, and we can own it + node.contentMode = MEMFS.CONTENT_OWNING; + } else { + node.contents = new Uint8Array(buffer.subarray(offset, offset+length)); + node.contentMode = MEMFS.CONTENT_FIXED; + } + return length; + } +#endif + MEMFS.ensureFlexible(node); + var contents = node.contents; while (contents.length < position) contents.push(0); for (var i = 0; i < length; i++) { contents[position + i] = buffer[offset + i]; } - stream.node.timestamp = Date.now(); return length; }, llseek: function(stream, offset, whence) { @@ -202,6 +237,7 @@ mergeInto(LibraryManager.library, { return position; }, allocate: function(stream, offset, length) { + MEMFS.ensureFlexible(stream.node); var contents = stream.node.contents; var limit = offset + length; while (limit > contents.length) contents.push(0); @@ -214,10 +250,10 @@ mergeInto(LibraryManager.library, { var allocated; var contents = stream.node.contents; // Only make a new copy when MAP_PRIVATE is specified. - if (!(flags & {{{ cDefine('MAP_PRIVATE') }}})) { + if ( !(flags & {{{ cDefine('MAP_PRIVATE') }}}) && + (contents.buffer === buffer || contents.buffer === buffer.buffer) ) { // We can't emulate MAP_SHARED when the file is not backed by the buffer // we're mapping to (e.g. the HEAP buffer). - assert(contents.buffer === buffer || contents.buffer === buffer.buffer); allocated = false; ptr = contents.byteOffset; } else { @@ -240,4 +276,5 @@ mergeInto(LibraryManager.library, { }, } } -});
\ No newline at end of file +}); + diff --git a/src/library_openal.js b/src/library_openal.js index cbb5c0bb..dea986f3 100644 --- a/src/library_openal.js +++ b/src/library_openal.js @@ -8,6 +8,12 @@ var LibraryOpenAL = { QUEUE_INTERVAL: 25, QUEUE_LOOKAHEAD: 100, + getCurrentTime: function(context) { + // currentTime is frozen during execution, use performance timers to + // emulate the current time at call time + return (window['performance']['now']() - context.startTime) / 1000.0; + }, + updateSources: function(context) { for (var i = 0; i < context.src.length; i++) { AL.updateSource(context.src[i]); @@ -22,7 +28,7 @@ var LibraryOpenAL = { return; } - var currentTime = AL.currentContext.ctx.currentTime; + var currentTime = AL.getCurrentTime(AL.currentContext); var startTime = src.bufferPosition; for (var i = src.buffersPlayed; i < src.queue.length; i++) { @@ -73,7 +79,7 @@ var LibraryOpenAL = { if (src.state !== 0x1013 /* AL_PAUSED */) { src.state = 0x1012 /* AL_PLAYING */; // Reset our position. - src.bufferPosition = AL.currentContext.ctx.currentTime; + src.bufferPosition = AL.getCurrentTime(AL.currentContext); src.buffersPlayed = 0; #if OPENAL_DEBUG console.log('setSourceState resetting and playing source ' + idx); @@ -81,7 +87,7 @@ var LibraryOpenAL = { } else { src.state = 0x1012 /* AL_PLAYING */; // Use the current offset from src.bufferPosition to resume at the correct point. - src.bufferPosition = AL.currentContext.ctx.currentTime - src.bufferPosition; + src.bufferPosition = AL.getCurrentTime(AL.currentContext) - src.bufferPosition; #if OPENAL_DEBUG console.log('setSourceState resuming source ' + idx + ' at ' + src.bufferPosition.toFixed(4)); #endif @@ -92,7 +98,7 @@ var LibraryOpenAL = { if (src.state === 0x1012 /* AL_PLAYING */) { src.state = 0x1013 /* AL_PAUSED */; // Store off the current offset to restore with on resume. - src.bufferPosition = AL.currentContext.ctx.currentTime - src.bufferPosition; + src.bufferPosition = AL.getCurrentTime(AL.currentContext) - src.bufferPosition; AL.stopSourceQueue(src); #if OPENAL_DEBUG console.log('setSourceState pausing source ' + idx + ' at ' + src.bufferPosition.toFixed(4)); @@ -206,7 +212,8 @@ var LibraryOpenAL = { err: 0, src: [], buf: [], - interval: setInterval(function() { AL.updateSources(context); }, AL.QUEUE_INTERVAL) + interval: setInterval(function() { AL.updateSources(context); }, AL.QUEUE_INTERVAL), + startTime: window['performance']['now']() }; AL.contexts.push(context); return AL.contexts.length; @@ -237,7 +244,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alDeleteSources called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } for (var i = 0; i < count; ++i) { @@ -251,7 +257,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alGenSources called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } for (var i = 0; i < count; ++i) { @@ -311,7 +316,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alSourcei called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; @@ -380,7 +384,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alSourcef called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; @@ -433,7 +436,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alSource3f called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; @@ -474,7 +476,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alSourceQueueBuffers called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; @@ -511,7 +512,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alSourceUnqueueBuffers called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; @@ -550,7 +550,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alDeleteBuffers called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } if (count > AL.currentContext.buf.length) { @@ -594,7 +593,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alGenBuffers called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } for (var i = 0; i < count; ++i) { @@ -608,7 +606,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alBufferData called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } if (buffer > AL.currentContext.buf.length) { @@ -673,7 +670,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alSourcePlay called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; @@ -693,7 +689,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alSourceStop called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; @@ -713,7 +708,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alSourcePause called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; @@ -733,7 +727,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alGetSourcei called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; @@ -797,7 +790,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alGetSourcef called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } var src = AL.currentContext.src[source - 1]; @@ -858,7 +850,6 @@ var LibraryOpenAL = { #if OPENAL_DEBUG console.error("alListenerfv called without a valid context"); #endif - AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */; return; } switch (param) { diff --git a/src/library_sdl.js b/src/library_sdl.js index 236ab1bf..1fb75724 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -379,7 +379,8 @@ var LibrarySDL = { SDL.surfaces[surf] = null; }, - touchX:0, touchY: 0, + touchX: 0, touchY: 0, + savedKeydown: null, receiveEvent: function(event) { switch(event.type) { @@ -466,11 +467,29 @@ var LibrarySDL = { SDL.DOMButtons[event.button] = 0; } - if (event.type == 'keypress' && !SDL.textInput) { - break; + // SDL expects a unicode character to be passed to its keydown events. + // Unfortunately, the browser APIs only provide a charCode property on + // keypress events, so we must backfill in keydown events with their + // subsequent keypress event's charCode. + if (event.type === 'keypress' && SDL.savedKeydown) { + // charCode is read-only + SDL.savedKeydown.keypressCharCode = event.charCode; + SDL.savedKeydown = null; + } else if (event.type === 'keydown') { + SDL.savedKeydown = event; + } + + // If we preventDefault on keydown events, the subsequent keypress events + // won't fire. However, it's fine (and in some cases necessary) to + // preventDefault for keys that don't generate a character. + if (event.type !== 'keydown' || (event.keyCode === 8 /* backspace */ || event.keyCode === 9 /* tab */)) { + event.preventDefault(); + } + + // Don't push keypress events unless SDL_StartTextInput has been called. + if (event.type !== 'keypress' || SDL.textInput) { + SDL.events.push(event); } - - SDL.events.push(event); break; case 'mouseout': // Un-press all pressed mouse buttons, because we might miss the release outside of the canvas @@ -485,6 +504,7 @@ var LibrarySDL = { SDL.DOMButtons[i] = 0; } } + event.preventDefault(); break; case 'blur': case 'visibilitychange': { @@ -495,6 +515,7 @@ var LibrarySDL = { keyCode: SDL.keyboardMap[code] }); } + event.preventDefault(); break; } case 'unload': @@ -506,16 +527,16 @@ var LibrarySDL = { return; case 'resize': SDL.events.push(event); + // manually triggered resize event doesn't have a preventDefault member + if (event.preventDefault) { + event.preventDefault(); + } break; } if (SDL.events.length >= 10000) { Module.printErr('SDL event queue full, dropping events'); SDL.events = SDL.events.slice(0, 10000); } - // manually triggered resize event doesn't have a preventDefault member - if (event.preventDefault) { - event.preventDefault(); - } return; }, @@ -526,7 +547,12 @@ var LibrarySDL = { switch (event.type) { case 'keydown': case 'keyup': { var down = event.type === 'keydown'; - var code = SDL.keyCodes[event.keyCode] || event.keyCode; + var code = event.keyCode; + if (code >= 65 && code <= 90) { + code += 32; // make lowercase for SDL + } else { + code = SDL.keyCodes[event.keyCode] || event.keyCode; + } {{{ makeSetValue('SDL.keyboardState', 'code', 'down', 'i8') }}}; // TODO: lmeta, rmeta, numlock, capslock, KMOD_MODE, KMOD_RESERVED @@ -590,8 +616,9 @@ var LibrarySDL = { {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.repeat', '0', 'i8') }}} // TODO {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.scancode', 'scan', 'i32') }}} {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.sym', 'key', 'i32') }}} - {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.mod', 'SDL.modState', 'i32') }}} - {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.unicode', 'key', 'i32') }}} + {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.mod', 'SDL.modState', 'i16') }}} + // some non-character keys (e.g. backspace and tab) won't have keypressCharCode set, fill in with the keyCode. + {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.unicode', 'event.keypressCharCode || key', 'i32') }}} break; } diff --git a/src/parseTools.js b/src/parseTools.js index 65e96264..046dac1b 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -727,15 +727,37 @@ function makeI64(low, high) { // Splits a number (an integer in a double, possibly > 32 bits) into an USE_TYPED_ARRAYS == 2 i64 value. // Will suffer from rounding. mergeI64 does the opposite. function splitI64(value, floatConversion) { - // We need to min here, since our input might be a double, and large values are rounded, so they can + // general idea: + // + // $1$0 = ~~$d >>> 0; + // $1$1 = Math_abs($d) >= 1 ? ( + // $d > 0 ? Math.min(Math_floor(($d)/ 4294967296.0), 4294967295.0) + // : Math_ceil(Math.min(-4294967296.0, $d - $1$0)/ 4294967296.0) + // ) : 0; + // + // We need to min on positive values here, since our input might be a double, and large values are rounded, so they can // be slightly higher than expected. And if we get 4294967296, that will turn into a 0 if put into a // HEAP32 or |0'd, etc. + // + // For negatives, we need to ensure a -1 if the value is overall negative, even if not significant negative component + var lowInput = legalizedI64s ? value : 'VALUE'; if (floatConversion && ASM_JS) lowInput = asmFloatToInt(lowInput); + var low = lowInput + '>>>0'; + var high = makeInlineCalculation( + asmCoercion('Math.abs(VALUE)', 'double') + ' >= ' + asmEnsureFloat('1', 'double') + ' ? ' + + '(VALUE > ' + asmEnsureFloat('0', 'double') + ' ? ' + + asmCoercion('Math.min(' + asmCoercion('Math.floor((VALUE)/' + asmEnsureFloat(4294967296, 'float') + ')', 'double') + ', ' + asmEnsureFloat(4294967295, 'float') + ')', 'i32') + '>>>0' + + ' : ' + asmFloatToInt(asmCoercion('Math.ceil((VALUE - +((' + asmFloatToInt('VALUE') + ')>>>0))/' + asmEnsureFloat(4294967296, 'float') + ')', 'double')) + '>>>0' + + ')' + + ' : 0', + value, + 'tempDouble' + ); if (legalizedI64s) { - return [lowInput + '>>>0', asmCoercion('Math.min(' + asmCoercion('Math.floor((' + value + ')/' + asmEnsureFloat(4294967296, 'float') + ')', 'double') + ', ' + asmEnsureFloat(4294967295, 'float') + ')', 'i32') + '>>>0']; + return [low, high]; } else { - return makeInlineCalculation(makeI64(lowInput + '>>>0', asmCoercion('Math.min(' + asmCoercion('Math.floor(VALUE/' + asmEnsureFloat(4294967296, 'float') + ')', 'double') + ', ' + asmEnsureFloat(4294967295, 'float') + ')', 'i32') + '>>>0'), value, 'tempBigIntP'); + return makeI64(low, high); } } function mergeI64(value, unsigned) { diff --git a/src/postamble.js b/src/postamble.js index 08c3a9d8..df844121 100644 --- a/src/postamble.js +++ b/src/postamble.js @@ -11,12 +11,18 @@ ExitStatus.prototype.constructor = ExitStatus; var initialStackTop; +var preloadStartTime = null; + Module['callMain'] = Module.callMain = function callMain(args) { assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on __ATMAIN__)'); assert(__ATPRERUN__.length == 0, 'cannot call main when preRun functions remain to be called'); args = args || []; + if (ENVIRONMENT_IS_WEB && preloadStartTime !== null) { + Module.printErr('preload time: ' + (Date.now() - preloadStartTime) + ' ms'); + } + ensureInitRuntime(); var argc = args.length+1; @@ -72,6 +78,8 @@ Module['callMain'] = Module.callMain = function callMain(args) { function run(args) { args = args || Module['arguments']; + if (preloadStartTime === null) preloadStartTime = Date.now(); + if (runDependencies > 0) { Module.printErr('run() called, but dependencies remain, so not running'); return; diff --git a/src/preamble.js b/src/preamble.js index 0f3f52c9..4cae05a6 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -524,6 +524,7 @@ function allocate(slab, types, allocator, ptr) { Module['allocate'] = allocate; function Pointer_stringify(ptr, /* optional */ length) { + // TODO: use TextDecoder // Find the length, and check for UTF while doing so var hasUtf = false; var t; diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp index a457914b..afb6ecc8 100644 --- a/src/relooper/Relooper.cpp +++ b/src/relooper/Relooper.cpp @@ -104,12 +104,14 @@ void Branch::Render(Block *Target, bool SetLabel) { int Block::IdCounter = 1; // 0 is reserved for clearings -Block::Block(const char *CodeInit) : Parent(NULL), Id(Block::IdCounter++), IsCheckedMultipleEntry(false) { +Block::Block(const char *CodeInit, const char *BranchVarInit) : Parent(NULL), Id(Block::IdCounter++), IsCheckedMultipleEntry(false) { Code = strdup(CodeInit); + BranchVar = BranchVarInit ? strdup(BranchVarInit) : NULL; } Block::~Block() { if (Code) free((void*)Code); + if (BranchVar) free((void*)BranchVar); for (BlockBranchMap::iterator iter = ProcessedBranchesOut.begin(); iter != ProcessedBranchesOut.end(); iter++) { delete iter->second; } @@ -189,8 +191,14 @@ void Block::Render(bool InLoop) { } assert(DefaultTarget); // Since each block *must* branch somewhere, this must be set + bool useSwitch = BranchVar != NULL; + + if (useSwitch) { + PrintIndented("switch (%s) {\n", BranchVar); + } + ministring RemainingConditions; - bool First = true; + bool First = !useSwitch; // when using a switch, there is no special first for (BlockBranchMap::iterator iter = ProcessedBranchesOut.begin();; iter++) { Block *Target; Branch *Details; @@ -208,26 +216,39 @@ void Block::Render(bool InLoop) { bool HasContent = SetCurrLabel || Details->Type != Branch::Direct || HasFusedContent || Details->Code; if (iter != ProcessedBranchesOut.end()) { // If there is nothing to show in this branch, omit the condition - if (HasContent) { - PrintIndented("%sif (%s) {\n", First ? "" : "} else ", Details->Condition); - First = false; + if (useSwitch) { + PrintIndented("%s {\n", Details->Condition); } else { - if (RemainingConditions.size() > 0) RemainingConditions += " && "; - RemainingConditions += "!("; - RemainingConditions += Details->Condition; - RemainingConditions += ")"; + if (HasContent) { + PrintIndented("%sif (%s) {\n", First ? "" : "} else ", Details->Condition); + First = false; + } else { + if (RemainingConditions.size() > 0) RemainingConditions += " && "; + RemainingConditions += "!("; + if (BranchVar) { + RemainingConditions += BranchVar; + RemainingConditions += " == "; + } + RemainingConditions += Details->Condition; + RemainingConditions += ")"; + } } } else { - if (HasContent) { - if (RemainingConditions.size() > 0) { - if (First) { - PrintIndented("if (%s) {\n", RemainingConditions.c_str()); - First = false; - } else { - PrintIndented("} else if (%s) {\n", RemainingConditions.c_str()); + // this is the default + if (useSwitch) { + PrintIndented("default: {\n"); + } else { + if (HasContent) { + if (RemainingConditions.size() > 0) { + if (First) { + PrintIndented("if (%s) {\n", RemainingConditions.c_str()); + First = false; + } else { + PrintIndented("} else if (%s) {\n", RemainingConditions.c_str()); + } + } else if (!First) { + PrintIndented("} else {\n"); } - } else if (!First) { - PrintIndented("} else {\n"); } } } @@ -236,7 +257,13 @@ void Block::Render(bool InLoop) { if (HasFusedContent) { Fused->InnerMap.find(Target)->second->Render(InLoop); } + if (useSwitch && iter != ProcessedBranchesOut.end()) { + PrintIndented("break;\n"); + } if (!First) Indenter::Unindent(); + if (useSwitch) { + PrintIndented("}\n"); + } if (iter == ProcessedBranchesOut.end()) break; } if (!First) PrintIndented("}\n"); @@ -392,7 +419,7 @@ void Relooper::Calculate(Block *Entry) { PrintDebug("Splitting block %d\n", Original->Id); for (BlockSet::iterator iter = Original->BranchesIn.begin(); iter != Original->BranchesIn.end(); iter++) { Block *Prior = *iter; - Block *Split = new Block(Original->Code); + Block *Split = new Block(Original->Code, Original->BranchVar); Parent->Blocks.push_back(Split); PrintDebug(" to %d\n", Split->Id); Split->BranchesIn.insert(Prior); @@ -975,6 +1002,8 @@ void Relooper::Calculate(Block *Entry) { Root = Next; Next = NULL; SHAPE_SWITCH(Root, { + if (Simple->Inner->BranchVar) LastLoop = NULL; // a switch clears out the loop (TODO: only for breaks, not continue) + // If there is a next block, we already know at Simple creation time to make direct branches, // and we can do nothing more. If there is no next however, then Natural is where we will // go to by doing nothing, so we can potentially optimize some branches to direct. @@ -1028,6 +1057,11 @@ void Relooper::Calculate(Block *Entry) { // If we are fusing a Multiple with a loop into this Simple, then visit it now if (Fused && Fused->NeedLoop) { LoopStack.push(Fused); + } + if (Simple->Inner->BranchVar) { + LoopStack.push(NULL); // a switch means breaks are now useless, push a dummy + } + if (Fused) { RECURSE_Multiple(Fused, FindLabeledLoops); } for (BlockBranchMap::iterator iter = Simple->Inner->ProcessedBranchesOut.begin(); iter != Simple->Inner->ProcessedBranchesOut.end(); iter++) { @@ -1038,14 +1072,18 @@ void Relooper::Calculate(Block *Entry) { if (Details->Ancestor != LoopStack.top() && Details->Labeled) { LabeledShape *Labeled = Shape::IsLabeled(Details->Ancestor); Labeled->Labeled = true; - Details->Labeled = true; } else { Details->Labeled = false; } } } + if (Simple->Inner->BranchVar) { + LoopStack.pop(); + } if (Fused && Fused->NeedLoop) { LoopStack.pop(); + } + if (Fused) { Next = Fused->Next; } else { Next = Root->Next; @@ -1173,8 +1211,8 @@ void rl_set_asm_js_mode(int on) { Relooper::SetAsmJSMode(on); } -void *rl_new_block(const char *text) { - Block *ret = new Block(text); +void *rl_new_block(const char *text, const char *branch_var) { + Block *ret = new Block(text, branch_var); #if DEBUG printf(" void *b%d = rl_new_block(\"// code %d\");\n", ret->Id, ret->Id); __blockDebugMap__[ret] = ret->Id; diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h index e54b578c..f3dedf8c 100644 --- a/src/relooper/Relooper.h +++ b/src/relooper/Relooper.h @@ -59,9 +59,10 @@ struct Block { Shape *Parent; // The shape we are directly inside int Id; // A unique identifier const char *Code; // The string representation of the code in this block. Owning pointer (we copy the input) + 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 - Block(const char *CodeInit); + Block(const char *CodeInit, const char *BranchVarInit); ~Block(); void AddBranchTo(Block *Target, const char *Condition, const char *Code=NULL); @@ -235,7 +236,7 @@ extern "C" { RELOOPERDLL_API void rl_set_output_buffer(char *buffer, int size); RELOOPERDLL_API void rl_make_output_buffer(int size); RELOOPERDLL_API void rl_set_asm_js_mode(int on); -RELOOPERDLL_API void *rl_new_block(const char *text); +RELOOPERDLL_API void *rl_new_block(const char *text, const char *branch_var); RELOOPERDLL_API void rl_delete_block(void *block); RELOOPERDLL_API void rl_block_add_branch_to(void *from, void *to, const char *condition, const char *code); RELOOPERDLL_API void *rl_new_relooper(); diff --git a/src/relooper/emscripten/glue.js b/src/relooper/emscripten/glue.js index 36922185..40ddabec 100644 --- a/src/relooper/emscripten/glue.js +++ b/src/relooper/emscripten/glue.js @@ -6,15 +6,22 @@ var TBUFFER_SIZE = 10*1024*1024; var tbuffer = _malloc(TBUFFER_SIZE); + var VBUFFER_SIZE = 256; + var vbuffer = _malloc(VBUFFER_SIZE); + var RelooperGlue = {}; RelooperGlue['init'] = function() { this.r = _rl_new_relooper(); }, - RelooperGlue['addBlock'] = function(text) { + RelooperGlue['addBlock'] = function(text, branchVar) { assert(this.r); assert(text.length+1 < TBUFFER_SIZE); writeStringToMemory(text, tbuffer); - var b = _rl_new_block(tbuffer); + if (branchVar) { + assert(branchVar.length+1 < VBUFFER_SIZE); + writeStringToMemory(branchVar, vbuffer); + } + var b = _rl_new_block(tbuffer, branchVar ? vbuffer : 0); _rl_relooper_add_block(this.r, b); return b; }; diff --git a/src/relooper/fuzzer.py b/src/relooper/fuzzer.py index 5f6bae3d..50846d10 100644 --- a/src/relooper/fuzzer.py +++ b/src/relooper/fuzzer.py @@ -26,13 +26,13 @@ while True: pass # parts - entry = '''print('entry'); var label; var state; var decisions = %s; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }''' % str(decisions) + entry = '''print('entry'); var label; var state; var modded; var decisions = %s; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }''' % str(decisions) slow = entry + '\n' for i in range(len(branches[0])): if i > 0: slow += 'else ' b = branches[0] - slow += 'if (state %% %d == %d) { label = %d; }\n' % (len(b)+1, i, b[i]) # TODO: split range 1-n into these options + slow += 'if (modded == %d) { label = %d; }\n' % (i, b[i]) # TODO: split range 1-n into these options if len(branches[0]): slow += 'else ' slow += 'label = %d;\n' % defaults[0] @@ -51,26 +51,35 @@ int main() { ''' for i in range(1, num): - slow += ' case %d: print(%d); state = check(); \n' % (i, i) + slow += ' case %d: print(%d); state = check(); modded = state %% %d\n' % (i, i, len(branches[i])+1) b = branches[i] for j in range(len(b)): - slow += ' if (state %% %d == %d) { label = %d; break }\n' % (len(b)+1, j, b[j]) # TODO: split range 1-n into these options + slow += ' if (modded == %d) { label = %d; break }\n' % (j, b[j]) # TODO: split range 1-n into these options slow += ' label = %d; break\n' % defaults[i] + branch_vars = [] for i in range(num): + branch_var = '"modded"' if len(branches[i]) > 0 and not (len(branches[i]) == 1 and random.random() < 0.5) else 'NULL' + branch_vars.append(branch_var) + if i == 0: fast += ''' - Block *b%d = new Block("%s"); -''' % (i, entry) + Block *b%d = new Block("%s", %s); +''' % (i, entry, branch_var) else: - fast += ''' Block *b%d = new Block("print(%d); state = check();%s"); -''' % (i, i, '// ' + ('.' * int(random.expovariate(0.5/num)))) + fast += ''' Block *b%d = new Block("print(%d); state = check(); modded = state %% %d; %s", %s); +''' % (i, i, len(branches[i])+1, '// ' + ('.' * int(random.expovariate(0.5/num))), branch_var) for i in range(num): + branch_var = branch_vars[i] b = branches[i] for j in range(len(b)): - fast += ''' b%d->AddBranchTo(b%d, "state %% %d == %d"); -''' % (i, b[j], len(b)+1, j) + if branch_var == 'NULL': + fast += ''' b%d->AddBranchTo(b%d, "modded == %d"); +''' % (i, b[j], j) + else: + fast += ''' b%d->AddBranchTo(b%d, "case %d:"); +''' % (i, b[j], j) fast += ''' b%d->AddBranchTo(b%d, NULL); ''' % (i, defaults[i]) diff --git a/src/relooper/test.cpp b/src/relooper/test.cpp index b2d500d7..fbd9c7aa 100644 --- a/src/relooper/test.cpp +++ b/src/relooper/test.cpp @@ -7,11 +7,11 @@ int main() { if (1) { Relooper::SetOutputBuffer(buffer, sizeof(buffer)); - printf("\n\n-- If pattern --\n\n"); + printf("\n\n-- If pattern --\n\n", "the_var"); - Block *b_a = new Block("// block A\n"); - Block *b_b = new Block("// block B\n"); - Block *b_c = new Block("// block C\n"); + Block *b_a = new Block("// block A\n", "the_var"); + Block *b_b = new Block("// block B\n", "the_var"); + Block *b_c = new Block("// block C\n", "the_var"); b_a->AddBranchTo(b_b, "check == 10", "atob();"); b_a->AddBranchTo(b_c, NULL, "atoc();"); @@ -24,7 +24,7 @@ int main() { r.AddBlock(b_c); r.Calculate(b_a); - printf("\n\n"); + printf("\n\n", "the_var"); r.Render(); puts(buffer); @@ -33,12 +33,12 @@ int main() { if (1) { Relooper::SetOutputBuffer(buffer, sizeof(buffer)); - printf("\n\n-- If-else pattern --\n\n"); + printf("\n\n-- If-else pattern --\n\n", "the_var"); - Block *b_a = new Block("// block A\n"); - Block *b_b = new Block("// block B\n"); - Block *b_c = new Block("// block C\n"); - Block *b_d = new Block("// block D\n"); + Block *b_a = new Block("// block A\n", "the_var"); + Block *b_b = new Block("// block B\n", "the_var"); + Block *b_c = new Block("// block C\n", "the_var"); + Block *b_d = new Block("// block D\n", "the_var"); b_a->AddBranchTo(b_b, "check == 15"); b_a->AddBranchTo(b_c, NULL); @@ -54,7 +54,7 @@ int main() { r.AddBlock(b_d); r.Calculate(b_a); - printf("\n\n"); + printf("\n\n", "the_var"); r.Render(); puts(buffer); @@ -63,11 +63,11 @@ int main() { if (1) { Relooper::SetOutputBuffer(buffer, sizeof(buffer)); - printf("\n\n-- Loop + tail pattern --\n\n"); + printf("\n\n-- Loop + tail pattern --\n\n", "the_var"); - Block *b_a = new Block("// block A\nvar check = maybe();\n"); - Block *b_b = new Block("// block B\n"); - Block *b_c = new Block("// block C\n"); + Block *b_a = new Block("// block A\nvar check = maybe();\n", "the_var"); + Block *b_b = new Block("// block B\n", "the_var"); + Block *b_c = new Block("// block C\n", "the_var"); b_a->AddBranchTo(b_b, NULL); @@ -80,7 +80,7 @@ int main() { r.AddBlock(b_c); r.Calculate(b_a); - printf("\n\n"); + printf("\n\n", "the_var"); r.Render(); puts(buffer); @@ -89,29 +89,29 @@ int main() { if (1) { Relooper::SetOutputBuffer(buffer, sizeof(buffer)); - printf("\n\n-- Loop with phi to head \n\n"); + printf("\n\n-- Loop with phi to head \n\n", "the_var"); void *block_map[10000]; void *rl = rl_new_relooper(); - void *b1 = rl_new_block("// code 1"); + void *b1 = rl_new_block("// code 1", "the_var"); block_map[1] = b1; rl_relooper_add_block(rl, block_map[1]); - void *b2 = rl_new_block("// code 2"); + void *b2 = rl_new_block("// code 2", "the_var"); block_map[2] = b2; rl_relooper_add_block(rl, block_map[2]); - void *b3 = rl_new_block("// code 3"); + void *b3 = rl_new_block("// code 3", "the_var"); block_map[3] = b3; rl_relooper_add_block(rl, block_map[3]); - void *b4 = rl_new_block("// code 4"); + void *b4 = rl_new_block("// code 4", "the_var"); block_map[4] = b4; rl_relooper_add_block(rl, block_map[4]); - void *b5 = rl_new_block("// code 5"); + void *b5 = rl_new_block("// code 5", "the_var"); block_map[5] = b5; rl_relooper_add_block(rl, block_map[5]); - void *b6 = rl_new_block("// code 6"); + void *b6 = rl_new_block("// code 6", "the_var"); block_map[6] = b6; rl_relooper_add_block(rl, block_map[6]); - void *b7 = rl_new_block("// code 7"); + void *b7 = rl_new_block("// code 7", "the_var"); block_map[7] = b7; rl_relooper_add_block(rl, block_map[7]); rl_block_add_branch_to(block_map[1], block_map[2], NULL, "var $i_0 = 0;var $x_0 = 5; "); @@ -132,13 +132,13 @@ int main() { if (1) { Relooper::SetOutputBuffer(buffer, sizeof(buffer)); - printf("\n\n-- phi on split dead ends --\n\n"); + printf("\n\n-- phi on split dead ends --\n\n", "the_var"); - Block *b_a = new Block("// block A...................................................................................................\n"); - Block *b_b = new Block("// block B...................................................................................................\n"); - Block *b_c = new Block("// block C...................................................................................................\n"); - Block *b_d = new Block("// block D\n"); // small and splittable! - Block *b_e = new Block("// block E\n"); + Block *b_a = new Block("// block A...................................................................................................\n", "the_var"); + Block *b_b = new Block("// block B...................................................................................................\n", "the_var"); + Block *b_c = new Block("// block C...................................................................................................\n", "the_var"); + Block *b_d = new Block("// block D\n", "the_var"); // small and splittable! + Block *b_e = new Block("// block E\n", "the_var"); b_a->AddBranchTo(b_b, "chak()", "atob();"); b_a->AddBranchTo(b_c, NULL, "atoc();"); @@ -155,7 +155,7 @@ int main() { r.AddBlock(b_e); r.Calculate(b_a); - printf("\n\n"); + printf("\n\n", "the_var"); r.Render(); puts(buffer); @@ -164,12 +164,12 @@ int main() { if (1) { Relooper::SetOutputBuffer(buffer, sizeof(buffer)); - printf("\n\n-- Unbalanced with a dead end --\n\n"); + printf("\n\n-- Unbalanced with a dead end --\n\n", "the_var"); - Block *b_a = new Block("// block A\n"); - Block *b_b = new Block("// block B\n"); - Block *b_c = new Block("return C;\n"); - Block *b_d = new Block("// block D\n"); + Block *b_a = new Block("// block A\n", "the_var"); + Block *b_b = new Block("// block B\n", "the_var"); + Block *b_c = new Block("return C;\n", "the_var"); + Block *b_d = new Block("// block D\n", "the_var"); b_a->AddBranchTo(b_b, "check == 10"); b_a->AddBranchTo(b_c, NULL); // c is a dead end @@ -185,7 +185,7 @@ int main() { r.AddBlock(b_d); r.Calculate(b_a); - printf("\n\n"); + printf("\n\n", "the_var"); r.Render(); puts(buffer); @@ -194,14 +194,14 @@ int main() { if (1) { Relooper::SetOutputBuffer(buffer, sizeof(buffer)); - printf("\n\n-- if (expensive || expensive2) X else Y; Z --\n\n"); + printf("\n\n-- if (expensive || expensive2) X else Y; Z --\n\n", "the_var"); - Block *b_a = new Block("// block A\n"); - Block *b_b = new Block("// block B\n"); - Block *b_c = new Block("// block C;\n"); - Block *b_d = new Block("// block D\n"); - Block *b_e = new Block("// block E\n"); - Block *b_f = new Block("// block F\n"); + Block *b_a = new Block("// block A\n", "the_var"); + Block *b_b = new Block("// block B\n", "the_var"); + Block *b_c = new Block("// block C;\n", "the_var"); + Block *b_d = new Block("// block D\n", "the_var"); + Block *b_e = new Block("// block E\n", "the_var"); + Block *b_f = new Block("// block F\n", "the_var"); b_a->AddBranchTo(b_c, "expensive()"); b_a->AddBranchTo(b_b, NULL); @@ -226,7 +226,7 @@ int main() { r.AddBlock(b_f); r.Calculate(b_a); - printf("\n\n"); + printf("\n\n", "the_var"); r.Render(); puts(buffer); @@ -235,11 +235,11 @@ int main() { if (1) { Relooper::SetOutputBuffer(buffer, sizeof(buffer)); - printf("\n\n-- conditional loop --\n\n"); + printf("\n\n-- conditional loop --\n\n", "the_var"); - Block *b_a = new Block("// block A\n"); - Block *b_b = new Block("// block B\n"); - Block *b_c = new Block("// block C\n"); + Block *b_a = new Block("// block A\n", "the_var"); + Block *b_b = new Block("// block B\n", "the_var"); + Block *b_c = new Block("// block C\n", "the_var"); b_a->AddBranchTo(b_b, "shouldLoop()"); b_a->AddBranchTo(b_c, NULL); @@ -253,7 +253,7 @@ int main() { r.AddBlock(b_c); r.Calculate(b_a); - printf("\n\n"); + printf("\n\n", "the_var"); r.Render(); puts(buffer); diff --git a/src/relooper/test.txt b/src/relooper/test.txt index 6c910846..2c530567 100644 --- a/src/relooper/test.txt +++ b/src/relooper/test.txt @@ -5,13 +5,21 @@ // block A -if (check == 10) { +switch (the_var) { +check == 10 { atob(); // block B - btoc(); -} else { + switch (the_var) { + default: { + btoc(); + } + } + break; +} +default: { atoc(); } +} // block C @@ -21,10 +29,22 @@ if (check == 10) { // block A -if (check == 15) { +switch (the_var) { +check == 15 { // block B -} else { + switch (the_var) { + default: { + } + } + break; +} +default: { // block C + switch (the_var) { + default: { + } + } +} } // block D @@ -34,13 +54,22 @@ if (check == 15) { -while(1) { +L9: while(1) { // block A var check = maybe(); + switch (the_var) { + default: { + } + } // block B - if (!(check == 41)) { + switch (the_var) { + check == 41 { break; } + default: { + break L9; + } + } } // block C @@ -49,30 +78,56 @@ while(1) { -- Loop with phi to head // code 1 -var $i_0 = 0;var $x_0 = 5; -while(1) { +switch (the_var) { +default: { + var $i_0 = 0;var $x_0 = 5; +} +} +L14: while(1) { // code 2 - if (!($2)) { + switch (the_var) { + $2 { + break; + } + default: { var $x_1 = $x_0; label = 18; - break; + break L14; + } } // code 3 - if ($6) { + switch (the_var) { + $6 { + break L14; break; - } else { + } + default: { var $i_0 = $7;var $x_0 = $5; } + } } if (label == 18) { // code 7 } // code 4 -if ($10) { +switch (the_var) { +$10 { // code 5 + switch (the_var) { + default: { + } + } + break; +} +default: { +} } // code 6 -var $x_1 = $13; +switch (the_var) { +default: { + var $x_1 = $13; +} +} // code 7 @@ -82,17 +137,29 @@ var $x_1 = $13; // block A................................................................................................... -if (chak()) { +switch (the_var) { +chak() { atob(); // block B................................................................................................... - btod(); + switch (the_var) { + default: { + btod(); + } + } // block D -} else { + break; +} +default: { atoc(); // block C................................................................................................... - ctod2(); + switch (the_var) { + default: { + ctod2(); + } + } // block D } +} @@ -101,12 +168,25 @@ if (chak()) { // block A -if (!(check == 10)) { +switch (the_var) { +check == 10 { + break; +} +default: { return C; } +} while(1) { // block B + switch (the_var) { + default: { + } + } // block D + switch (the_var) { + default: { + } + } } @@ -116,24 +196,49 @@ while(1) { // block A -do { - if (expensive()) { +L37: do { + switch (the_var) { + expensive() { label = 33; - } else { + break; + } + default: { // block B - if (expensive2()) { + switch (the_var) { + expensive2() { label = 33; + break L37; break; } + default: { + } + } // block D + 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: { + } + } } @@ -143,13 +248,25 @@ while(1) { // block A -if (shouldLoop()) { - while(1) { - // block B - if (!(moarLoop())) { - break; +L46: do { + switch (the_var) { + shouldLoop() { + while(1) { + // block B + switch (the_var) { + moarLoop() { + break; + } + default: { + break L46; + } + } } + break; } -} + default: { + } + } +} while(0); // block C diff --git a/src/relooper/test2.c b/src/relooper/test2.c index 118a2627..156945c3 100644 --- a/src/relooper/test2.c +++ b/src/relooper/test2.c @@ -6,20 +6,20 @@ int main() { rl_set_output_buffer(buffer, sizeof(buffer)); void *r = rl_new_relooper(); - void *ep = rl_new_block("ep"); + void *ep = rl_new_block("ep", "var"); rl_relooper_add_block(r, ep); - void *LBB1 = rl_new_block("LBB1"); + void *LBB1 = rl_new_block("LBB1", "the_var"); rl_relooper_add_block(r, LBB1); - void *LBB2 = rl_new_block("LBB2"); + void *LBB2 = rl_new_block("LBB2", "the_var"); rl_relooper_add_block(r, LBB2); - void *LBB3 = rl_new_block("LBB3"); + void *LBB3 = rl_new_block("LBB3", "the_var"); rl_relooper_add_block(r, LBB3); /* - void *LBB4 = rl_new_block("LBB4"); + void *LBB4 = rl_new_block("LBB4", "the_var"); rl_relooper_add_block(r, LBB4); - void *LBB5 = rl_new_block("LBB5"); + void *LBB5 = rl_new_block("LBB5", "the_var"); rl_relooper_add_block(r, LBB5); - void *LBB6 = rl_new_block("LBB6"); + void *LBB6 = rl_new_block("LBB6", "the_var"); rl_relooper_add_block(r, LBB6); */ rl_block_add_branch_to(ep, LBB1, "ep -> LBB1", NULL); @@ -27,13 +27,13 @@ int main() { rl_block_add_branch_to(LBB1, LBB2, "LBB1 -> LBB2", NULL); rl_block_add_branch_to(LBB1, LBB3, NULL, NULL); rl_block_add_branch_to(LBB2, LBB3, NULL, NULL); -// rl_block_add_branch_to(LBB3, LBB4, "LBB3 -> LBB4"); -// rl_block_add_branch_to(LBB3, LBB6, "LBB3 -> LBB6"); +// rl_block_add_branch_to(LBB3, LBB4, "LBB3 -> LBB4", "the_var"); +// rl_block_add_branch_to(LBB3, LBB6, "LBB3 -> LBB6", "the_var"); /* - rl_block_add_branch_to(LBB4, LBB5, "LBB4 -> LBB5"); - rl_block_add_branch_to(LBB4, LBB6, "LBB4 -> LBB6"); - rl_block_add_branch_to(LBB5, LBB6, "LBB5 -> LBB6"); - rl_block_add_branch_to(LBB5, LBB5, "LBB5 -> LBB5"); + rl_block_add_branch_to(LBB4, LBB5, "LBB4 -> LBB5", "the_var"); + rl_block_add_branch_to(LBB4, LBB6, "LBB4 -> LBB6", "the_var"); + rl_block_add_branch_to(LBB5, LBB6, "LBB5 -> LBB6", "the_var"); + rl_block_add_branch_to(LBB5, LBB5, "LBB5 -> LBB5", "the_var"); */ rl_relooper_calculate(r, ep); rl_relooper_render(r); diff --git a/src/relooper/test2.txt b/src/relooper/test2.txt index 2f3e5ca1..a558a8b7 100644 --- a/src/relooper/test2.txt +++ b/src/relooper/test2.txt @@ -1,11 +1,25 @@ ep -do { - if (ep -> LBB1) { +L1: do { + switch (var) { + ep -> LBB1 { LBB1 - if (!(LBB1 -> LBB2)) { + switch (the_var) { + LBB1 -> LBB2 { break; } + default: { + break L1; + } + } LBB2 + switch (the_var) { + default: { + } + } + break; + } + default: { + } } } while(0); LBB3 diff --git a/src/relooper/test3.c b/src/relooper/test3.c index 2cef14fb..f652a2bc 100644 --- a/src/relooper/test3.c +++ b/src/relooper/test3.c @@ -6,19 +6,19 @@ int main() { rl_set_output_buffer(buffer, sizeof(buffer)); void *r = rl_new_relooper(); - void *ep = rl_new_block("ep"); + void *ep = rl_new_block("ep", "the_var"); rl_relooper_add_block(r, ep); - void *LBB1 = rl_new_block("LBB1"); + void *LBB1 = rl_new_block("LBB1", "the_var"); rl_relooper_add_block(r, LBB1); - void *LBB2 = rl_new_block("LBB2"); + void *LBB2 = rl_new_block("LBB2", "the_var"); rl_relooper_add_block(r, LBB2); - void *LBB3 = rl_new_block("LBB3"); + void *LBB3 = rl_new_block("LBB3", "the_var"); rl_relooper_add_block(r, LBB3); - void *LBB4 = rl_new_block("LBB4"); + void *LBB4 = rl_new_block("LBB4", "the_var"); rl_relooper_add_block(r, LBB4); - void *LBB5 = rl_new_block("LBB5"); + void *LBB5 = rl_new_block("LBB5", "the_var"); rl_relooper_add_block(r, LBB5); - void *LBB6 = rl_new_block("LBB6"); + void *LBB6 = rl_new_block("LBB6", "the_var"); rl_relooper_add_block(r, LBB6); rl_block_add_branch_to(ep, LBB1, "ep -> LBB1", NULL); diff --git a/src/relooper/test3.txt b/src/relooper/test3.txt index 51199f72..f77e2618 100644 --- a/src/relooper/test3.txt +++ b/src/relooper/test3.txt @@ -1,26 +1,55 @@ ep -do { - if (ep -> LBB1) { +L1: do { + switch (the_var) { + ep -> LBB1 { LBB1 - if (!(LBB1 -> LBB2)) { + switch (the_var) { + LBB1 -> LBB2 { break; } + default: { + break L1; + } + } LBB2 + switch (the_var) { + default: { + } + } + break; + } + default: { + } } } while(0); LBB3 -do { - if (LBB3 -> LBB4) { +L5: do { + switch (the_var) { + LBB3 -> LBB4 { LBB4 - if (!(LBB4 -> LBB5)) { + switch (the_var) { + LBB4 -> LBB5 { break; } + default: { + break L5; + } + } while(1) { LBB5 - if (LBB5 -> LBB6) { + switch (the_var) { + LBB5 -> LBB6 { + break L5; break; } + default: { + } + } } + break; + } + default: { + } } } while(0); LBB6 diff --git a/src/relooper/test4.cpp b/src/relooper/test4.cpp index 76fc8ec0..8cbc024c 100644 --- a/src/relooper/test4.cpp +++ b/src/relooper/test4.cpp @@ -7,19 +7,19 @@ int main() { void *r = rl_new_relooper(); - void *b19 = rl_new_block("//19"); + void *b19 = rl_new_block("//19", "the_var"); rl_relooper_add_block(r, b19); - void *b20 = rl_new_block("//20"); + void *b20 = rl_new_block("//20", "the_var"); rl_relooper_add_block(r, b20); - void *b21 = rl_new_block("//21"); + void *b21 = rl_new_block("//21", "the_var"); rl_relooper_add_block(r, b21); - void *b22 = rl_new_block("//22"); + void *b22 = rl_new_block("//22", "the_var"); rl_relooper_add_block(r, b22); - void *b23 = rl_new_block("//23"); + void *b23 = rl_new_block("//23", "the_var"); rl_relooper_add_block(r, b23); - void *b24 = rl_new_block("//24"); + void *b24 = rl_new_block("//24", "the_var"); rl_relooper_add_block(r, b24); - void *b28 = rl_new_block("//28"); + void *b28 = rl_new_block("//28", "the_var"); rl_relooper_add_block(r, b28); rl_block_add_branch_to(b19, b20, " 1 ", NULL); diff --git a/src/relooper/test4.txt b/src/relooper/test4.txt index ab7051c1..1829e523 100644 --- a/src/relooper/test4.txt +++ b/src/relooper/test4.txt @@ -1,23 +1,44 @@ //19 -do { - if ( 1 ) { +L1: do { + switch (the_var) { + 1 { //20 - if (!( 1 )) { - label = 4; + switch (the_var) { + 1 { break; } + default: { + label = 4; + break L1; + } + } //21 - } else { + switch (the_var) { + default: { + } + } + break; + } + default: { label = 4; } + } } while(0); if (label == 4) { //22 + switch (the_var) { + default: { + } + } } //23 -if ( 1 ) { +switch (the_var) { + 1 { //24 -} else { + break; +} +default: { //28 } +} diff --git a/src/relooper/test5.cpp b/src/relooper/test5.cpp index f86da2b3..d04d157d 100644 --- a/src/relooper/test5.cpp +++ b/src/relooper/test5.cpp @@ -7,17 +7,17 @@ int main() { void *r = rl_new_relooper(); - void *b0 = rl_new_block("//0"); + void *b0 = rl_new_block("//0", "the_var"); rl_relooper_add_block(r, b0); - void *b1 = rl_new_block("//1"); + void *b1 = rl_new_block("//1", "the_var"); rl_relooper_add_block(r, b1); - void *b2 = rl_new_block("//2"); + void *b2 = rl_new_block("//2", "the_var"); rl_relooper_add_block(r, b2); - void *b3 = rl_new_block("//3"); + void *b3 = rl_new_block("//3", "the_var"); rl_relooper_add_block(r, b3); - void *b4 = rl_new_block("//4"); + void *b4 = rl_new_block("//4", "the_var"); rl_relooper_add_block(r, b4); - void *b5 = rl_new_block("//5"); + void *b5 = rl_new_block("//5", "the_var"); rl_relooper_add_block(r, b5); rl_block_add_branch_to(b0, b1, "check(0)", NULL); diff --git a/src/relooper/test5.txt b/src/relooper/test5.txt index 83755289..82ef5edf 100644 --- a/src/relooper/test5.txt +++ b/src/relooper/test5.txt @@ -1,32 +1,56 @@ //0 -if (check(0)) { - while(1) { +switch (the_var) { +check(0) { + L2: while(1) { //1 - if (!(check(1))) { + switch (the_var) { + check(1) { break; } + default: { + break L2; + } + } } - while(1) { + L4: while(1) { //2 - if (!(check(2))) { + switch (the_var) { + check(2) { break; } + default: { + break L4; + } + } } //3 -} else { + break; +} +default: { goingFrom0to4(); - while(1) { + L7: while(1) { //4 - if (!(check(4))) { + switch (the_var) { + check(4) { break; } + default: { + break L7; + } + } } - while(1) { + L9: while(1) { //5 - if (check(5)) { + switch (the_var) { + check(5) { + break L9; break; } + default: { + } + } } //3 } +} diff --git a/src/relooper/test6.cpp b/src/relooper/test6.cpp index 90453d4c..c292e79c 100644 --- a/src/relooper/test6.cpp +++ b/src/relooper/test6.cpp @@ -7,13 +7,13 @@ int main() { void *r = rl_new_relooper(); - void *b0 = rl_new_block("//0"); + void *b0 = rl_new_block("//0", "the_var"); rl_relooper_add_block(r, b0); - void *b1 = rl_new_block("//1"); + void *b1 = rl_new_block("//1", "the_var"); rl_relooper_add_block(r, b1); - void *b2 = rl_new_block("//2"); + void *b2 = rl_new_block("//2", "the_var"); rl_relooper_add_block(r, b2); - void *b3 = rl_new_block("//3"); + void *b3 = rl_new_block("//3", "the_var"); rl_relooper_add_block(r, b3); rl_block_add_branch_to(b0, b1, "check(0)", NULL); diff --git a/src/relooper/test6.txt b/src/relooper/test6.txt index 4f29f292..f9d6e93a 100644 --- a/src/relooper/test6.txt +++ b/src/relooper/test6.txt @@ -1,11 +1,25 @@ //0 -do { - if (check(0)) { +L1: do { + switch (the_var) { + check(0) { //1 - if (!(check(1))) { + switch (the_var) { + check(1) { break; } + default: { + break L1; + } + } //2 + switch (the_var) { + default: { + } + } + break; + } + default: { + } } } while(0); //3 diff --git a/src/relooper/test_dead.cpp b/src/relooper/test_dead.cpp index 887d254c..5c9fde1b 100644 --- a/src/relooper/test_dead.cpp +++ b/src/relooper/test_dead.cpp @@ -8,8 +8,8 @@ int main() { printf("\n\n-- If pattern --\n\n"); - Block *b_a = new Block("// block A\n"); - Block *b_b = new Block("// block B\n"); // never reached + Block *b_a = new Block("// block A\n", "the_var"); + Block *b_b = new Block("// block B\n", "waka"); // never reached b_b->AddBranchTo(b_b, NULL); diff --git a/src/relooper/test_debug.cpp b/src/relooper/test_debug.cpp index 14511b62..91b6c9d7 100644 --- a/src/relooper/test_debug.cpp +++ b/src/relooper/test_debug.cpp @@ -6,13 +6,13 @@ int main() { rl_set_output_buffer(buffer, sizeof(buffer)); void *r = rl_new_relooper(); - void *ep = rl_new_block("ep"); + void *ep = rl_new_block("ep", "the_var"); rl_relooper_add_block(r, ep); - void *LBB1 = rl_new_block("LBB1"); + void *LBB1 = rl_new_block("LBB1", "the_var"); rl_relooper_add_block(r, LBB1); - void *LBB2 = rl_new_block("LBB2"); + void *LBB2 = rl_new_block("LBB2", "the_var"); rl_relooper_add_block(r, LBB2); - void *LBB3 = rl_new_block("LBB3"); + void *LBB3 = rl_new_block("LBB3", "the_var"); rl_relooper_add_block(r, LBB3); rl_block_add_branch_to(ep, LBB1, "ep -> LBB1", NULL); diff --git a/src/relooper/test_debug.txt b/src/relooper/test_debug.txt index 4a42e642..eb33fdbc 100644 --- a/src/relooper/test_debug.txt +++ b/src/relooper/test_debug.txt @@ -115,13 +115,27 @@ int main() { // === Optimizing shapes === // Fusing Multiple to Simple ep -do { - if (ep -> LBB1) { +L1: do { + switch (the_var) { + ep -> LBB1 { LBB1 - if (!(LBB1 -> LBB2)) { + switch (the_var) { + LBB1 -> LBB2 { break; } + default: { + break L1; + } + } LBB2 + switch (the_var) { + default: { + } + } + break; + } + default: { + } } } while(0); LBB3 diff --git a/src/relooper/test_fuzz1.cpp b/src/relooper/test_fuzz1.cpp index 54205694..ef48ea93 100644 --- a/src/relooper/test_fuzz1.cpp +++ b/src/relooper/test_fuzz1.cpp @@ -8,15 +8,15 @@ int main() { char *buffer = (char*)malloc(SIZE); Relooper::SetOutputBuffer(buffer, SIZE); - Block *b0 = new Block("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++] }"); - Block *b1 = new Block("print(1); state = check();"); - Block *b2 = new Block("print(2); state = check();"); - Block *b3 = new Block("print(3); state = check();"); - Block *b4 = new Block("print(4); state = check();"); - Block *b5 = new Block("print(5); state = check();"); - Block *b6 = new Block("print(6); state = check();"); - Block *b7 = new Block("print(7); state = check();"); - Block *b8 = new Block("print(8); state = check();"); + Block *b0 = new Block("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++] }", "the_var"); + Block *b1 = new Block("print(1); state = check();", "the_var"); + Block *b2 = new Block("print(2); state = check();", "the_var"); + Block *b3 = new Block("print(3); state = check();", "the_var"); + Block *b4 = new Block("print(4); state = check();", "the_var"); + Block *b5 = new Block("print(5); state = check();", "the_var"); + Block *b6 = new Block("print(6); state = check();", "the_var"); + Block *b7 = new Block("print(7); state = check();", "the_var"); + Block *b8 = new Block("print(8); state = check();", "the_var"); b0->AddBranchTo(b5, NULL); b1->AddBranchTo(b3, NULL); b2->AddBranchTo(b1, NULL); diff --git a/src/relooper/test_fuzz1.txt b/src/relooper/test_fuzz1.txt index becbc0d2..d887f5b8 100644 --- a/src/relooper/test_fuzz1.txt +++ b/src/relooper/test_fuzz1.txt @@ -1,32 +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(); -if (state == 7) { +switch (the_var) { +state == 7 { print(7); state = check(); - label = 3; + switch (the_var) { + default: { + label = 3; + } + } + break; +} +default: { +} } L5: while(1) { if (label == 3) { label = 0; print(2); state = check(); + switch (the_var) { + default: { + } + } } print(1); state = check(); + switch (the_var) { + default: { + } + } while(1) { print(3); state = check(); - if (!(state == 8)) { + switch (the_var) { + state == 8 { + break; + } + default: { continue L5; } + } print(8); state = check(); - if (!(state == 4)) { + switch (the_var) { + state == 4 { + break; + } + default: { label = 3; continue L5; } + } print(4); state = check(); - if (!(state == 3)) { + switch (the_var) { + state == 3 { + break; + } + default: { continue L5; } + } } } diff --git a/src/relooper/test_fuzz2.cpp b/src/relooper/test_fuzz2.cpp index 00375340..8a66b113 100644 --- a/src/relooper/test_fuzz2.cpp +++ b/src/relooper/test_fuzz2.cpp @@ -8,10 +8,10 @@ int main() { char *buffer = (char*)malloc(SIZE); Relooper::SetOutputBuffer(buffer, SIZE); - Block *b0 = new Block("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++] }"); - Block *b1 = new Block("print(1); state = check();"); - Block *b2 = new Block("print(2); state = check();"); - Block *b3 = new Block("print(3); state = check();"); + Block *b0 = new Block("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++] }", "the_var"); + Block *b1 = new Block("print(1); state = check();", "the_var"); + Block *b2 = new Block("print(2); state = check();", "the_var"); + Block *b3 = new Block("print(3); state = check();", "the_var"); b0->AddBranchTo(b1, "state == 1"); b0->AddBranchTo(b3, NULL); b1->AddBranchTo(b1, NULL); diff --git a/src/relooper/test_fuzz2.txt b/src/relooper/test_fuzz2.txt index 02b2c83b..69f4350c 100644 --- a/src/relooper/test_fuzz2.txt +++ b/src/relooper/test_fuzz2.txt @@ -1,13 +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++] } -if (state == 1) { +switch (the_var) { +state == 1 { while(1) { print(1); state = check(); + switch (the_var) { + default: { + } + } } + break; +} +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.cpp b/src/relooper/test_fuzz3.cpp index 3f39f5da..cb37d50f 100644 --- a/src/relooper/test_fuzz3.cpp +++ b/src/relooper/test_fuzz3.cpp @@ -8,11 +8,11 @@ int main() { char *buffer = (char*)malloc(SIZE); Relooper::SetOutputBuffer(buffer, SIZE); - Block *b0 = new Block("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++] }"); - Block *b1 = new Block("print(1); state = check();"); - Block *b2 = new Block("print(2); state = check();"); - Block *b3 = new Block("print(3); state = check();"); - Block *b4 = new Block("print(4); state = check();"); + Block *b0 = new Block("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++] }", "the_var"); + Block *b1 = new Block("print(1); state = check();", "the_var"); + Block *b2 = new Block("print(2); state = check();", "the_var"); + Block *b3 = new Block("print(3); state = check();", "the_var"); + Block *b4 = new Block("print(4); state = check();", "the_var"); b0->AddBranchTo(b1, NULL); b1->AddBranchTo(b3, NULL); b2->AddBranchTo(b1, NULL); diff --git a/src/relooper/test_fuzz3.txt b/src/relooper/test_fuzz3.txt index b4b1831d..398b4803 100644 --- a/src/relooper/test_fuzz3.txt +++ b/src/relooper/test_fuzz3.txt @@ -1,9 +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(); + switch (the_var) { + default: { + } + } } diff --git a/src/relooper/test_fuzz4.cpp b/src/relooper/test_fuzz4.cpp index 8f969386..8cd93984 100644 --- a/src/relooper/test_fuzz4.cpp +++ b/src/relooper/test_fuzz4.cpp @@ -8,11 +8,11 @@ int main() { char *buffer = (char*)malloc(SIZE); Relooper::SetOutputBuffer(buffer, SIZE); - Block *b0 = new Block("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++] }"); - Block *b1 = new Block("print(1); state = check();"); - Block *b2 = new Block("print(2); state = check();"); - Block *b3 = new Block("print(3); state = check();"); - Block *b4 = new Block("print(4); state = check();"); + Block *b0 = new Block("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++] }", "the_var"); + Block *b1 = new Block("print(1); state = check();", "the_var"); + Block *b2 = new Block("print(2); state = check();", "the_var"); + Block *b3 = new Block("print(3); state = check();", "the_var"); + Block *b4 = new Block("print(4); state = check();", "the_var"); b0->AddBranchTo(b2, "state == 2"); b0->AddBranchTo(b4, NULL); b1->AddBranchTo(b1, NULL); diff --git a/src/relooper/test_fuzz4.txt b/src/relooper/test_fuzz4.txt index 766ebdb6..2e2f2c6f 100644 --- a/src/relooper/test_fuzz4.txt +++ b/src/relooper/test_fuzz4.txt @@ -1,19 +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++] } -if (state == 2) { +switch (the_var) { +state == 2 { while(1) { print(2); state = check(); + switch (the_var) { + default: { + } + } } + break; } -while(1) { +default: { +} +} +L4: while(1) { print(4); state = check(); - if (!(state == 4)) { + 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.cpp b/src/relooper/test_fuzz5.cpp index f48c31ee..a58e19ba 100644 --- a/src/relooper/test_fuzz5.cpp +++ b/src/relooper/test_fuzz5.cpp @@ -8,16 +8,16 @@ int main() { char *buffer = (char*)malloc(SIZE); Relooper::SetOutputBuffer(buffer, SIZE); - Block *b0 = new Block("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++] }"); - Block *b1 = new Block("print(1); state = check();"); - Block *b2 = new Block("print(2); state = check();"); - Block *b3 = new Block("print(3); state = check();"); - Block *b4 = new Block("print(4); state = check();"); - Block *b5 = new Block("print(5); state = check();"); - Block *b6 = new Block("print(6); state = check();"); - Block *b7 = new Block("print(7); state = check();"); - Block *b8 = new Block("print(8); state = check();"); - Block *b9 = new Block("print(9); state = check();"); + Block *b0 = new Block("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++] }", "the_var"); + Block *b1 = new Block("print(1); state = check();", "the_var"); + Block *b2 = new Block("print(2); state = check();", "the_var"); + Block *b3 = new Block("print(3); state = check();", "the_var"); + Block *b4 = new Block("print(4); state = check();", "the_var"); + Block *b5 = new Block("print(5); state = check();", "the_var"); + Block *b6 = new Block("print(6); state = check();", "the_var"); + Block *b7 = new Block("print(7); state = check();", "the_var"); + Block *b8 = new Block("print(8); state = check();", "the_var"); + Block *b9 = new Block("print(9); state = check();", "the_var"); b0->AddBranchTo(b7, NULL); b1->AddBranchTo(b4, "state % 2 == 0"); b1->AddBranchTo(b6, NULL); diff --git a/src/relooper/test_fuzz5.txt b/src/relooper/test_fuzz5.txt index 0f76d1ed..f87e5b79 100644 --- a/src/relooper/test_fuzz5.txt +++ b/src/relooper/test_fuzz5.txt @@ -1,52 +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(); - if (state % 3 == 1) { + switch (the_var) { + state % 3 == 1 { label = 3; - } else if (state % 3 == 0) { + break; + } + state % 3 == 0 { print(8); state = check(); - if (state % 2 == 0) { + switch (the_var) { + state % 2 == 0 { label = 5; - } else { + break; + } + default: { label = 7; } - } else { + } break; } - while(1) { + default: { + break L1; + } + } + L5: while(1) { if (label == 3) { label = 0; print(2); state = check(); + switch (the_var) { + default: { + } + } print(1); state = check(); - if (state % 2 == 0) { + switch (the_var) { + state % 2 == 0 { label = 5; - continue; - } else { + continue L5; + break; + } + default: { label = 7; - continue; + continue L5; + } } } else if (label == 5) { label = 0; print(4); state = check(); - label = 3; - continue; + switch (the_var) { + default: { + label = 3; + continue L5; + } + } } else if (label == 7) { label = 0; print(6); state = check(); - if (state % 2 == 0) { + switch (the_var) { + state % 2 == 0 { continue L1; - } else { + break; + } + default: { label = 7; - continue; + continue L5; + } } } } } while(1) { print(3); state = check(); + switch (the_var) { + default: { + } + } } diff --git a/src/relooper/test_fuzz6.cpp b/src/relooper/test_fuzz6.cpp index 76a016d6..bea834ae 100644 --- a/src/relooper/test_fuzz6.cpp +++ b/src/relooper/test_fuzz6.cpp @@ -8,98 +8,98 @@ int main() { char *buffer = (char*)malloc(SIZE); Relooper::SetOutputBuffer(buffer, SIZE); - Block *b0 = new Block("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++] }"); - Block *b1 = new Block("print(1); state = check();// ..........................................................................."); - Block *b2 = new Block("print(2); state = check();// ........."); - Block *b3 = new Block("print(3); state = check();// .................................."); - Block *b4 = new Block("print(4); state = check();// ..........................................................................................................................."); - Block *b5 = new Block("print(5); state = check();// .........................................................................................................................................."); - Block *b6 = new Block("print(6); state = check();// ........."); - Block *b7 = new Block("print(7); state = check();// ............................................................................................................................................................................................."); - Block *b8 = new Block("print(8); state = check();// ...................................................................................................................................................................................................................................................."); - Block *b9 = new Block("print(9); state = check();// ..................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."); - Block *b10 = new Block("print(10); state = check();// ..................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."); - Block *b11 = new Block("print(11); state = check();// ........................................................"); - Block *b12 = new Block("print(12); state = check();// ................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................"); - Block *b13 = new Block("print(13); state = check();// ..................."); - Block *b14 = new Block("print(14); state = check();// ............................."); - Block *b15 = new Block("print(15); state = check();// .................................................."); - Block *b16 = new Block("print(16); state = check();// ................................................................................................................................................................................................................................................................................................................................................................"); - Block *b17 = new Block("print(17); state = check();// ................................................................"); - Block *b18 = new Block("print(18); state = check();// .............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."); - Block *b19 = new Block("print(19); state = check();// ......................................................................................................................................................................................................................"); - Block *b20 = new Block("print(20); state = check();// .................................................................................................................................................................."); - Block *b21 = new Block("print(21); state = check();// ..........................."); - Block *b22 = new Block("print(22); state = check();// ........................................................................................................."); - Block *b23 = new Block("print(23); state = check();// ................................................................................................................................................................................................................."); - Block *b24 = new Block("print(24); state = check();// ..........................."); - Block *b25 = new Block("print(25); state = check();// ......................................................................................................................................................"); - Block *b26 = new Block("print(26); state = check();// ........................................................................................................................................................................................................................................................................."); - Block *b27 = new Block("print(27); state = check();// ............................................................................................................................................................................."); - Block *b28 = new Block("print(28); state = check();// .............................................................................................................."); - Block *b29 = new Block("print(29); state = check();// ..............."); - Block *b30 = new Block("print(30); state = check();// ................................................................................................................................................................................................................."); - Block *b31 = new Block("print(31); state = check();// .........................................................................................................................................................................................................."); - Block *b32 = new Block("print(32); state = check();// ......................................................................................................"); - Block *b33 = new Block("print(33); state = check();// ...."); - Block *b34 = new Block("print(34); state = check();// .........................................................................................................................................."); - Block *b35 = new Block("print(35); state = check();// ................................."); - Block *b36 = new Block("print(36); state = check();// ........................."); - Block *b37 = new Block("print(37); state = check();// ................................................................................................................................"); - Block *b38 = new Block("print(38); state = check();// ............................................................................................................................................................................................................................................................................................................................................"); - Block *b39 = new Block("print(39); state = check();// ................"); - Block *b40 = new Block("print(40); state = check();// ................................................................................................................................................"); - Block *b41 = new Block("print(41); state = check();// ..................................................................................................................................."); - Block *b42 = new Block("print(42); state = check();// ....................................................."); - Block *b43 = new Block("print(43); state = check();// ........."); - Block *b44 = new Block("print(44); state = check();// ....................................................................................................................................................."); - Block *b45 = new Block("print(45); state = check();// ............................"); - Block *b46 = new Block("print(46); state = check();// ............................................................................."); - Block *b47 = new Block("print(47); state = check();// ...................................................................................................................................."); - Block *b48 = new Block("print(48); state = check();// ............"); - Block *b49 = new Block("print(49); state = check();// ............................................................................................................................................................................................................................................................................................"); - Block *b50 = new Block("print(50); state = check();// ........................................"); - Block *b51 = new Block("print(51); state = check();// ............................................................................................."); - Block *b52 = new Block("print(52); state = check();// .............................................................................."); - Block *b53 = new Block("print(53); state = check();// .............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."); - Block *b54 = new Block("print(54); state = check();// ....................................."); - Block *b55 = new Block("print(55); state = check();// ..........................................................................................................................................................................................................."); - Block *b56 = new Block("print(56); state = check();// ...................................................................................................................................................................................................................."); - Block *b57 = new Block("print(57); state = check();// ..........................................................................................................................................................................................................................................................................................................................."); - Block *b58 = new Block("print(58); state = check();// ......................................................................................"); - Block *b59 = new Block("print(59); state = check();// ..................................."); - Block *b60 = new Block("print(60); state = check();// ......................................................................................................................................................................................................................................"); - Block *b61 = new Block("print(61); state = check();// ........................................................................................................................................................."); - Block *b62 = new Block("print(62); state = check();// ......................................................................................."); - Block *b63 = new Block("print(63); state = check();// ....................................................................................................................................................................."); - Block *b64 = new Block("print(64); state = check();// ......................................................................................................................................................................................................................................................................."); - Block *b65 = new Block("print(65); state = check();// ........................................................."); - Block *b66 = new Block("print(66); state = check();// ..............................................................................................................."); - Block *b67 = new Block("print(67); state = check();// ....................................................................................................................................................................................................................."); - Block *b68 = new Block("print(68); state = check();// ......................................................................................................................................................................................................................................................................................................................"); - Block *b69 = new Block("print(69); state = check();// ......................................................................................................................................................"); - Block *b70 = new Block("print(70); state = check();// .........................................................................................................................."); - Block *b71 = new Block("print(71); state = check();// ..........................................................................................................................................................................................................."); - Block *b72 = new Block("print(72); state = check();// .........................................................................................................."); - Block *b73 = new Block("print(73); state = check();// ."); - Block *b74 = new Block("print(74); state = check();// .............................................."); - Block *b75 = new Block("print(75); state = check();// ............................................."); - Block *b76 = new Block("print(76); state = check();// .............................................................................................................................................................................................................................................................................................................................................................................................................................."); - Block *b77 = new Block("print(77); state = check();// ..........................................................................................................................................................................................................................................................................................."); - Block *b78 = new Block("print(78); state = check();// .........................................................................................."); - Block *b79 = new Block("print(79); state = check();// ..................................................................................................................................................................................................................................................."); - Block *b80 = new Block("print(80); state = check();// ...................................."); - Block *b81 = new Block("print(81); state = check();// ................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................"); - Block *b82 = new Block("print(82); state = check();// ...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."); - Block *b83 = new Block("print(83); state = check();// ........................................................................................"); - Block *b84 = new Block("print(84); state = check();// ..................."); - Block *b85 = new Block("print(85); state = check();// ........................................................................................................................................................................................................................................................................................................................................................."); - Block *b86 = new Block("print(86); state = check();// ................................................................................................................................................................................................................................................."); - Block *b87 = new Block("print(87); state = check();// ......"); - Block *b88 = new Block("print(88); state = check();// ...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................."); - Block *b89 = new Block("print(89); state = check();// ......................................................................................................................................................................................................................................................................................................................................................"); - Block *b90 = new Block("print(90); state = check();// ..........................................................................................................................................................................................................................."); - Block *b91 = new Block("print(91); state = check();// .............................................."); + Block *b0 = new Block("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++] }", "the_var"); + Block *b1 = new Block("print(1); state = check();// ...........................................................................", "the_var"); + Block *b2 = new Block("print(2); state = check();// .........", "the_var"); + Block *b3 = new Block("print(3); state = check();// ..................................", "the_var"); + Block *b4 = new Block("print(4); state = check();// ...........................................................................................................................", "the_var"); + Block *b5 = new Block("print(5); state = check();// ..........................................................................................................................................", "the_var"); + Block *b6 = new Block("print(6); state = check();// .........", "the_var"); + Block *b7 = new Block("print(7); state = check();// .............................................................................................................................................................................................", "the_var"); + Block *b8 = new Block("print(8); state = check();// ....................................................................................................................................................................................................................................................", "the_var"); + Block *b9 = new Block("print(9); state = check();// ...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", "the_var"); + Block *b10 = new Block("print(10); state = check();// ...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", "the_var"); + Block *b11 = new Block("print(11); state = check();// ........................................................", "the_var"); + Block *b12 = new Block("print(12); state = check();// ................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", "the_var"); + Block *b13 = new Block("print(13); state = check();// ...................", "the_var"); + Block *b14 = new Block("print(14); state = check();// .............................", "the_var"); + Block *b15 = new Block("print(15); state = check();// ..................................................", "the_var"); + Block *b16 = new Block("print(16); state = check();// ................................................................................................................................................................................................................................................................................................................................................................", "the_var"); + Block *b17 = new Block("print(17); state = check();// ................................................................", "the_var"); + Block *b18 = new Block("print(18); state = check();// ..............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", "the_var"); + Block *b19 = new Block("print(19); state = check();// ......................................................................................................................................................................................................................", "the_var"); + Block *b20 = new Block("print(20); state = check();// ..................................................................................................................................................................", "the_var"); + Block *b21 = new Block("print(21); state = check();// ...........................", "the_var"); + Block *b22 = new Block("print(22); state = check();// .........................................................................................................", "the_var"); + Block *b23 = new Block("print(23); state = check();// .................................................................................................................................................................................................................", "the_var"); + Block *b24 = new Block("print(24); state = check();// ...........................", "the_var"); + Block *b25 = new Block("print(25); state = check();// ......................................................................................................................................................", "the_var"); + Block *b26 = new Block("print(26); state = check();// .........................................................................................................................................................................................................................................................................", "the_var"); + Block *b27 = new Block("print(27); state = check();// .............................................................................................................................................................................", "the_var"); + Block *b28 = new Block("print(28); state = check();// ..............................................................................................................", "the_var"); + Block *b29 = new Block("print(29); state = check();// ...............", "the_var"); + Block *b30 = new Block("print(30); state = check();// .................................................................................................................................................................................................................", "the_var"); + Block *b31 = new Block("print(31); state = check();// ..........................................................................................................................................................................................................", "the_var"); + Block *b32 = new Block("print(32); state = check();// ......................................................................................................", "the_var"); + Block *b33 = new Block("print(33); state = check();// ....", "the_var"); + Block *b34 = new Block("print(34); state = check();// ..........................................................................................................................................", "the_var"); + Block *b35 = new Block("print(35); state = check();// .................................", "the_var"); + Block *b36 = new Block("print(36); state = check();// .........................", "the_var"); + Block *b37 = new Block("print(37); state = check();// ................................................................................................................................", "the_var"); + Block *b38 = new Block("print(38); state = check();// ............................................................................................................................................................................................................................................................................................................................................", "the_var"); + Block *b39 = new Block("print(39); state = check();// ................", "the_var"); + Block *b40 = new Block("print(40); state = check();// ................................................................................................................................................", "the_var"); + Block *b41 = new Block("print(41); state = check();// ...................................................................................................................................", "the_var"); + Block *b42 = new Block("print(42); state = check();// .....................................................", "the_var"); + Block *b43 = new Block("print(43); state = check();// .........", "the_var"); + Block *b44 = new Block("print(44); state = check();// .....................................................................................................................................................", "the_var"); + Block *b45 = new Block("print(45); state = check();// ............................", "the_var"); + Block *b46 = new Block("print(46); state = check();// .............................................................................", "the_var"); + Block *b47 = new Block("print(47); state = check();// ....................................................................................................................................", "the_var"); + Block *b48 = new Block("print(48); state = check();// ............", "the_var"); + Block *b49 = new Block("print(49); state = check();// ............................................................................................................................................................................................................................................................................................", "the_var"); + Block *b50 = new Block("print(50); state = check();// ........................................", "the_var"); + Block *b51 = new Block("print(51); state = check();// .............................................................................................", "the_var"); + Block *b52 = new Block("print(52); state = check();// ..............................................................................", "the_var"); + Block *b53 = new Block("print(53); state = check();// ..............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", "the_var"); + Block *b54 = new Block("print(54); state = check();// .....................................", "the_var"); + Block *b55 = new Block("print(55); state = check();// ...........................................................................................................................................................................................................", "the_var"); + Block *b56 = new Block("print(56); state = check();// ....................................................................................................................................................................................................................", "the_var"); + Block *b57 = new Block("print(57); state = check();// ...........................................................................................................................................................................................................................................................................................................................", "the_var"); + Block *b58 = new Block("print(58); state = check();// ......................................................................................", "the_var"); + Block *b59 = new Block("print(59); state = check();// ...................................", "the_var"); + Block *b60 = new Block("print(60); state = check();// ......................................................................................................................................................................................................................................", "the_var"); + Block *b61 = new Block("print(61); state = check();// .........................................................................................................................................................", "the_var"); + Block *b62 = new Block("print(62); state = check();// .......................................................................................", "the_var"); + Block *b63 = new Block("print(63); state = check();// .....................................................................................................................................................................", "the_var"); + Block *b64 = new Block("print(64); state = check();// .......................................................................................................................................................................................................................................................................", "the_var"); + Block *b65 = new Block("print(65); state = check();// .........................................................", "the_var"); + Block *b66 = new Block("print(66); state = check();// ...............................................................................................................", "the_var"); + Block *b67 = new Block("print(67); state = check();// .....................................................................................................................................................................................................................", "the_var"); + Block *b68 = new Block("print(68); state = check();// ......................................................................................................................................................................................................................................................................................................................", "the_var"); + Block *b69 = new Block("print(69); state = check();// ......................................................................................................................................................", "the_var"); + Block *b70 = new Block("print(70); state = check();// ..........................................................................................................................", "the_var"); + Block *b71 = new Block("print(71); state = check();// ...........................................................................................................................................................................................................", "the_var"); + Block *b72 = new Block("print(72); state = check();// ..........................................................................................................", "the_var"); + Block *b73 = new Block("print(73); state = check();// .", "the_var"); + Block *b74 = new Block("print(74); state = check();// ..............................................", "the_var"); + Block *b75 = new Block("print(75); state = check();// .............................................", "the_var"); + Block *b76 = new Block("print(76); state = check();// ..............................................................................................................................................................................................................................................................................................................................................................................................................................", "the_var"); + Block *b77 = new Block("print(77); state = check();// ...........................................................................................................................................................................................................................................................................................", "the_var"); + Block *b78 = new Block("print(78); state = check();// ..........................................................................................", "the_var"); + Block *b79 = new Block("print(79); state = check();// ...................................................................................................................................................................................................................................................", "the_var"); + Block *b80 = new Block("print(80); state = check();// ....................................", "the_var"); + Block *b81 = new Block("print(81); state = check();// ................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", "the_var"); + Block *b82 = new Block("print(82); state = check();// ....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", "the_var"); + Block *b83 = new Block("print(83); state = check();// ........................................................................................", "the_var"); + Block *b84 = new Block("print(84); state = check();// ...................", "the_var"); + Block *b85 = new Block("print(85); state = check();// .........................................................................................................................................................................................................................................................................................................................................................", "the_var"); + Block *b86 = new Block("print(86); state = check();// .................................................................................................................................................................................................................................................", "the_var"); + Block *b87 = new Block("print(87); state = check();// ......", "the_var"); + Block *b88 = new Block("print(88); state = check();// ....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................", "the_var"); + Block *b89 = new Block("print(89); state = check();// ......................................................................................................................................................................................................................................................................................................................................................", "the_var"); + Block *b90 = new Block("print(90); state = check();// ...........................................................................................................................................................................................................................", "the_var"); + Block *b91 = new Block("print(91); state = check();// ..............................................", "the_var"); b0->AddBranchTo(b30, NULL); b1->AddBranchTo(b66, NULL); b2->AddBranchTo(b51, NULL); diff --git a/src/relooper/test_fuzz6.txt b/src/relooper/test_fuzz6.txt index cd93958c..b9c1499a 100644 --- a/src/relooper/test_fuzz6.txt +++ b/src/relooper/test_fuzz6.txt @@ -1,108 +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++] } -while(1) { +switch (the_var) { +default: { +} +} +L1: while(1) { print(30); state = check();// ................................................................................................................................................................................................................. - if (state % 3 == 1) { - label = 67; + switch (the_var) { + state % 3 == 0 { break; - } else if (!(state % 3 == 0)) { + } + 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(6); state = check();// ......... +switch (the_var) { +default: { +} +} while(1) { print(88); state = check();// .................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... + switch (the_var) { + default: { + } + } print(70); state = check();// .......................................................................................................................... + switch (the_var) { + default: { + } + } L10: while(1) { print(47); state = check();// .................................................................................................................................... + switch (the_var) { + default: { + } + } print(28); state = check();// .............................................................................................................. - while(1) { + switch (the_var) { + default: { + } + } + L13: while(1) { print(75); state = check();// ............................................. + switch (the_var) { + default: { + } + } print(7); state = check();// ............................................................................................................................................................................................. - if (!(state % 2 == 0)) { + 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();// ......................... - if (state % 2 == 0) { + 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();// ................ - if (state % 3 == 1) { + switch (the_var) { + state % 3 == 0 { + break; + } + state % 3 == 1 { label = 74; - } else if (!(state % 3 == 0)) { - label = 32; break; } - while(1) { + default: { + label = 32; + break L20; + } + } + L25: while(1) { if (label == 74) { label = 0; print(73); state = check();// . - if (state % 3 == 1) { + switch (the_var) { + state % 3 == 1 { label = 32; break L20; - } else if (state % 3 == 0) { 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();// .......................................................................................................... - if (state % 2 == 0) { + switch (the_var) { + state % 2 == 0 { label = 92; break L20; + break; + } + default: { + } } print(80); state = check();// .................................... - if (state % 2 == 0) { + 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();// .................................................................................................................................................................................................................................................... - if (state % 2 == 0) { + switch (the_var) { + state % 2 == 0 { continue L10; + break; + } + default: { + } } print(19); state = check();// ...................................................................................................................................................................................................................... + switch (the_var) { + default: { + } + } print(56); state = check();// .................................................................................................................................................................................................................... + switch (the_var) { + default: { + } + } print(34); state = check();// .......................................................................................................................................... - label = 74; + switch (the_var) { + default: { + label = 74; + } + } } print(62); state = check();// ....................................................................................... + switch (the_var) { + default: { + } + } } if (label == 32) { label = 0; print(31); state = check();// .......................................................................................................................................................................................................... + switch (the_var) { + default: { + } + } } else if (label == 92) { label = 0; print(91); state = check();// .............................................. + switch (the_var) { + default: { + } + } print(33); 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();// .............................................................................. - if (state % 2 == 0) { + 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: { + } + } } diff --git a/src/relooper/test_inf.cpp b/src/relooper/test_inf.cpp index 66e712ed..1363bf4b 100644 --- a/src/relooper/test_inf.cpp +++ b/src/relooper/test_inf.cpp @@ -4,556 +4,556 @@ int main() { void *rl = rl_new_relooper(); char buffer[100000]; rl_set_output_buffer(buffer, sizeof(buffer)); - void *b0 = rl_new_block("code 0"); + void *b0 = rl_new_block("code 0", "the_var"); block_map[0] = b0; rl_relooper_add_block(rl, block_map[0]); - void *b1 = rl_new_block("code 1"); + void *b1 = rl_new_block("code 1", "the_var"); block_map[1] = b1; rl_relooper_add_block(rl, block_map[1]); - void *b2 = rl_new_block("code 2"); + void *b2 = rl_new_block("code 2", "the_var"); block_map[2] = b2; rl_relooper_add_block(rl, block_map[2]); - void *b3 = rl_new_block("code 3"); + void *b3 = rl_new_block("code 3", "the_var"); block_map[3] = b3; rl_relooper_add_block(rl, block_map[3]); - void *b4 = rl_new_block("code 4"); + void *b4 = rl_new_block("code 4", "the_var"); block_map[4] = b4; rl_relooper_add_block(rl, block_map[4]); - void *b5 = rl_new_block("code 5"); + void *b5 = rl_new_block("code 5", "the_var"); block_map[5] = b5; rl_relooper_add_block(rl, block_map[5]); - void *b6 = rl_new_block("code 6"); + void *b6 = rl_new_block("code 6", "the_var"); block_map[6] = b6; rl_relooper_add_block(rl, block_map[6]); - void *b7 = rl_new_block("code 7"); + void *b7 = rl_new_block("code 7", "the_var"); block_map[7] = b7; rl_relooper_add_block(rl, block_map[7]); - void *b8 = rl_new_block("code 8"); + void *b8 = rl_new_block("code 8", "the_var"); block_map[8] = b8; rl_relooper_add_block(rl, block_map[8]); - void *b9 = rl_new_block("code 9"); + void *b9 = rl_new_block("code 9", "the_var"); block_map[9] = b9; rl_relooper_add_block(rl, block_map[9]); - void *b10 = rl_new_block("code 10"); + void *b10 = rl_new_block("code 10", "the_var"); block_map[10] = b10; rl_relooper_add_block(rl, block_map[10]); - void *b11 = rl_new_block("code 11"); + void *b11 = rl_new_block("code 11", "the_var"); block_map[11] = b11; rl_relooper_add_block(rl, block_map[11]); - void *b12 = rl_new_block("code 12"); + void *b12 = rl_new_block("code 12", "the_var"); block_map[12] = b12; rl_relooper_add_block(rl, block_map[12]); - void *b13 = rl_new_block("code 13"); + void *b13 = rl_new_block("code 13", "the_var"); block_map[13] = b13; rl_relooper_add_block(rl, block_map[13]); - void *b14 = rl_new_block("code 14"); + void *b14 = rl_new_block("code 14", "the_var"); block_map[14] = b14; rl_relooper_add_block(rl, block_map[14]); - void *b15 = rl_new_block("code 15"); + void *b15 = rl_new_block("code 15", "the_var"); block_map[15] = b15; rl_relooper_add_block(rl, block_map[15]); - void *b16 = rl_new_block("code 16"); + void *b16 = rl_new_block("code 16", "the_var"); block_map[16] = b16; rl_relooper_add_block(rl, block_map[16]); - void *b17 = rl_new_block("code 17"); + void *b17 = rl_new_block("code 17", "the_var"); block_map[17] = b17; rl_relooper_add_block(rl, block_map[17]); - void *b18 = rl_new_block("code 18"); + void *b18 = rl_new_block("code 18", "the_var"); block_map[18] = b18; rl_relooper_add_block(rl, block_map[18]); - void *b19 = rl_new_block("code 19"); + void *b19 = rl_new_block("code 19", "the_var"); block_map[19] = b19; rl_relooper_add_block(rl, block_map[19]); - void *b20 = rl_new_block("code 20"); + void *b20 = rl_new_block("code 20", "the_var"); block_map[20] = b20; rl_relooper_add_block(rl, block_map[20]); - void *b21 = rl_new_block("code 21"); + void *b21 = rl_new_block("code 21", "the_var"); block_map[21] = b21; rl_relooper_add_block(rl, block_map[21]); - void *b22 = rl_new_block("code 22"); + void *b22 = rl_new_block("code 22", "the_var"); block_map[22] = b22; rl_relooper_add_block(rl, block_map[22]); - void *b23 = rl_new_block("code 23"); + void *b23 = rl_new_block("code 23", "the_var"); block_map[23] = b23; rl_relooper_add_block(rl, block_map[23]); - void *b24 = rl_new_block("code 24"); + void *b24 = rl_new_block("code 24", "the_var"); block_map[24] = b24; rl_relooper_add_block(rl, block_map[24]); - void *b25 = rl_new_block("code 25"); + void *b25 = rl_new_block("code 25", "the_var"); block_map[25] = b25; rl_relooper_add_block(rl, block_map[25]); - void *b26 = rl_new_block("code 26"); + void *b26 = rl_new_block("code 26", "the_var"); block_map[26] = b26; rl_relooper_add_block(rl, block_map[26]); - void *b27 = rl_new_block("code 27"); + void *b27 = rl_new_block("code 27", "the_var"); block_map[27] = b27; rl_relooper_add_block(rl, block_map[27]); - void *b28 = rl_new_block("code 28"); + void *b28 = rl_new_block("code 28", "the_var"); block_map[28] = b28; rl_relooper_add_block(rl, block_map[28]); - void *b29 = rl_new_block("code 29"); + void *b29 = rl_new_block("code 29", "the_var"); block_map[29] = b29; rl_relooper_add_block(rl, block_map[29]); - void *b30 = rl_new_block("code 30"); + void *b30 = rl_new_block("code 30", "the_var"); block_map[30] = b30; rl_relooper_add_block(rl, block_map[30]); - void *b31 = rl_new_block("code 31"); + void *b31 = rl_new_block("code 31", "the_var"); block_map[31] = b31; rl_relooper_add_block(rl, block_map[31]); - void *b32 = rl_new_block("code 32"); + void *b32 = rl_new_block("code 32", "the_var"); block_map[32] = b32; rl_relooper_add_block(rl, block_map[32]); - void *b33 = rl_new_block("code 33"); + void *b33 = rl_new_block("code 33", "the_var"); block_map[33] = b33; rl_relooper_add_block(rl, block_map[33]); - void *b34 = rl_new_block("code 34"); + void *b34 = rl_new_block("code 34", "the_var"); block_map[34] = b34; rl_relooper_add_block(rl, block_map[34]); - void *b35 = rl_new_block("code 35"); + void *b35 = rl_new_block("code 35", "the_var"); block_map[35] = b35; rl_relooper_add_block(rl, block_map[35]); - void *b36 = rl_new_block("code 36"); + void *b36 = rl_new_block("code 36", "the_var"); block_map[36] = b36; rl_relooper_add_block(rl, block_map[36]); - void *b37 = rl_new_block("code 37"); + void *b37 = rl_new_block("code 37", "the_var"); block_map[37] = b37; rl_relooper_add_block(rl, block_map[37]); - void *b38 = rl_new_block("code 38"); + void *b38 = rl_new_block("code 38", "the_var"); block_map[38] = b38; rl_relooper_add_block(rl, block_map[38]); - void *b39 = rl_new_block("code 39"); + void *b39 = rl_new_block("code 39", "the_var"); block_map[39] = b39; rl_relooper_add_block(rl, block_map[39]); - void *b40 = rl_new_block("code 40"); + void *b40 = rl_new_block("code 40", "the_var"); block_map[40] = b40; rl_relooper_add_block(rl, block_map[40]); - void *b41 = rl_new_block("code 41"); + void *b41 = rl_new_block("code 41", "the_var"); block_map[41] = b41; rl_relooper_add_block(rl, block_map[41]); - void *b42 = rl_new_block("code 42"); + void *b42 = rl_new_block("code 42", "the_var"); block_map[42] = b42; rl_relooper_add_block(rl, block_map[42]); - void *b43 = rl_new_block("code 43"); + void *b43 = rl_new_block("code 43", "the_var"); block_map[43] = b43; rl_relooper_add_block(rl, block_map[43]); - void *b44 = rl_new_block("code 44"); + void *b44 = rl_new_block("code 44", "the_var"); block_map[44] = b44; rl_relooper_add_block(rl, block_map[44]); - void *b45 = rl_new_block("code 45"); + void *b45 = rl_new_block("code 45", "the_var"); block_map[45] = b45; rl_relooper_add_block(rl, block_map[45]); - void *b46 = rl_new_block("code 46"); + void *b46 = rl_new_block("code 46", "the_var"); block_map[46] = b46; rl_relooper_add_block(rl, block_map[46]); - void *b47 = rl_new_block("code 47"); + void *b47 = rl_new_block("code 47", "the_var"); block_map[47] = b47; rl_relooper_add_block(rl, block_map[47]); - void *b48 = rl_new_block("code 48"); + void *b48 = rl_new_block("code 48", "the_var"); block_map[48] = b48; rl_relooper_add_block(rl, block_map[48]); - void *b49 = rl_new_block("code 49"); + void *b49 = rl_new_block("code 49", "the_var"); block_map[49] = b49; rl_relooper_add_block(rl, block_map[49]); - void *b50 = rl_new_block("code 50"); + void *b50 = rl_new_block("code 50", "the_var"); block_map[50] = b50; rl_relooper_add_block(rl, block_map[50]); - void *b51 = rl_new_block("code 51"); + void *b51 = rl_new_block("code 51", "the_var"); block_map[51] = b51; rl_relooper_add_block(rl, block_map[51]); - void *b52 = rl_new_block("code 52"); + void *b52 = rl_new_block("code 52", "the_var"); block_map[52] = b52; rl_relooper_add_block(rl, block_map[52]); - void *b53 = rl_new_block("code 53"); + void *b53 = rl_new_block("code 53", "the_var"); block_map[53] = b53; rl_relooper_add_block(rl, block_map[53]); - void *b54 = rl_new_block("code 54"); + void *b54 = rl_new_block("code 54", "the_var"); block_map[54] = b54; rl_relooper_add_block(rl, block_map[54]); - void *b55 = rl_new_block("code 55"); + void *b55 = rl_new_block("code 55", "the_var"); block_map[55] = b55; rl_relooper_add_block(rl, block_map[55]); - void *b56 = rl_new_block("code 56"); + void *b56 = rl_new_block("code 56", "the_var"); block_map[56] = b56; rl_relooper_add_block(rl, block_map[56]); - void *b57 = rl_new_block("code 57"); + void *b57 = rl_new_block("code 57", "the_var"); block_map[57] = b57; rl_relooper_add_block(rl, block_map[57]); - void *b58 = rl_new_block("code 58"); + void *b58 = rl_new_block("code 58", "the_var"); block_map[58] = b58; rl_relooper_add_block(rl, block_map[58]); - void *b59 = rl_new_block("code 59"); + void *b59 = rl_new_block("code 59", "the_var"); block_map[59] = b59; rl_relooper_add_block(rl, block_map[59]); - void *b60 = rl_new_block("code 60"); + void *b60 = rl_new_block("code 60", "the_var"); block_map[60] = b60; rl_relooper_add_block(rl, block_map[60]); - void *b61 = rl_new_block("code 61"); + void *b61 = rl_new_block("code 61", "the_var"); block_map[61] = b61; rl_relooper_add_block(rl, block_map[61]); - void *b62 = rl_new_block("code 62"); + void *b62 = rl_new_block("code 62", "the_var"); block_map[62] = b62; rl_relooper_add_block(rl, block_map[62]); - void *b63 = rl_new_block("code 63"); + void *b63 = rl_new_block("code 63", "the_var"); block_map[63] = b63; rl_relooper_add_block(rl, block_map[63]); - void *b64 = rl_new_block("code 64"); + void *b64 = rl_new_block("code 64", "the_var"); block_map[64] = b64; rl_relooper_add_block(rl, block_map[64]); - void *b65 = rl_new_block("code 65"); + void *b65 = rl_new_block("code 65", "the_var"); block_map[65] = b65; rl_relooper_add_block(rl, block_map[65]); - void *b66 = rl_new_block("code 66"); + void *b66 = rl_new_block("code 66", "the_var"); block_map[66] = b66; rl_relooper_add_block(rl, block_map[66]); - void *b67 = rl_new_block("code 67"); + void *b67 = rl_new_block("code 67", "the_var"); block_map[67] = b67; rl_relooper_add_block(rl, block_map[67]); - void *b68 = rl_new_block("code 68"); + void *b68 = rl_new_block("code 68", "the_var"); block_map[68] = b68; rl_relooper_add_block(rl, block_map[68]); - void *b69 = rl_new_block("code 69"); + void *b69 = rl_new_block("code 69", "the_var"); block_map[69] = b69; rl_relooper_add_block(rl, block_map[69]); - void *b70 = rl_new_block("code 70"); + void *b70 = rl_new_block("code 70", "the_var"); block_map[70] = b70; rl_relooper_add_block(rl, block_map[70]); - void *b71 = rl_new_block("code 71"); + void *b71 = rl_new_block("code 71", "the_var"); block_map[71] = b71; rl_relooper_add_block(rl, block_map[71]); - void *b72 = rl_new_block("code 72"); + void *b72 = rl_new_block("code 72", "the_var"); block_map[72] = b72; rl_relooper_add_block(rl, block_map[72]); - void *b73 = rl_new_block("code 73"); + void *b73 = rl_new_block("code 73", "the_var"); block_map[73] = b73; rl_relooper_add_block(rl, block_map[73]); - void *b74 = rl_new_block("code 74"); + void *b74 = rl_new_block("code 74", "the_var"); block_map[74] = b74; rl_relooper_add_block(rl, block_map[74]); - void *b75 = rl_new_block("code 75"); + void *b75 = rl_new_block("code 75", "the_var"); block_map[75] = b75; rl_relooper_add_block(rl, block_map[75]); - void *b76 = rl_new_block("code 76"); + void *b76 = rl_new_block("code 76", "the_var"); block_map[76] = b76; rl_relooper_add_block(rl, block_map[76]); - void *b77 = rl_new_block("code 77"); + void *b77 = rl_new_block("code 77", "the_var"); block_map[77] = b77; rl_relooper_add_block(rl, block_map[77]); - void *b78 = rl_new_block("code 78"); + void *b78 = rl_new_block("code 78", "the_var"); block_map[78] = b78; rl_relooper_add_block(rl, block_map[78]); - void *b79 = rl_new_block("code 79"); + void *b79 = rl_new_block("code 79", "the_var"); block_map[79] = b79; rl_relooper_add_block(rl, block_map[79]); - void *b80 = rl_new_block("code 80"); + void *b80 = rl_new_block("code 80", "the_var"); block_map[80] = b80; rl_relooper_add_block(rl, block_map[80]); - void *b81 = rl_new_block("code 81"); + void *b81 = rl_new_block("code 81", "the_var"); block_map[81] = b81; rl_relooper_add_block(rl, block_map[81]); - void *b82 = rl_new_block("code 82"); + void *b82 = rl_new_block("code 82", "the_var"); block_map[82] = b82; rl_relooper_add_block(rl, block_map[82]); - void *b83 = rl_new_block("code 83"); + void *b83 = rl_new_block("code 83", "the_var"); block_map[83] = b83; rl_relooper_add_block(rl, block_map[83]); - void *b84 = rl_new_block("code 84"); + void *b84 = rl_new_block("code 84", "the_var"); block_map[84] = b84; rl_relooper_add_block(rl, block_map[84]); - void *b85 = rl_new_block("code 85"); + void *b85 = rl_new_block("code 85", "the_var"); block_map[85] = b85; rl_relooper_add_block(rl, block_map[85]); - void *b86 = rl_new_block("code 86"); + void *b86 = rl_new_block("code 86", "the_var"); block_map[86] = b86; rl_relooper_add_block(rl, block_map[86]); - void *b87 = rl_new_block("code 87"); + void *b87 = rl_new_block("code 87", "the_var"); block_map[87] = b87; rl_relooper_add_block(rl, block_map[87]); - void *b88 = rl_new_block("code 88"); + void *b88 = rl_new_block("code 88", "the_var"); block_map[88] = b88; rl_relooper_add_block(rl, block_map[88]); - void *b89 = rl_new_block("code 89"); + void *b89 = rl_new_block("code 89", "the_var"); block_map[89] = b89; rl_relooper_add_block(rl, block_map[89]); - void *b90 = rl_new_block("code 90"); + void *b90 = rl_new_block("code 90", "the_var"); block_map[90] = b90; rl_relooper_add_block(rl, block_map[90]); - void *b91 = rl_new_block("code 91"); + void *b91 = rl_new_block("code 91", "the_var"); block_map[91] = b91; rl_relooper_add_block(rl, block_map[91]); - void *b92 = rl_new_block("code 92"); + void *b92 = rl_new_block("code 92", "the_var"); block_map[92] = b92; rl_relooper_add_block(rl, block_map[92]); - void *b93 = rl_new_block("code 93"); + void *b93 = rl_new_block("code 93", "the_var"); block_map[93] = b93; rl_relooper_add_block(rl, block_map[93]); - void *b94 = rl_new_block("code 94"); + void *b94 = rl_new_block("code 94", "the_var"); block_map[94] = b94; rl_relooper_add_block(rl, block_map[94]); - void *b95 = rl_new_block("code 95"); + void *b95 = rl_new_block("code 95", "the_var"); block_map[95] = b95; rl_relooper_add_block(rl, block_map[95]); - void *b96 = rl_new_block("code 96"); + void *b96 = rl_new_block("code 96", "the_var"); block_map[96] = b96; rl_relooper_add_block(rl, block_map[96]); - void *b97 = rl_new_block("code 97"); + void *b97 = rl_new_block("code 97", "the_var"); block_map[97] = b97; rl_relooper_add_block(rl, block_map[97]); - void *b98 = rl_new_block("code 98"); + void *b98 = rl_new_block("code 98", "the_var"); block_map[98] = b98; rl_relooper_add_block(rl, block_map[98]); - void *b99 = rl_new_block("code 99"); + void *b99 = rl_new_block("code 99", "the_var"); block_map[99] = b99; rl_relooper_add_block(rl, block_map[99]); - void *b100 = rl_new_block("code 100"); + void *b100 = rl_new_block("code 100", "the_var"); block_map[100] = b100; rl_relooper_add_block(rl, block_map[100]); - void *b101 = rl_new_block("code 101"); + void *b101 = rl_new_block("code 101", "the_var"); block_map[101] = b101; rl_relooper_add_block(rl, block_map[101]); - void *b102 = rl_new_block("code 102"); + void *b102 = rl_new_block("code 102", "the_var"); block_map[102] = b102; rl_relooper_add_block(rl, block_map[102]); - void *b103 = rl_new_block("code 103"); + void *b103 = rl_new_block("code 103", "the_var"); block_map[103] = b103; rl_relooper_add_block(rl, block_map[103]); - void *b104 = rl_new_block("code 104"); + void *b104 = rl_new_block("code 104", "the_var"); block_map[104] = b104; rl_relooper_add_block(rl, block_map[104]); - void *b105 = rl_new_block("code 105"); + void *b105 = rl_new_block("code 105", "the_var"); block_map[105] = b105; rl_relooper_add_block(rl, block_map[105]); - void *b106 = rl_new_block("code 106"); + void *b106 = rl_new_block("code 106", "the_var"); block_map[106] = b106; rl_relooper_add_block(rl, block_map[106]); - void *b107 = rl_new_block("code 107"); + void *b107 = rl_new_block("code 107", "the_var"); block_map[107] = b107; rl_relooper_add_block(rl, block_map[107]); - void *b108 = rl_new_block("code 108"); + void *b108 = rl_new_block("code 108", "the_var"); block_map[108] = b108; rl_relooper_add_block(rl, block_map[108]); - void *b109 = rl_new_block("code 109"); + void *b109 = rl_new_block("code 109", "the_var"); block_map[109] = b109; rl_relooper_add_block(rl, block_map[109]); - void *b110 = rl_new_block("code 110"); + void *b110 = rl_new_block("code 110", "the_var"); block_map[110] = b110; rl_relooper_add_block(rl, block_map[110]); - void *b111 = rl_new_block("code 111"); + void *b111 = rl_new_block("code 111", "the_var"); block_map[111] = b111; rl_relooper_add_block(rl, block_map[111]); - void *b112 = rl_new_block("code 112"); + void *b112 = rl_new_block("code 112", "the_var"); block_map[112] = b112; rl_relooper_add_block(rl, block_map[112]); - void *b113 = rl_new_block("code 113"); + void *b113 = rl_new_block("code 113", "the_var"); block_map[113] = b113; rl_relooper_add_block(rl, block_map[113]); - void *b114 = rl_new_block("code 114"); + void *b114 = rl_new_block("code 114", "the_var"); block_map[114] = b114; rl_relooper_add_block(rl, block_map[114]); - void *b115 = rl_new_block("code 115"); + void *b115 = rl_new_block("code 115", "the_var"); block_map[115] = b115; rl_relooper_add_block(rl, block_map[115]); - void *b116 = rl_new_block("code 116"); + void *b116 = rl_new_block("code 116", "the_var"); block_map[116] = b116; rl_relooper_add_block(rl, block_map[116]); - void *b117 = rl_new_block("code 117"); + void *b117 = rl_new_block("code 117", "the_var"); block_map[117] = b117; rl_relooper_add_block(rl, block_map[117]); - void *b118 = rl_new_block("code 118"); + void *b118 = rl_new_block("code 118", "the_var"); block_map[118] = b118; rl_relooper_add_block(rl, block_map[118]); - void *b119 = rl_new_block("code 119"); + void *b119 = rl_new_block("code 119", "the_var"); block_map[119] = b119; rl_relooper_add_block(rl, block_map[119]); - void *b120 = rl_new_block("code 120"); + void *b120 = rl_new_block("code 120", "the_var"); block_map[120] = b120; rl_relooper_add_block(rl, block_map[120]); - void *b121 = rl_new_block("code 121"); + void *b121 = rl_new_block("code 121", "the_var"); block_map[121] = b121; rl_relooper_add_block(rl, block_map[121]); - void *b122 = rl_new_block("code 122"); + void *b122 = rl_new_block("code 122", "the_var"); block_map[122] = b122; rl_relooper_add_block(rl, block_map[122]); - void *b123 = rl_new_block("code 123"); + void *b123 = rl_new_block("code 123", "the_var"); block_map[123] = b123; rl_relooper_add_block(rl, block_map[123]); - void *b124 = rl_new_block("code 124"); + void *b124 = rl_new_block("code 124", "the_var"); block_map[124] = b124; rl_relooper_add_block(rl, block_map[124]); - void *b125 = rl_new_block("code 125"); + void *b125 = rl_new_block("code 125", "the_var"); block_map[125] = b125; rl_relooper_add_block(rl, block_map[125]); - void *b126 = rl_new_block("code 126"); + void *b126 = rl_new_block("code 126", "the_var"); block_map[126] = b126; rl_relooper_add_block(rl, block_map[126]); - void *b127 = rl_new_block("code 127"); + void *b127 = rl_new_block("code 127", "the_var"); block_map[127] = b127; rl_relooper_add_block(rl, block_map[127]); - void *b128 = rl_new_block("code 128"); + void *b128 = rl_new_block("code 128", "the_var"); block_map[128] = b128; rl_relooper_add_block(rl, block_map[128]); - void *b129 = rl_new_block("code 129"); + void *b129 = rl_new_block("code 129", "the_var"); block_map[129] = b129; rl_relooper_add_block(rl, block_map[129]); - void *b130 = rl_new_block("code 130"); + void *b130 = rl_new_block("code 130", "the_var"); block_map[130] = b130; rl_relooper_add_block(rl, block_map[130]); - void *b131 = rl_new_block("code 131"); + void *b131 = rl_new_block("code 131", "the_var"); block_map[131] = b131; rl_relooper_add_block(rl, block_map[131]); - void *b132 = rl_new_block("code 132"); + void *b132 = rl_new_block("code 132", "the_var"); block_map[132] = b132; rl_relooper_add_block(rl, block_map[132]); - void *b133 = rl_new_block("code 133"); + void *b133 = rl_new_block("code 133", "the_var"); block_map[133] = b133; rl_relooper_add_block(rl, block_map[133]); - void *b134 = rl_new_block("code 134"); + void *b134 = rl_new_block("code 134", "the_var"); block_map[134] = b134; rl_relooper_add_block(rl, block_map[134]); - void *b135 = rl_new_block("code 135"); + void *b135 = rl_new_block("code 135", "the_var"); block_map[135] = b135; rl_relooper_add_block(rl, block_map[135]); - void *b136 = rl_new_block("code 136"); + void *b136 = rl_new_block("code 136", "the_var"); block_map[136] = b136; rl_relooper_add_block(rl, block_map[136]); - void *b137 = rl_new_block("code 137"); + void *b137 = rl_new_block("code 137", "the_var"); block_map[137] = b137; rl_relooper_add_block(rl, block_map[137]); - void *b138 = rl_new_block("code 138"); + void *b138 = rl_new_block("code 138", "the_var"); block_map[138] = b138; rl_relooper_add_block(rl, block_map[138]); - void *b139 = rl_new_block("code 139"); + void *b139 = rl_new_block("code 139", "the_var"); block_map[139] = b139; rl_relooper_add_block(rl, block_map[139]); - void *b140 = rl_new_block("code 140"); + void *b140 = rl_new_block("code 140", "the_var"); block_map[140] = b140; rl_relooper_add_block(rl, block_map[140]); - void *b141 = rl_new_block("code 141"); + void *b141 = rl_new_block("code 141", "the_var"); block_map[141] = b141; rl_relooper_add_block(rl, block_map[141]); - void *b142 = rl_new_block("code 142"); + void *b142 = rl_new_block("code 142", "the_var"); block_map[142] = b142; rl_relooper_add_block(rl, block_map[142]); - void *b143 = rl_new_block("code 143"); + void *b143 = rl_new_block("code 143", "the_var"); block_map[143] = b143; rl_relooper_add_block(rl, block_map[143]); - void *b144 = rl_new_block("code 144"); + void *b144 = rl_new_block("code 144", "the_var"); block_map[144] = b144; rl_relooper_add_block(rl, block_map[144]); - void *b145 = rl_new_block("code 145"); + void *b145 = rl_new_block("code 145", "the_var"); block_map[145] = b145; rl_relooper_add_block(rl, block_map[145]); - void *b146 = rl_new_block("code 146"); + void *b146 = rl_new_block("code 146", "the_var"); block_map[146] = b146; rl_relooper_add_block(rl, block_map[146]); - void *b147 = rl_new_block("code 147"); + void *b147 = rl_new_block("code 147", "the_var"); block_map[147] = b147; rl_relooper_add_block(rl, block_map[147]); - void *b148 = rl_new_block("code 148"); + void *b148 = rl_new_block("code 148", "the_var"); block_map[148] = b148; rl_relooper_add_block(rl, block_map[148]); - void *b149 = rl_new_block("code 149"); + void *b149 = rl_new_block("code 149", "the_var"); block_map[149] = b149; rl_relooper_add_block(rl, block_map[149]); - void *b150 = rl_new_block("code 150"); + void *b150 = rl_new_block("code 150", "the_var"); block_map[150] = b150; rl_relooper_add_block(rl, block_map[150]); - void *b151 = rl_new_block("code 151"); + void *b151 = rl_new_block("code 151", "the_var"); block_map[151] = b151; rl_relooper_add_block(rl, block_map[151]); - void *b152 = rl_new_block("code 152"); + void *b152 = rl_new_block("code 152", "the_var"); block_map[152] = b152; rl_relooper_add_block(rl, block_map[152]); - void *b153 = rl_new_block("code 153"); + void *b153 = rl_new_block("code 153", "the_var"); block_map[153] = b153; rl_relooper_add_block(rl, block_map[153]); - void *b154 = rl_new_block("code 154"); + void *b154 = rl_new_block("code 154", "the_var"); block_map[154] = b154; rl_relooper_add_block(rl, block_map[154]); - void *b155 = rl_new_block("code 155"); + void *b155 = rl_new_block("code 155", "the_var"); block_map[155] = b155; rl_relooper_add_block(rl, block_map[155]); - void *b156 = rl_new_block("code 156"); + void *b156 = rl_new_block("code 156", "the_var"); block_map[156] = b156; rl_relooper_add_block(rl, block_map[156]); - void *b157 = rl_new_block("code 157"); + void *b157 = rl_new_block("code 157", "the_var"); block_map[157] = b157; rl_relooper_add_block(rl, block_map[157]); - void *b158 = rl_new_block("code 158"); + void *b158 = rl_new_block("code 158", "the_var"); block_map[158] = b158; rl_relooper_add_block(rl, block_map[158]); - void *b159 = rl_new_block("code 159"); + void *b159 = rl_new_block("code 159", "the_var"); block_map[159] = b159; rl_relooper_add_block(rl, block_map[159]); - void *b160 = rl_new_block("code 160"); + void *b160 = rl_new_block("code 160", "the_var"); block_map[160] = b160; rl_relooper_add_block(rl, block_map[160]); - void *b161 = rl_new_block("code 161"); + void *b161 = rl_new_block("code 161", "the_var"); block_map[161] = b161; rl_relooper_add_block(rl, block_map[161]); - void *b162 = rl_new_block("code 162"); + void *b162 = rl_new_block("code 162", "the_var"); block_map[162] = b162; rl_relooper_add_block(rl, block_map[162]); - void *b163 = rl_new_block("code 163"); + void *b163 = rl_new_block("code 163", "the_var"); block_map[163] = b163; rl_relooper_add_block(rl, block_map[163]); - void *b164 = rl_new_block("code 164"); + void *b164 = rl_new_block("code 164", "the_var"); block_map[164] = b164; rl_relooper_add_block(rl, block_map[164]); - void *b165 = rl_new_block("code 165"); + void *b165 = rl_new_block("code 165", "the_var"); block_map[165] = b165; rl_relooper_add_block(rl, block_map[165]); - void *b166 = rl_new_block("code 166"); + void *b166 = rl_new_block("code 166", "the_var"); block_map[166] = b166; rl_relooper_add_block(rl, block_map[166]); - void *b167 = rl_new_block("code 167"); + void *b167 = rl_new_block("code 167", "the_var"); block_map[167] = b167; rl_relooper_add_block(rl, block_map[167]); - void *b168 = rl_new_block("code 168"); + void *b168 = rl_new_block("code 168", "the_var"); block_map[168] = b168; rl_relooper_add_block(rl, block_map[168]); - void *b169 = rl_new_block("code 169"); + void *b169 = rl_new_block("code 169", "the_var"); block_map[169] = b169; rl_relooper_add_block(rl, block_map[169]); - void *b170 = rl_new_block("code 170"); + void *b170 = rl_new_block("code 170", "the_var"); block_map[170] = b170; rl_relooper_add_block(rl, block_map[170]); - void *b171 = rl_new_block("code 171"); + void *b171 = rl_new_block("code 171", "the_var"); block_map[171] = b171; rl_relooper_add_block(rl, block_map[171]); - void *b172 = rl_new_block("code 172"); + void *b172 = rl_new_block("code 172", "the_var"); block_map[172] = b172; rl_relooper_add_block(rl, block_map[172]); - void *b173 = rl_new_block("code 173"); + void *b173 = rl_new_block("code 173", "the_var"); block_map[173] = b173; rl_relooper_add_block(rl, block_map[173]); - void *b174 = rl_new_block("code 174"); + void *b174 = rl_new_block("code 174", "the_var"); block_map[174] = b174; rl_relooper_add_block(rl, block_map[174]); - void *b175 = rl_new_block("code 175"); + void *b175 = rl_new_block("code 175", "the_var"); block_map[175] = b175; rl_relooper_add_block(rl, block_map[175]); - void *b176 = rl_new_block("code 176"); + void *b176 = rl_new_block("code 176", "the_var"); block_map[176] = b176; rl_relooper_add_block(rl, block_map[176]); - void *b177 = rl_new_block("code 177"); + void *b177 = rl_new_block("code 177", "the_var"); block_map[177] = b177; rl_relooper_add_block(rl, block_map[177]); - void *b178 = rl_new_block("code 178"); + void *b178 = rl_new_block("code 178", "the_var"); block_map[178] = b178; rl_relooper_add_block(rl, block_map[178]); - void *b179 = rl_new_block("code 179"); + void *b179 = rl_new_block("code 179", "the_var"); block_map[179] = b179; rl_relooper_add_block(rl, block_map[179]); - void *b180 = rl_new_block("code 180"); + void *b180 = rl_new_block("code 180", "the_var"); block_map[180] = b180; rl_relooper_add_block(rl, block_map[180]); - void *b181 = rl_new_block("code 181"); + void *b181 = rl_new_block("code 181", "the_var"); block_map[181] = b181; rl_relooper_add_block(rl, block_map[181]); - void *b182 = rl_new_block("code 182"); + void *b182 = rl_new_block("code 182", "the_var"); block_map[182] = b182; rl_relooper_add_block(rl, block_map[182]); - void *b183 = rl_new_block("code 183"); + void *b183 = rl_new_block("code 183", "the_var"); block_map[183] = b183; rl_relooper_add_block(rl, block_map[183]); rl_block_add_branch_to(block_map[0], block_map[2], "uint(i4) >= uint(i5)", NULL); diff --git a/src/relooper/test_inf.txt b/src/relooper/test_inf.txt index bc2fad3e..6db32edb 100644 --- a/src/relooper/test_inf.txt +++ b/src/relooper/test_inf.txt @@ -1,385 +1,1131 @@ code 0 -if (uint(i4) >= uint(i5)) { +switch (the_var) { +uint(i4) >= uint(i5) { code 2 -} else { + switch (the_var) { + default: { + } + } + break; +} +default: { code 1 + switch (the_var) { + default: { + } + } +} } code 3 -if (!(i2 == 0)) { - code 4 - while(1) { - code 5 - if (uint(i6) >= uint(i7)) { - code 7 - } else { - code 6 - } - code 8 - if (uint(i6) >= uint(i7)) { - code 10 - } else { - code 9 +L5: do { + switch (the_var) { + i2 == 0 { + break; + } + default: { + code 4 + switch (the_var) { + default: { } - code 11 - if (uint(i5) >= uint(i6)) { - code 13 - } else { - code 12 } - code 14 - if (!(i2 != 0)) { - break; + 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: { + } + } + } + } + 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 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 12 + switch (the_var) { + default: { + } + } + } + } + code 14 + switch (the_var) { + i2 != 0 { + break; + } + default: { + break L5; + } + } } } -} + } +} while(0); code 15 -if (uint(i4) >= uint(i5)) { +switch (the_var) { +uint(i4) >= uint(i5) { code 17 -} else { + switch (the_var) { + default: { + } + } + break; +} +default: { code 16 + switch (the_var) { + default: { + } + } +} } code 18 -if (!(i2 == 0)) { - code 19 - while(1) { - code 20 - if (uint(i5) >= uint(i6)) { - code 22 - } else { - code 21 - } - code 23 - if (uint(i5) >= uint(i6)) { - code 25 - } else { - code 24 - } - code 26 - if (uint(i5) >= uint(i6)) { - code 28 - } else { - code 27 - } - code 29 - if (uint(i5) >= uint(i6)) { - code 31 - } else { - code 30 - } - code 32 - if (uint(i5) >= uint(i6)) { - code 34 - } else { - code 33 - } - code 35 - if (uint(i5) >= uint(i6)) { - code 37 - } else { - code 36 - } - code 38 - if (uint(i5) >= uint(i6)) { - code 40 - } else { - code 39 - } - code 41 - if (uint(i5) >= uint(i6)) { - code 43 - } else { - code 42 - } - code 44 - if (uint(i5) >= uint(i6)) { - code 46 - } else { - code 45 - } - code 47 - if (uint(i5) >= uint(i6)) { - code 49 - } else { - code 48 - } - code 50 - if (uint(i5) >= uint(i6)) { - code 52 - } else { - code 51 - } - code 53 - if (uint(i5) >= uint(i6)) { - code 55 - } else { - code 54 - } - code 56 - if (uint(i5) >= uint(i6)) { - code 58 - } else { - code 57 - } - code 59 - if (uint(i5) >= uint(i6)) { - code 61 - } else { - code 60 - } - code 62 - if (uint(i5) >= uint(i6)) { - code 64 - } else { - code 63 - } - code 65 - if (uint(i5) >= uint(i6)) { - code 67 - } else { - code 66 - } - code 68 - if (uint(i5) >= uint(i6)) { - code 70 - } else { - code 69 - } - code 71 - if (uint(i5) >= uint(i6)) { - code 73 - } else { - code 72 - } - code 74 - if (uint(i5) >= uint(i6)) { - code 76 - } else { - code 75 - } - code 77 - if (uint(i5) >= uint(i6)) { - code 79 - } else { - code 78 - } - code 80 - if (uint(i5) >= uint(i6)) { - code 82 - } else { - code 81 - } - code 83 - if (uint(i5) >= uint(i6)) { - code 85 - } else { - code 84 - } - code 86 - if (uint(i5) >= uint(i6)) { - code 88 - } else { - code 87 - } - code 89 - if (uint(i5) >= uint(i6)) { - code 91 - } else { - code 90 - } - code 92 - if (uint(i5) >= uint(i6)) { - code 94 - } else { - code 93 - } - code 95 - if (uint(i5) >= uint(i6)) { - code 97 - } else { - code 96 +L26: do { + switch (the_var) { + i2 == 0 { + break; + } + default: { + code 19 + switch (the_var) { + default: { } - code 98 - if (uint(i5) >= uint(i6)) { - code 100 - } else { - code 99 } - code 101 - if (!(i2 != 0)) { - break; + while(1) { + code 20 + 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 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 24 + switch (the_var) { + default: { + } + } + } + } + code 26 + switch (the_var) { + uint(i5) >= uint(i6) { + code 28 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 27 + switch (the_var) { + default: { + } + } + } + } + code 29 + switch (the_var) { + uint(i5) >= uint(i6) { + code 31 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 30 + switch (the_var) { + default: { + } + } + } + } + code 32 + switch (the_var) { + uint(i5) >= uint(i6) { + code 34 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 33 + switch (the_var) { + default: { + } + } + } + } + code 35 + switch (the_var) { + uint(i5) >= uint(i6) { + code 37 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 36 + switch (the_var) { + default: { + } + } + } + } + code 38 + switch (the_var) { + uint(i5) >= uint(i6) { + code 40 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 39 + switch (the_var) { + default: { + } + } + } + } + code 41 + switch (the_var) { + uint(i5) >= uint(i6) { + code 43 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 42 + switch (the_var) { + default: { + } + } + } + } + code 44 + switch (the_var) { + uint(i5) >= uint(i6) { + code 46 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 45 + switch (the_var) { + default: { + } + } + } + } + code 47 + switch (the_var) { + uint(i5) >= uint(i6) { + code 49 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 48 + switch (the_var) { + default: { + } + } + } + } + code 50 + switch (the_var) { + uint(i5) >= uint(i6) { + code 52 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 51 + switch (the_var) { + default: { + } + } + } + } + code 53 + switch (the_var) { + uint(i5) >= uint(i6) { + code 55 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 54 + switch (the_var) { + default: { + } + } + } + } + code 56 + switch (the_var) { + uint(i5) >= uint(i6) { + code 58 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 57 + switch (the_var) { + default: { + } + } + } + } + code 59 + switch (the_var) { + uint(i5) >= uint(i6) { + code 61 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 60 + switch (the_var) { + default: { + } + } + } + } + code 62 + switch (the_var) { + uint(i5) >= uint(i6) { + code 64 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 63 + switch (the_var) { + default: { + } + } + } + } + code 65 + switch (the_var) { + uint(i5) >= uint(i6) { + code 67 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 66 + switch (the_var) { + default: { + } + } + } + } + code 68 + switch (the_var) { + uint(i5) >= uint(i6) { + code 70 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 69 + switch (the_var) { + default: { + } + } + } + } + code 71 + switch (the_var) { + uint(i5) >= uint(i6) { + code 73 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 72 + switch (the_var) { + default: { + } + } + } + } + code 74 + switch (the_var) { + uint(i5) >= uint(i6) { + code 76 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 75 + switch (the_var) { + default: { + } + } + } + } + code 77 + switch (the_var) { + uint(i5) >= uint(i6) { + code 79 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 78 + switch (the_var) { + default: { + } + } + } + } + code 80 + switch (the_var) { + uint(i5) >= uint(i6) { + code 82 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 81 + switch (the_var) { + default: { + } + } + } + } + code 83 + switch (the_var) { + uint(i5) >= uint(i6) { + code 85 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 84 + switch (the_var) { + default: { + } + } + } + } + code 86 + switch (the_var) { + uint(i5) >= uint(i6) { + code 88 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 87 + switch (the_var) { + default: { + } + } + } + } + code 89 + switch (the_var) { + uint(i5) >= uint(i6) { + code 91 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 90 + switch (the_var) { + default: { + } + } + } + } + code 92 + switch (the_var) { + uint(i5) >= uint(i6) { + code 94 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 93 + switch (the_var) { + default: { + } + } + } + } + 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 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 99 + switch (the_var) { + default: { + } + } + } + } + code 101 + switch (the_var) { + i2 != 0 { + break; + } + default: { + break L26; + } + } } } -} + } +} while(0); code 102 -if (uint(i4) >= uint(i5)) { +switch (the_var) { +uint(i4) >= uint(i5) { code 104 -} else { + switch (the_var) { + default: { + } + } + break; +} +default: { code 103 + switch (the_var) { + default: { + } + } +} } code 105 -if (!(i2 == 0)) { - code 106 - while(1) { - code 107 - if (uint(i5) >= uint(i6)) { - code 109 - } else { - code 108 - } - code 110 - if (uint(i5) >= uint(i6)) { - code 112 - } else { - code 111 - } - code 113 - if (uint(i5) >= uint(i6)) { - code 115 - } else { - code 114 - } - code 116 - if (uint(i5) >= uint(i6)) { - code 118 - } else { - code 117 - } - code 119 - if (uint(i5) >= uint(i6)) { - code 121 - } else { - code 120 - } - code 122 - if (uint(i5) >= uint(i6)) { - code 124 - } else { - code 123 - } - code 125 - if (uint(i5) >= uint(i6)) { - code 127 - } else { - code 126 - } - code 128 - if (uint(i5) >= uint(i6)) { - code 130 - } else { - code 129 - } - code 131 - if (uint(i5) >= uint(i6)) { - code 133 - } else { - code 132 - } - code 134 - if (uint(i5) >= uint(i6)) { - code 136 - } else { - code 135 - } - code 137 - if (uint(i5) >= uint(i6)) { - code 139 - } else { - code 138 - } - code 140 - if (uint(i5) >= uint(i6)) { - code 142 - } else { - code 141 - } - code 143 - if (uint(i5) >= uint(i6)) { - code 145 - } else { - code 144 - } - code 146 - if (uint(i5) >= uint(i6)) { - code 148 - } else { - code 147 - } - code 149 - if (uint(i5) >= uint(i6)) { - code 151 - } else { - code 150 - } - code 152 - if (uint(i5) >= uint(i6)) { - code 154 - } else { - code 153 - } - code 155 - if (uint(i5) >= uint(i6)) { - code 157 - } else { - code 156 - } - code 158 - if (uint(i5) >= uint(i6)) { - code 160 - } else { - code 159 - } - code 161 - if (uint(i5) >= uint(i6)) { - code 163 - } else { - code 162 +L143: do { + switch (the_var) { + i2 == 0 { + break; + } + default: { + code 106 + switch (the_var) { + default: { } - code 164 - if (uint(i5) >= uint(i6)) { - code 166 - } else { - code 165 } - code 167 - if (!(i2 != 0)) { - break; + while(1) { + code 107 + 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 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 111 + switch (the_var) { + default: { + } + } + } + } + code 113 + switch (the_var) { + uint(i5) >= uint(i6) { + code 115 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 114 + switch (the_var) { + default: { + } + } + } + } + code 116 + switch (the_var) { + uint(i5) >= uint(i6) { + code 118 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 117 + switch (the_var) { + default: { + } + } + } + } + code 119 + switch (the_var) { + uint(i5) >= uint(i6) { + code 121 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 120 + switch (the_var) { + default: { + } + } + } + } + code 122 + switch (the_var) { + uint(i5) >= uint(i6) { + code 124 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 123 + switch (the_var) { + default: { + } + } + } + } + code 125 + switch (the_var) { + uint(i5) >= uint(i6) { + code 127 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 126 + switch (the_var) { + default: { + } + } + } + } + code 128 + switch (the_var) { + uint(i5) >= uint(i6) { + code 130 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 129 + switch (the_var) { + default: { + } + } + } + } + code 131 + switch (the_var) { + uint(i5) >= uint(i6) { + code 133 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 132 + switch (the_var) { + default: { + } + } + } + } + code 134 + switch (the_var) { + uint(i5) >= uint(i6) { + code 136 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 135 + switch (the_var) { + default: { + } + } + } + } + code 137 + switch (the_var) { + uint(i5) >= uint(i6) { + code 139 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 138 + switch (the_var) { + default: { + } + } + } + } + code 140 + switch (the_var) { + uint(i5) >= uint(i6) { + code 142 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 141 + switch (the_var) { + default: { + } + } + } + } + code 143 + switch (the_var) { + uint(i5) >= uint(i6) { + code 145 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 144 + switch (the_var) { + default: { + } + } + } + } + code 146 + switch (the_var) { + uint(i5) >= uint(i6) { + code 148 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 147 + switch (the_var) { + default: { + } + } + } + } + code 149 + switch (the_var) { + uint(i5) >= uint(i6) { + code 151 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 150 + switch (the_var) { + default: { + } + } + } + } + code 152 + switch (the_var) { + uint(i5) >= uint(i6) { + code 154 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 153 + switch (the_var) { + default: { + } + } + } + } + code 155 + switch (the_var) { + uint(i5) >= uint(i6) { + code 157 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 156 + switch (the_var) { + default: { + } + } + } + } + code 158 + switch (the_var) { + uint(i5) >= uint(i6) { + code 160 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 159 + switch (the_var) { + default: { + } + } + } + } + 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 + switch (the_var) { + default: { + } + } + break; + } + default: { + code 165 + switch (the_var) { + default: { + } + } + } + } + code 167 + switch (the_var) { + i2 != 0 { + break; + } + default: { + break L143; + } + } } } -} + } +} while(0); code 168 -if (uint(i4) >= uint(i5)) { +switch (the_var) { +uint(i4) >= uint(i5) { code 170 -} else { + switch (the_var) { + default: { + } + } + break; +} +default: { code 169 + switch (the_var) { + default: { + } + } +} } code 171 -if (i2 == 0) { +switch (the_var) { +i2 == 0 { code 183 + break; +} +default: { +} } code 172 -while(1) { +switch (the_var) { +default: { +} +} +L235: while(1) { code 173 - if (uint(i5) >= uint(i6)) { + switch (the_var) { + uint(i5) >= uint(i6) { code 175 - } else { + switch (the_var) { + default: { + } + } + break; + } + default: { code 174 + switch (the_var) { + default: { + } + } + } } code 176 - if (uint(i5) >= uint(i6)) { + switch (the_var) { + uint(i5) >= uint(i6) { code 178 - } else { + switch (the_var) { + default: { + } + } + break; + } + default: { code 177 + switch (the_var) { + default: { + } + } + } } code 179 - if (uint(i4) >= uint(i5)) { + switch (the_var) { + uint(i4) >= uint(i5) { code 181 - } else { + switch (the_var) { + default: { + } + } + break; + } + default: { code 180 + switch (the_var) { + default: { + } + } + } } code 182 - if (!(i2 != 0)) { + switch (the_var) { + i2 != 0 { break; } + default: { + break L235; + } + } } code 183 diff --git a/src/runtime.js b/src/runtime.js index e07d5054..33088ad9 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -386,35 +386,51 @@ var Runtime = { // Returns a processor of UTF. // processCChar() receives characters from a C-like UTF representation and returns JS string fragments. + // See RFC3629 for details, the bytes are assumed to be valid UTF-8 // processJSString() receives a JS string and returns a C-like UTF representation in an array UTF8Processor: function() { var buffer = []; var needed = 0; this.processCChar = function (code) { - code = code & 0xff; - if (needed) { - buffer.push(code); - needed--; - } + code = code & 0xFF; + if (buffer.length == 0) { - if (code < 128) return String.fromCharCode(code); + if ((code & 0x80) == 0x00) { // 0xxxxxxx + return String.fromCharCode(code); + } buffer.push(code); - if (code > 191 && code < 224) { + if ((code & 0xE0) == 0xC0) { // 110xxxxx needed = 1; - } else { + } else if ((code & 0xF0) == 0xE0) { // 1110xxxx needed = 2; + } else { // 11110xxx + needed = 3; } return ''; } - if (needed > 0) return ''; + + if (needed) { + buffer.push(code); + needed--; + if (needed > 0) return ''; + } + var c1 = buffer[0]; var c2 = buffer[1]; var c3 = buffer[2]; + var c4 = buffer[3]; var ret; - if (c1 > 191 && c1 < 224) { - ret = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63)); + if (buffer.length == 2) { + ret = String.fromCharCode(((c1 & 0x1F) << 6) | (c2 & 0x3F)); + } else if (buffer.length == 3) { + ret = String.fromCharCode(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)); } else { - ret = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + var codePoint = ((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) | + ((c3 & 0x3F) << 6) | (c4 & 0x3F); + ret = String.fromCharCode( + Math.floor((codePoint - 0x10000) / 0x400) + 0xD800, + (codePoint - 0x10000) % 0x400 + 0xDC00); } buffer.length = 0; return ret; diff --git a/src/settings.js b/src/settings.js index 8757f7b9..03b4ed64 100644 --- a/src/settings.js +++ b/src/settings.js @@ -6,6 +6,11 @@ // emcc -s OPTION1=VALUE1 -s OPTION2=VALUE2 [..other stuff..] // // See https://github.com/kripken/emscripten/wiki/Code-Generation-Modes/ +// +// Note that the values here are the defaults in -O0, that is, unoptimized +// mode. See apply_opt_level in tools/shared.py for how -O1,2,3 affect these +// flags. +// // Tuning var QUANTUM_SIZE = 4; // This is the size of an individual field in a structure. 1 would @@ -131,6 +136,16 @@ var OUTLINING_LIMIT = 0; // A function size above which we try to automatically // large functions (JS engines often compile them very slowly, // compile them with lower optimizations, or do not optimize them // at all). If 0, we do not perform outlining at all. + // To see which funcs are large, you can inspect the source + // in a debug build (-g2 or -g for example), and can run + // tools/find_bigfuncs.py on that to get a sorted list by size. + // Another possibility is to look in the web console in firefox, + // which will note slowly-compiling functions. + // You will probably want to experiment with various values to + // see the impact on compilation time, code size and runtime + // throughput. It is hard to say what values to start testing + // with, but something around 20,000 to 100,000 might make sense. + // (The unit size is number of AST nodes.) // Generated code debugging options var SAFE_HEAP = 0; // Check each write to the heap, for example, this will give a clear @@ -315,11 +330,12 @@ var SIDE_MODULE = 0; // Corresponds to MAIN_MODULE var BUILD_AS_SHARED_LIB = 0; // Whether to build the code as a shared library // 0 here means this is not a shared lib: It is a main file. - // All shared library options (1 and 2) are currently deprecated XXX // 1 means this is a normal shared lib, load it with dlopen() // 2 means this is a shared lib that will be linked at runtime, // which means it will insert its functions into // the global namespace. See STATIC_LIBS_TO_LOAD. + // + // Value 2 is currently deprecated. var RUNTIME_LINKED_LIBS = []; // If this is a main file (BUILD_AS_SHARED_LIB == 0), then // we will link these at runtime. They must have been built with // BUILD_AS_SHARED_LIB == 2. @@ -379,9 +395,7 @@ var HEADLESS = 0; // If 1, will include shim code that tries to 'fake' a browser var BENCHMARK = 0; // If 1, will just time how long main() takes to execute, and not // print out anything at all whatsoever. This is useful for benchmarking. -var ASM_JS = 0; // If 1, generate code in asm.js format. XXX This is highly experimental, - // and will not work on most codebases yet. It is NOT recommended that you - // try this yet. +var ASM_JS = 0; // If 1, generate code in asm.js format. var PGO = 0; // Enables profile-guided optimization in the form of runtime checks for // which functions are actually called. Emits a list during shutdown that you diff --git a/src/shell.html b/src/shell.html index 22bc9de9..ff5f6e35 100644 --- a/src/shell.html +++ b/src/shell.html @@ -87,6 +87,6 @@ }; Module.setStatus('Downloading...'); </script> - <script type='text/javascript'>{{{ SCRIPT_CODE }}}</script> + <script async type='text/javascript'>{{{ SCRIPT_CODE }}}</script> </body> </html> diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h index f0df8dca..1b9a8f25 100644 --- a/system/include/emscripten/emscripten.h +++ b/system/include/emscripten/emscripten.h @@ -19,6 +19,16 @@ extern "C" { #endif /* + * Convenient syntax for inline assembly/js. Allows stuff like + * + * EM_ASM(window.alert('hai')); + * + * Note: double-quotes (") are not supported, but you can use + * single-quotes (') in js anyhow. + */ +#define EM_ASM(...) asm(#__VA_ARGS__) + +/* * Forces LLVM to not dead-code-eliminate a function. Note that * you still need to use EXPORTED_FUNCTIONS so it stays alive * in JS, e.g. @@ -160,6 +170,12 @@ void emscripten_hide_mouse(); void emscripten_set_canvas_size(int width, int height); /* + * Get the current pixel width and height of the <canvas> element + * as well as whether the canvas is fullscreen or not. + */ +void emscripten_get_canvas_size(int *width, int *height, int *isFullscreen); + +/* * Returns the highest-precision representation of the * current time that the browser provides. This uses either * Date.now or performance.now. The result is *not* an diff --git a/tests/aniso.c b/tests/aniso.c index f210e5a5..e8d7bd3f 100644 --- a/tests/aniso.c +++ b/tests/aniso.c @@ -27,6 +27,7 @@ REDISTRIBUTION OF THIS SOFTWARE. #include "SDL/SDL_opengl.h" #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <assert.h> diff --git a/tests/cubegeom_color.c b/tests/cubegeom_color.c index 7d384324..ff30e1a9 100644 --- a/tests/cubegeom_color.c +++ b/tests/cubegeom_color.c @@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE. #endif #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <assert.h> diff --git a/tests/cubegeom_pre.c b/tests/cubegeom_pre.c index fb1a5e02..40b03cf7 100644 --- a/tests/cubegeom_pre.c +++ b/tests/cubegeom_pre.c @@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE. #endif #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <assert.h> diff --git a/tests/cubegeom_pre2.c b/tests/cubegeom_pre2.c index 51961bf7..df04ae31 100644 --- a/tests/cubegeom_pre2.c +++ b/tests/cubegeom_pre2.c @@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE. #endif #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <assert.h> diff --git a/tests/cubegeom_pre2_vao.c b/tests/cubegeom_pre2_vao.c index cba262ff..733c8fc6 100644 --- a/tests/cubegeom_pre2_vao.c +++ b/tests/cubegeom_pre2_vao.c @@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE. #endif #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <assert.h> diff --git a/tests/cubegeom_pre2_vao2.c b/tests/cubegeom_pre2_vao2.c index 3784006c..69096833 100644 --- a/tests/cubegeom_pre2_vao2.c +++ b/tests/cubegeom_pre2_vao2.c @@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE. #endif #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <assert.h> diff --git a/tests/cubegeom_pre3.c b/tests/cubegeom_pre3.c index 4ba2a779..ceaa757e 100644 --- a/tests/cubegeom_pre3.c +++ b/tests/cubegeom_pre3.c @@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE. #endif #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <assert.h> diff --git a/tests/cubegeom_pre_vao.c b/tests/cubegeom_pre_vao.c index cae68cfc..8c598143 100644 --- a/tests/cubegeom_pre_vao.c +++ b/tests/cubegeom_pre_vao.c @@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE. #endif #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <assert.h> diff --git a/tests/cubegeom_texturematrix.c b/tests/cubegeom_texturematrix.c index 99a4469e..abb667eb 100644 --- a/tests/cubegeom_texturematrix.c +++ b/tests/cubegeom_texturematrix.c @@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE. #endif #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <assert.h> diff --git a/tests/float_tex.cpp b/tests/float_tex.cpp index 61531124..c40ff786 100644 --- a/tests/float_tex.cpp +++ b/tests/float_tex.cpp @@ -113,7 +113,7 @@ static void gl_init(void) { /* Store the vertices in a vertex buffer object (VBO) */ glGenBuffers(1, &indicesVBO); glBindBuffer(GL_ARRAY_BUFFER, indicesVBO); - glBufferData(GL_ARRAY_BUFFER, elements.size() * sizeof(uint), &elements[0], GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, elements.size() * sizeof(float), &elements[0], GL_STATIC_DRAW); /* Get the locations of the uniforms so we can access them */ nodeSamplerLocation = glGetUniformLocation(program, "nodeInfo"); glBindAttribLocation(program, 0, "indices"); diff --git a/tests/gl_matrix_identity.c b/tests/gl_matrix_identity.c index 98b1c21f..9f990a77 100644 --- a/tests/gl_matrix_identity.c +++ b/tests/gl_matrix_identity.c @@ -26,6 +26,7 @@ REDISTRIBUTION OF THIS SOFTWARE. #endif #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <assert.h> diff --git a/tests/glshaderinfo.cpp b/tests/glshaderinfo.cpp index 8ec393a8..56da2414 100644 --- a/tests/glshaderinfo.cpp +++ b/tests/glshaderinfo.cpp @@ -1,8 +1,6 @@ #define GL_GLEXT_PROTOTYPES #define EGL_EGLEXT_PROTOTYPES -#define _GNU_SOURCE - #include <math.h> #include <stdlib.h> #include <stdio.h> diff --git a/tests/glut_touchevents.c b/tests/glut_touchevents.c new file mode 100644 index 00000000..2a0054bb --- /dev/null +++ b/tests/glut_touchevents.c @@ -0,0 +1,64 @@ +#include <stdio.h> +#include <stdlib.h> +#include <GL/glut.h> +#include <EGL/egl.h> +#include <emscripten.h> + +#define MULTILINE(...) #__VA_ARGS__ + +int touch_started = 0; +int touch_ended = 0; + +int result = 0; + +void mouseCB(int button, int state, int x, int y) +{ + if(button == GLUT_LEFT_BUTTON) + { + if(state == GLUT_DOWN) + { + touch_started = 1; + } + else if(state == GLUT_UP) + { + touch_ended = 1; + } + } +} + +int main(int argc, char *argv[]) +{ + emscripten_run_script(MULTILINE( + Module.injectEvent = function(eventType, x, y) { + // Desktop browsers do not have the event types for touch events, + // so we fake them by creating a plain-vanilla UIEvent and then + // filling in the fields that we look for with appropriate values. + var touch = { + pageX: x, + pageY: y + }; + var touches = [ touch ]; + touches.item = function(i) { return this[i]; }; + + var event = document.createEvent('UIEvent'); + event.target = Module['canvas']; + event.button = 0; + event.touches = touches; + event.initUIEvent(eventType, true, true, window, 1); + Module['canvas'].dispatchEvent(event); + } + )); + + // Fake a touch device so that glut sets up the appropriate event handlers. + emscripten_run_script("document.documentElement['ontouchstart'] = 1"); + glutInit(&argc, argv); + + glutMouseFunc(&mouseCB); + + emscripten_run_script("Module.injectEvent('touchend', 100, 100)"); + emscripten_run_script("Module.injectEvent('touchstart', 100, 100)"); + result = touch_started && touch_ended; + + REPORT_RESULT(); + return 0; +} diff --git a/tests/http.h b/tests/http.h index 7eff7013..d20f012b 100644 --- a/tests/http.h +++ b/tests/http.h @@ -8,6 +8,7 @@ #ifndef __HTTP_H__ #define __HTTP_H__ +#include <stdarg.h> #include <string> diff --git a/tests/pthread/specific.c b/tests/pthread/specific.c new file mode 100644 index 00000000..914884e7 --- /dev/null +++ b/tests/pthread/specific.c @@ -0,0 +1,60 @@ +#include <stdio.h> +#include <assert.h> +#include <errno.h> +#include <pthread.h> + +static void destr_function(void *arg) +{ + // Not implemented yet in Emscripten +} + +int main(void) +{ + pthread_key_t key = 0; + int rv; + int data = 123; + int *data2; + + assert(pthread_key_delete(key) != 0); + assert(pthread_getspecific(key) == NULL); + + rv = pthread_key_create(&key, &destr_function); + printf("pthread_key_create = %d\n", rv); + assert(rv == 0); + + assert(pthread_getspecific(key) == NULL); + + rv = pthread_setspecific(key, (void*) &data); + printf("pthread_setspecific = %d\n", rv); + assert(rv == 0); + + data2 = pthread_getspecific(key); + assert(data2 != NULL); + printf("pthread_getspecific = %d\n", *data2); + assert(*data2 == 123); + + rv = pthread_key_create(&key, &destr_function); + data2 = pthread_getspecific(key); + printf("pthread_getspecific after key recreate = %p\n", data2); + assert(data2 == NULL); + + rv = pthread_key_delete(key); + printf("pthread_key_delete = %d\n", rv); + assert(rv == 0); + + rv = pthread_key_delete(key); + printf("pthread_key_delete repeated = %d\n", rv); + assert(rv == EINVAL); + + rv = pthread_setspecific(key, NULL); + printf("pthread_setspecific for value NULL = %d\n", rv); + assert(rv == EINVAL); + + rv = pthread_key_create(&key, &destr_function); + assert(rv == 0); + rv = pthread_key_delete(key); + printf("pthread_key_delete just after created = %d\n", rv); + assert(rv == 0); + + return 0; +} diff --git a/tests/pthread/specific.c.txt b/tests/pthread/specific.c.txt new file mode 100644 index 00000000..ad122b3d --- /dev/null +++ b/tests/pthread/specific.c.txt @@ -0,0 +1,8 @@ +pthread_key_create = 0 +pthread_setspecific = 0 +pthread_getspecific = 123 +pthread_getspecific after key recreate = (nil) +pthread_key_delete = 0 +pthread_key_delete repeated = 22 +pthread_setspecific for value NULL = 22 +pthread_key_delete just after created = 0 diff --git a/tests/runner.py b/tests/runner.py index 318946e6..bbbc23e5 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -732,6 +732,7 @@ if __name__ == '__main__': ============================================================================== Running the main part of the test suite. Don't forget to run the other parts! + other - tests separate from the main suite sanity - tests for first run, etc., modifies ~/.emscripten benchmark - run before and after each set of changes before pushing to master, verify no regressions diff --git a/tests/s3tc.c b/tests/s3tc.c index 16ee783f..5f7bee83 100644 --- a/tests/s3tc.c +++ b/tests/s3tc.c @@ -27,6 +27,7 @@ REDISTRIBUTION OF THIS SOFTWARE. #include "SDL/SDL_opengl.h" #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <assert.h> diff --git a/tests/s3tc_crunch.c b/tests/s3tc_crunch.c index 90ed02d9..c2606c8f 100644 --- a/tests/s3tc_crunch.c +++ b/tests/s3tc_crunch.c @@ -27,6 +27,7 @@ REDISTRIBUTION OF THIS SOFTWARE. #include "SDL/SDL_opengl.h" #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <assert.h> diff --git a/tests/sdl_canvas.c b/tests/sdl_canvas.c index 10044ff4..6bd659b8 100644 --- a/tests/sdl_canvas.c +++ b/tests/sdl_canvas.c @@ -1,4 +1,5 @@ #include <stdio.h> +#include <stdlib.h> #include <SDL/SDL.h> #include <SDL/SDL_ttf.h> #include <emscripten.h> @@ -43,6 +44,16 @@ int main(int argc, char **argv) { SDL_Flip(screen); SDL_LockSurface(screen); + + int width, height, isFullscreen; + emscripten_get_canvas_size(&width, &height, &isFullscreen); + + if (width != 600 && height != 450) + { + printf("error: wrong width/height\n"); + abort(); + } + int sum = 0; for (int i = 0; i < screen->h; i++) { sum += *((char*)screen->pixels + i*screen->w*4 + i*4 + 0); diff --git a/tests/sdl_headless.c b/tests/sdl_headless.c new file mode 100644 index 00000000..349c5e26 --- /dev/null +++ b/tests/sdl_headless.c @@ -0,0 +1,65 @@ +#include <stdio.h> +#include <stdlib.h> +#include <SDL/SDL.h> +#include <SDL/SDL_ttf.h> +#include <emscripten.h> + + +int main(int argc, char **argv) { +#if EMSCRIPTEN + // include GL stuff, to check that we can compile hybrid 2d/GL apps + extern void glBegin(int mode); + extern void glBindBuffer(int target, int buffer); + if (argc == 9876) { + glBegin(0); + glBindBuffer(0, 0); + } +#endif + + SDL_Init(SDL_INIT_VIDEO); + SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE); + + printf("Init: %d\n", TTF_Init()); + + TTF_Font *font = TTF_OpenFont("sans-serif", 40); + printf("Font: %p\n", font); + + SDL_Color color = { 0xff, 0x99, 0x00, 0xff }; + + SDL_Surface *text = TTF_RenderText_Solid(font, "hello orange world", color); + + SDL_Color color2 = { 0xbb, 0, 0xff, 0xff }; + SDL_Surface *text2 = TTF_RenderText_Solid(font, "a second line, purple", color2); + + // render + SDL_Rect dest = { 0, 50, 0, 0 }; + SDL_BlitSurface (text, NULL, screen, NULL); + dest.y = 100; + SDL_BlitSurface (text2, NULL, screen, &dest); + + // fill stuff + SDL_Rect rect = { 200, 200, 175, 125 }; + SDL_FillRect(screen, &rect, SDL_MapRGBA(screen->format, 0x22, 0x22, 0xff, 0xff)); + + SDL_Flip(screen); + + SDL_LockSurface(screen); + + int sum = 0; + for (int i = 0; i < screen->h; i++) { + sum += *((char*)screen->pixels + i*screen->w*4 + i*4 + 0); + } + printf("Sum: %d\n", sum); + + printf("you should see two lines of text in different colors and a blue rectangle\n"); + + SDL_Quit(); + + printf("done.\n"); + + int result = sum > 3000 && sum < 5000; // varies a little on different browsers, font differences? + REPORT_RESULT(); + + return 0; +} + diff --git a/tests/sdl_image_prepare_data.c b/tests/sdl_image_prepare_data.c index d45a2e60..043ace47 100644 --- a/tests/sdl_image_prepare_data.c +++ b/tests/sdl_image_prepare_data.c @@ -58,7 +58,7 @@ int main() { printf("prepare..\n"); #define SIZE 203164 - FILE *f = open("screenshot.not", "rb"); + FILE *f = fopen("screenshot.not", "rb"); char *buffer = malloc(SIZE); fread(buffer, SIZE, 1, f); fclose(f); diff --git a/tests/sdl_pumpevents.c b/tests/sdl_pumpevents.c index 64becaad..e765d285 100644 --- a/tests/sdl_pumpevents.c +++ b/tests/sdl_pumpevents.c @@ -40,6 +40,20 @@ int loop2() return r; } +int alphakey() +{ + unsigned i; + int r = 0; + + SDL_PumpEvents(); + + const Uint8 *keys = SDL_GetKeyState(NULL); + if (keys[SDLK_a]) + r = 4; + + return r; +} + int main(int argc, char *argv[]) { SDL_Init(SDL_INIT_EVERYTHING); @@ -49,6 +63,8 @@ int main(int argc, char *argv[]) result += loop1(); emscripten_run_script("keydown(39);"); // right result += loop2(); + emscripten_run_script("keydown(65);"); // A + result += alphakey(); REPORT_RESULT(); return 0; } diff --git a/tests/sockets/test_enet_client.c b/tests/sockets/test_enet_client.c index bf14375c..afcdcae8 100644 --- a/tests/sockets/test_enet_client.c +++ b/tests/sockets/test_enet_client.c @@ -93,6 +93,7 @@ int main (int argc, char ** argv) } #if EMSCRIPTEN +#if USE_IFRAME emscripten_run_script("console.log('adding iframe');" "var iframe = document.createElement('iframe');" "iframe.src = 'server.html';" @@ -101,6 +102,7 @@ int main (int argc, char ** argv) "document.body.appendChild(iframe);" "console.log('added.');"); #endif +#endif #if EMSCRIPTEN emscripten_set_main_loop(main_loop, 3, 1); diff --git a/tests/sockets/test_sockets_echo_server.c b/tests/sockets/test_sockets_echo_server.c index 38e27cac..f01004c3 100644 --- a/tests/sockets/test_sockets_echo_server.c +++ b/tests/sockets/test_sockets_echo_server.c @@ -111,7 +111,7 @@ int main() { int res; atexit(cleanup); - signal(SIGTERM, cleanup); + //signal(SIGTERM, cleanup); memset(&server, 0, sizeof(server_t)); memset(&client, 0, sizeof(client_t)); diff --git a/tests/sockets/test_sockets_partial_server.c b/tests/sockets/test_sockets_partial_server.c index dfe0e249..44ad40a3 100644 --- a/tests/sockets/test_sockets_partial_server.c +++ b/tests/sockets/test_sockets_partial_server.c @@ -38,13 +38,12 @@ void do_send(int sockfd) { int i; int res; char *buffer; - struct sockaddr_in addr; socklen_t addrlen; for (i = 0; i < sizeof(buffers) / sizeof(char*); i++) { buffer = buffers[i]; - res = sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)&addr, sizeof(addr)); + res = send(sockfd, buffer, strlen(buffer), 0); if (res == -1) { perror("send failed"); exit(EXIT_FAILURE); @@ -87,7 +86,7 @@ int main() { int res; atexit(cleanup); - signal(SIGTERM, cleanup); + //signal(SIGTERM, cleanup); // create the socket serverfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); diff --git a/tests/sockets/test_sockets_select_server_no_accept_client.c b/tests/sockets/test_sockets_select_server_down_client.c index e05bd4c8..e05bd4c8 100644 --- a/tests/sockets/test_sockets_select_server_no_accept_client.c +++ b/tests/sockets/test_sockets_select_server_down_client.c diff --git a/tests/sockets/test_sockets_select_server_no_accept_server.c b/tests/sockets/test_sockets_select_server_down_server.c index 4a399ed1..c2e70f33 100644 --- a/tests/sockets/test_sockets_select_server_no_accept_server.c +++ b/tests/sockets/test_sockets_select_server_down_server.c @@ -14,38 +14,13 @@ #include <emscripten.h> #endif -int serverfd = -1; - -void iter(void *arg) { - int res; - fd_set fdr; - fd_set fdw; - - // see if there are any connections to accept / write to - FD_ZERO(&fdr); - FD_ZERO(&fdw); - FD_SET(serverfd, &fdr); - if (clientfd != -1) FD_SET(clientfd, &fdw); - res = select(64, &fdr, &fdw, NULL, NULL); - if (res == -1) { - perror("select failed"); - exit(EXIT_SUCCESS); - } - - if (FD_ISSET(serverfd, &fdr)) { - printf("accepted someone\n"); - clientfd = accept(serverfd, NULL, NULL); - assert(clientfd != -1); - } - - if (FD_ISSET(clientfd, &fdw)) { - do_send(clientfd); - } +void main_loop(void *arg) { } int main() { struct sockaddr_in addr; int res; + int serverfd; // create the socket serverfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -55,7 +30,7 @@ int main() { } fcntl(serverfd, F_SETFL, O_NONBLOCK); - // bind and listen to the supplied port + // bind to the supplied port memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(SOCKK); @@ -70,16 +45,12 @@ int main() { exit(EXIT_FAILURE); } - res = listen(serverfd, 50); - if (res == -1) { - perror("listen failed"); - exit(EXIT_FAILURE); - } + close(serverfd); #if EMSCRIPTEN - emscripten_set_main_loop(iter, 60, 0); + emscripten_set_main_loop(main_loop, 60, 0); #else - while (1) iter(NULL); + while (1) main_loop(NULL); sleep(1); #endif return EXIT_SUCCESS; diff --git a/tests/test_browser.py b/tests/test_browser.py index 69fb6f7e..1c9cbfad 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -38,8 +38,6 @@ class browser(BrowserCore): message='You should see "hello, world!" and a colored cube.') def test_html_source_map(self): - if 'test_html_source_map' not in str(sys.argv): return self.skip('''This test -requires manual intervention; will not be run unless explicitly requested''') cpp_file = os.path.join(self.get_dir(), 'src.cpp') html_file = os.path.join(self.get_dir(), 'src.html') # browsers will try to 'guess' the corresponding original line if a @@ -64,14 +62,20 @@ requires manual intervention; will not be run unless explicitly requested''') ''') # use relative paths when calling emcc, because file:// URIs can only load # sourceContent when the maps are relative paths + try_delete(html_file) + try_delete(html_file + '.map') Popen([PYTHON, EMCC, 'src.cpp', '-o', 'src.html', '-g4'], cwd=self.get_dir()).communicate() + assert os.path.exists(html_file) + assert os.path.exists(html_file + '.map') + import webbrowser, time webbrowser.open_new('file://' + html_file) + time.sleep(1) print ''' -Set the debugger to pause on exceptions -You should see an exception thrown at src.cpp:7. -Press any key to continue.''' - raw_input() +If manually bisecting: + Check that you see src.cpp among the page sources. + Even better, add a breakpoint, e.g. on the printf, then reload, then step through and see the print (best to run with EM_SAVE_DIR=1 for the reload). +''' def build_native_lzma(self): lzma_native = path_from_root('third_party', 'lzma.js', 'lzma-native') @@ -787,6 +791,9 @@ Press any key to continue.''' Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_mouse.c'), '-O2', '--minify', '0', '-o', 'sdl_mouse.js', '--pre-js', 'pre.js']).communicate() self.run_browser('page.html', '', '/report_result?600') + def test_glut_touchevents(self): + self.btest('glut_touchevents.c', '1') + def test_sdl_pumpevents(self): # key events should be detected using SDL_PumpEvents open(os.path.join(self.get_dir(), 'pre.js'), 'w').write(''' @@ -798,7 +805,7 @@ Press any key to continue.''' document.dispatchEvent(event); } ''') - self.btest('sdl_pumpevents.c', expected='3', args=['--pre-js', 'pre.js']) + self.btest('sdl_pumpevents.c', expected='7', args=['--pre-js', 'pre.js']) def test_sdl_audio(self): shutil.copyfile(path_from_root('tests', 'sounds', 'alarmvictory_1.ogg'), os.path.join(self.get_dir(), 'sound.ogg')) @@ -1350,7 +1357,7 @@ Press any key to continue.''' self.btest('perspective.c', reference='perspective.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_runtimelink(self): - return self.skip('shared libs are deprecated') + return self.skip('BUILD_AS_SHARED_LIB=2 is deprecated') main, supp = self.setup_runtimelink_test() open(self.in_dir('supp.cpp'), 'w').write(supp) diff --git a/tests/test_core.py b/tests/test_core.py index 88f6674a..7c5b651f 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -808,6 +808,80 @@ nada ''' self.do_run(src, ',0,,2,C!,0,C!,0,,65535,C!,0,') + def test_double_i64_conversion(self): + if Settings.USE_TYPED_ARRAYS != 2: return self.skip('needs ta2') + + src = r''' + #include <cassert> + #include <inttypes.h> + #include <stdio.h> + + __attribute((noinline)) bool eq(double d, int64_t i) { + int64_t i2 = (int64_t)d; + if (i != i2) { + printf("%.20g converted to int64 returns %lld, not %lld as expected!\n", d, i2, i); + } + return i == i2; + } + + int main() { + assert(eq(0.0, 0)); + assert(eq(-0.0, 0)); + assert(eq(0.1, 0)); + assert(eq(-0.1, 0)); + assert(eq(0.6, 0)); + assert(eq(-0.6, 0)); + assert(eq(1.0, 1)); + assert(eq(-1.0, -1)); + assert(eq(1.1, 1)); + assert(eq(-1.1, -1)); + assert(eq(1.6, 1)); + assert(eq(-1.6, -1)); + assert(eq(4294967295.0, 4294967295LL)); + assert(eq(4294967295.5, 4294967295LL)); + assert(eq(4294967296.0, 4294967296LL)); + assert(eq(4294967296.5, 4294967296LL)); + assert(eq(14294967295.0, 14294967295LL)); + assert(eq(14294967295.5, 14294967295LL)); + assert(eq(14294967296.0, 14294967296LL)); + assert(eq(14294967296.5, 14294967296LL)); + assert(eq(-4294967295.0, -4294967295LL)); + assert(eq(-4294967295.5, -4294967295LL)); + assert(eq(-4294967296.0, -4294967296LL)); + assert(eq(-4294967296.5, -4294967296LL)); + assert(eq(-14294967295.0, -14294967295LL)); + assert(eq(-14294967295.5, -14294967295LL)); + assert(eq(-14294967296.0, -14294967296LL)); + assert(eq(-14294967296.5, -14294967296LL)); + + assert(eq(4294967295.3, 4294967295LL)); + assert(eq(4294967296.3, 4294967296LL)); + assert(eq(14294967295.3, 14294967295LL)); + assert(eq(14294967296.3, 14294967296LL)); + assert(eq(-4294967295.3, -4294967295LL)); + assert(eq(-4294967296.3, -4294967296LL)); + assert(eq(-14294967295.3, -14294967295LL)); + assert(eq(-14294967296.3, -14294967296LL)); + + assert(eq(4294967295.8, 4294967295LL)); + assert(eq(4294967296.8, 4294967296LL)); + assert(eq(14294967295.8, 14294967295LL)); + assert(eq(14294967296.8, 14294967296LL)); + assert(eq(-4294967295.8, -4294967295LL)); + assert(eq(-4294967296.8, -4294967296LL)); + assert(eq(-14294967295.8, -14294967295LL)); + assert(eq(-14294967296.8, -14294967296LL)); + + // The following number is the largest double such that all integers smaller than this can exactly be represented in a double. + assert(eq(9007199254740992.0, 9007199254740992LL /* == 2^53 */)); + assert(eq(-9007199254740992.0, -9007199254740992LL /* == -2^53 */)); + + printf("OK!\n"); + return 0; + } + ''' + self.do_run(src, 'OK!\n'); + def test_negative_zero(self): src = r''' #include <stdio.h> @@ -3678,7 +3752,7 @@ def process(filename): } ''' - self.do_run(src, 'Inline JS is very cool\n3.64') + self.do_run(src, 'Inline JS is very cool\n3.64\n') def test_inlinejs2(self): if Settings.ASM_JS: return self.skip('asm does not support random code, TODO: something that works in asm') @@ -3705,6 +3779,27 @@ def process(filename): self.do_run(src, '4\n200\n') + def test_inlinejs3(self): + if Settings.ASM_JS: return self.skip('asm does not support random code, TODO: something that works in asm') + src = r''' + #include <stdio.h> + #include <emscripten.h> + + int main() { + EM_ASM(Module.print('hello dere1')); + EM_ASM( + Module.print('hello dere2'); + ); + EM_ASM( + Module.print('hello dere3'); + Module.print('hello dere' + 4); + ); + return 0; + } + ''' + + self.do_run(src, 'hello dere1\nhello dere2\nhello dere3\nhello dere4\n') + def test_memorygrowth(self): if Settings.USE_TYPED_ARRAYS == 0: return self.skip('memory growth is only supported with typed arrays') if Settings.ASM_JS: return self.skip('asm does not support memory growth yet') @@ -3861,8 +3956,7 @@ def process(filename): self.do_run(src, 'Hello world!') def test_bigswitch(self): - if Settings.RELOOP: return self.skip('TODO: switch in relooper, issue #781') - if Settings.ASM_JS: return self.skip('TODO: switch too large for asm') + if self.run_name != 'default': return self.skip('TODO: issue #781') src = open(path_from_root('tests', 'bigswitch.cpp')).read() self.do_run(src, '''34962: GL_ARRAY_BUFFER (0x8892) @@ -4570,6 +4664,12 @@ The current type of b is: 9 ''' self.do_run(src, 'BA') + def test_pthread_specific(self): + if self.emcc_args is None: return self.skip('requires emcc') + src = open(path_from_root('tests', 'pthread', 'specific.c'), 'r').read() + expected = open(path_from_root('tests', 'pthread', 'specific.c.txt'), 'r').read() + self.do_run(src, expected, force_c=True) + def test_time(self): # XXX Not sure what the right output is here. Looks like the test started failing with daylight savings changes. Modified it to pass again. src = open(path_from_root('tests', 'time', 'src.c'), 'r').read() @@ -5451,7 +5551,7 @@ The current type of b is: 9 self.do_run(src, '*16,0,4,8,8,12|20,0,4,4,8,12,12,16|24,0,20,0,4,4,8,12,12,16*\n*0,0,0,1,2,64,68,69,72*\n*2*') def test_runtimelink(self): - return self.skip('shared libs are deprecated') + return self.skip('BUILD_AS_SHARED_LIB=2 is deprecated') if Building.LLVM_OPTS: return self.skip('LLVM opts will optimize printf into puts in the parent, and the child will still look for puts') if Settings.ASM_JS: return self.skip('asm does not support runtime linking') @@ -5470,11 +5570,9 @@ The current type of b is: 9 self.do_run(main, 'supp: 54,2\nmain: 56\nsupp see: 543\nmain see: 76\nok.') def test_dlfcn_basic(self): - return self.skip('shared libs are deprecated') if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') Settings.NAMED_GLOBALS = 1 - Settings.LINKABLE = 1 lib_src = ''' #include <cstdio> @@ -5525,7 +5623,6 @@ def process(filename): post_build=add_pre_run_and_checks) def test_dlfcn_qsort(self): - return self.skip('shared libs are deprecated') if self.emcc_args is None: return self.skip('requires emcc') if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') @@ -5622,7 +5719,6 @@ def process(filename): post_build=add_pre_run_and_checks) def test_dlfcn_data_and_fptr(self): - return self.skip('shared libs are deprecated') if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') if Building.LLVM_OPTS: return self.skip('LLVM opts will optimize out parent_func') @@ -5727,7 +5823,6 @@ def process(filename): post_build=add_pre_run_and_checks) def test_dlfcn_alias(self): - return self.skip('shared libs are deprecated') if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') Settings.LINKABLE = 1 @@ -5785,7 +5880,6 @@ def process(filename): Settings.INCLUDE_FULL_LIBRARY = 0 def test_dlfcn_varargs(self): - return self.skip('shared libs are deprecated') if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') Settings.LINKABLE = 1 @@ -6673,6 +6767,7 @@ date: 18.07.2013w; day 18, month 7, year 2013, extra: 201, 3 def test_files(self): if self.emcc_args is not None and '-O2' in self.emcc_args: self.emcc_args += ['--closure', '1'] # Use closure here, to test we don't break FS stuff + self.emcc_args = filter(lambda x: x != '-g', self.emcc_args) # ensure we test --closure 1 --memory-init-file 1 (-g would disable closure) Settings.CORRECT_SIGNS = 1 # Just so our output is what we expect. Can flip them both. post = ''' @@ -6699,8 +6794,13 @@ def process(filename): other.close() src = open(path_from_root('tests', 'files.cpp'), 'r').read() + + mem_file = 'src.cpp.o.js.mem' + try_delete(mem_file) self.do_run(src, ('size: 7\ndata: 100,-56,50,25,10,77,123\nloop: 100 -56 50 25 10 77 123 \ninput:hi there!\ntexto\n$\n5 : 10,30,20,11,88\nother=some data.\nseeked=me da.\nseeked=ata.\nseeked=ta.\nfscanfed: 10 - hello\nok.\ntexte\n', 'size: 7\ndata: 100,-56,50,25,10,77,123\nloop: 100 -56 50 25 10 77 123 \ninput:hi there!\ntexto\ntexte\n$\n5 : 10,30,20,11,88\nother=some data.\nseeked=me da.\nseeked=ata.\nseeked=ta.\nfscanfed: 10 - hello\nok.\n'), post_build=post, extra_emscripten_args=['-H', 'libc/fcntl.h']) + if self.emcc_args and '--memory-init-file' in self.emcc_args: + assert os.path.exists(mem_file) def test_files_m(self): # Test for Module.stdin etc. @@ -7036,14 +7136,15 @@ def process(filename): #include <emscripten.h> int main() { - char *c = "μ†ℱ ╋ℯ╳╋"; + char *c = "μ†ℱ ╋ℯ╳╋ 😇"; printf("%d %d %d %d %s\n", c[0]&0xff, c[1]&0xff, c[2]&0xff, c[3]&0xff, c); - emscripten_run_script("cheez = _malloc(100);" - "Module.writeStringToMemory(\"μ†ℱ ╋ℯ╳╋\", cheez);" - "Module.print([Pointer_stringify(cheez), Module.getValue(cheez, 'i8')&0xff, Module.getValue(cheez+1, 'i8')&0xff, Module.getValue(cheez+2, 'i8')&0xff, Module.getValue(cheez+3, 'i8')&0xff, ]);"); + emscripten_run_script( + "cheez = _malloc(100);" + "Module.writeStringToMemory(\"μ†ℱ ╋ℯ╳╋ 😇\", cheez);" + "Module.print([Pointer_stringify(cheez), Module.getValue(cheez, 'i8')&0xff, Module.getValue(cheez+1, 'i8')&0xff, Module.getValue(cheez+2, 'i8')&0xff, Module.getValue(cheez+3, 'i8')&0xff, ]);"); } ''' - self.do_run(src, '206 188 226 128 μ†ℱ ╋ℯ╳╋\nμ†ℱ ╋ℯ╳╋,206,188,226,128\n'); + self.do_run(src, '206 188 226 128 μ†ℱ ╋ℯ╳╋ 😇\nμ†ℱ ╋ℯ╳╋ 😇,206,188,226,128\n'); def test_direct_string_constant_usage(self): if self.emcc_args is None: return self.skip('requires libcxx') @@ -8232,13 +8333,15 @@ def process(filename): shutil.copyfile(path_from_root('tests', 'freetype', 'LiberationSansBold.ttf'), os.path.join(self.get_dir(), 'font.ttf')) # Main - self.do_run(open(path_from_root('tests', 'freetype', 'main.c'), 'r').read(), - open(path_from_root('tests', 'freetype', 'ref.txt'), 'r').read(), - ['font.ttf', 'test!', '150', '120', '25'], - libraries=self.get_freetype(), - includes=[path_from_root('tests', 'freetype', 'include')], - post_build=post) - #build_ll_hook=self.do_autodebug) + for outlining in [0, 5000]: + Settings.OUTLINING_LIMIT = outlining + print >> sys.stderr, 'outlining:', outlining + self.do_run(open(path_from_root('tests', 'freetype', 'main.c'), 'r').read(), + open(path_from_root('tests', 'freetype', 'ref.txt'), 'r').read(), + ['font.ttf', 'test!', '150', '120', '25'], + libraries=self.get_freetype(), + includes=[path_from_root('tests', 'freetype', 'include')], + post_build=post) # github issue 324 print '[issue 324]' @@ -10071,4 +10174,4 @@ for compiler, quantum, embetter, typed_arrays in [ ) locals()[fullname] = make_run(fullname, fullname, compiler, embetter, quantum, typed_arrays) -del T # T is just a shape for the specific subclasses, we don't test it itself
\ No newline at end of file +del T # T is just a shape for the specific subclasses, we don't test it itself diff --git a/tests/test_other.py b/tests/test_other.py index b3e8a2a1..a6813b07 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -330,27 +330,6 @@ f.close() os.chdir(path_from_root('tests')) # Move away from the directory we are about to remove. shutil.rmtree(tempdirname) - def test_nostdincxx(self): - try: - old = os.environ.get('EMCC_LLVM_TARGET') or '' - for compiler in [EMCC, EMXX]: - for target in ['i386-pc-linux-gnu', 'le32-unknown-nacl']: - print compiler, target - os.environ['EMCC_LLVM_TARGET'] = target - out, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp'), '-v'], stdout=PIPE, stderr=PIPE).communicate() - out2, err2 = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp'), '-v', '-nostdinc++'], stdout=PIPE, stderr=PIPE).communicate() - assert out == out2 - def focus(e): - assert 'search starts here:' in e, e - assert e.count('End of search list.') == 1, e - return e[e.index('search starts here:'):e.index('End of search list.')+20] - err = focus(err) - err2 = focus(err2) - assert err == err2, err + '\n\n\n\n' + err2 - finally: - if old: - os.environ['EMCC_LLVM_TARGET'] = old - def test_failure_error_code(self): for compiler in [EMCC, EMXX]: # Test that if one file is missing from the build, then emcc shouldn't succeed, and shouldn't try to produce an output file. @@ -802,8 +781,8 @@ f.close() for test_opts, expected_ranges in [ ([], { - 100: (190, 250), - 250: (200, 330), + 100: (190, 275), + 250: (200, 500), 500: (250, 500), 1000: (230, 1000), 2000: (380, 2000), @@ -1033,7 +1012,7 @@ int main(int argc, char const *argv[]) self.assertContained('hello from lib', run_js(os.path.join(self.get_dir(), 'a.out.js'))) def test_runtimelink_multi(self): - return self.skip('shared libs are deprecated') + return self.skip('BUILD_AS_SHARED_LIB=2 is deprecated') if Settings.ASM_JS: return self.skip('asm does not support runtime linking yet') if SPIDERMONKEY_ENGINE not in JS_ENGINES: return self.skip('cannot run without spidermonkey due to node limitations') @@ -1902,7 +1881,7 @@ seeked= file. if SPIDERMONKEY_ENGINE not in JS_ENGINES: return self.skip('cannot run without spidermonkey due to node limitations (Uint8ClampedArray etc.)') shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'example.png')) - Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_canvas.c'), '-s', 'HEADLESS=1']).communicate() + Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_headless.c'), '-s', 'HEADLESS=1']).communicate() output = run_js('a.out.js', engine=SPIDERMONKEY_ENGINE, stderr=PIPE) assert '''Init: 0 Font: 0x1 diff --git a/tests/test_sanity.py b/tests/test_sanity.py index 931645e2..4188afff 100644 --- a/tests/test_sanity.py +++ b/tests/test_sanity.py @@ -519,4 +519,29 @@ fi finally: del os.environ['EMCC_DEBUG'] - del os.environ['EMCC_JSOPT_MIN_CHUNK_SIZE']
\ No newline at end of file + del os.environ['EMCC_JSOPT_MIN_CHUNK_SIZE'] + + def test_nostdincxx(self): + restore() + Cache.erase() + + try: + old = os.environ.get('EMCC_LLVM_TARGET') or '' + for compiler in [EMCC, EMXX]: + for target in ['i386-pc-linux-gnu', 'le32-unknown-nacl']: + print compiler, target + os.environ['EMCC_LLVM_TARGET'] = target + out, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp'), '-v'], stdout=PIPE, stderr=PIPE).communicate() + out2, err2 = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp'), '-v', '-nostdinc++'], stdout=PIPE, stderr=PIPE).communicate() + assert out == out2 + def focus(e): + assert 'search starts here:' in e, e + assert e.count('End of search list.') == 1, e + return e[e.index('search starts here:'):e.index('End of search list.')+20] + err = focus(err) + err2 = focus(err2) + assert err == err2, err + '\n\n\n\n' + err2 + finally: + if old: + os.environ['EMCC_LLVM_TARGET'] = old + diff --git a/tests/test_sockets.py b/tests/test_sockets.py index 4f6ee2a9..82ddc6fe 100644 --- a/tests/test_sockets.py +++ b/tests/test_sockets.py @@ -142,11 +142,12 @@ class sockets(BrowserCore): # def test_sockets_gethostbyname(self): # self.btest(os.path.join('sockets', 'test_sockets_gethostbyname.c'), expected='0', args=['-O2', '-DSOCKK=8997']) - def test_sockets_select_server_no_accept(self): + def test_sockets_select_server_down(self): for harness in [ - WebsockifyServerHarness(os.path.join('sockets', 'test_sockets_select_server_no_accept_server.c'), ['-DSOCKK=8995'], 8996, 8995) + WebsockifyServerHarness(os.path.join('sockets', 'test_sockets_select_server_down_server.c'), ['-DSOCKK=9002'], 9003, 9002) ]: - self.btest(os.path.join('sockets', 'test_sockets_select_server_no_accept_client.c'), expected='266', args=['-DSOCKK=8996']) + with harness: + self.btest(os.path.join('sockets', 'test_sockets_select_server_down_client.c'), expected='266', args=['-DSOCKK=9003']) def test_sockets_select_server_closes_connection_rw(self): sockets_include = '-I'+path_from_root('tests', 'sockets') @@ -178,7 +179,7 @@ class sockets(BrowserCore): try: proc = make_relay_server(2234, 2236) pids.append(proc.pid) - self.btest(os.path.join('sockets', 'test_enet_client.c'), expected='0', args=['-DSOCKK=2237'] + enet) + self.btest(os.path.join('sockets', 'test_enet_client.c'), expected='0', args=['-DSOCKK=2237', '-DUSE_IFRAME'] + enet) finally: clean_pids(pids); diff --git a/tests/tex_nonbyte.c b/tests/tex_nonbyte.c index 8f2ec162..960d0efb 100644 --- a/tests/tex_nonbyte.c +++ b/tests/tex_nonbyte.c @@ -37,6 +37,7 @@ REDISTRIBUTION OF THIS SOFTWARE. #endif #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <assert.h> diff --git a/tests/unistd/misc.out b/tests/unistd/misc.out index 43971955..8f03f688 100644 --- a/tests/unistd/misc.out +++ b/tests/unistd/misc.out @@ -44,3 +44,10 @@ setgid: -1, errno: 1 setegid: -1, errno: 1 setuid: -1, errno: 1 seteuid: -1, errno: 1 +setpgrp: -1, errno: 1 +setsid: -1, errno: 1 +setpgid: -1, errno: 1 +setregid: -1, errno: 1 +setreuid: -1, errno: 1 +getgroups: 1, result: 0, errno: 0 +setgroups: -1, errno: 1 diff --git a/tools/file_packager.py b/tools/file_packager.py index 33ccebad..bb62e905 100644 --- a/tools/file_packager.py +++ b/tools/file_packager.py @@ -329,13 +329,55 @@ if has_preloaded: # Data requests - for getting a block of data out of the big archive - have a similar API to XHRs code += ''' - function DataRequest() {} + function DataRequest(start, end, crunched, audio) { + this.start = start; + this.end = end; + this.crunched = crunched; + this.audio = audio; + } DataRequest.prototype = { requests: {}, open: function(mode, name) { + this.name = name; this.requests[name] = this; + Module['addRunDependency']('fp ' + this.name); + }, + send: function() {}, + onload: function() { + var data = this.byteArray.subarray(this.start, this.end); + var size = this.end - this.start; + var ptr = Module['_malloc'](size); // XXX leaked if a preload plugin replaces with new data + Module['HEAPU8'].set(data, ptr); + var arrayBuffer = Module['HEAPU8'].subarray(ptr, ptr + size); + assert(arrayBuffer, 'Loading file ' + name + ' failed'); + var byteArray = !arrayBuffer.subarray ? new Uint8Array(arrayBuffer) : arrayBuffer; + + if (this.crunched) { + var ddsHeader = byteArray.subarray(0, 128); + var that = this; + requestDecrunch(this.name, byteArray.subarray(128), function(ddsData) { + byteArray = new Uint8Array(ddsHeader.length + ddsData.length); + byteArray.set(ddsHeader, 0); + byteArray.set(ddsData, 128); + that.finish(byteArray); + }); + } else { + this.finish(byteArray); + } + }, + finish: function(byteArray) { + var that = this; + Module['FS_createPreloadedFile'](PATH.dirname(this.name), PATH.basename(this.name), byteArray, true, true, function() { + Module['removeRunDependency']('fp ' + that.name); + }, function() { + if (that.audio) { + Module['removeRunDependency']('fp ' + that.name); // workaround for chromium bug 124926 (still no audio with this, but at least we don't hang) + } else { + Runtime.warn('Preloading file ' + that.name + ' failed'); + } + }); + this.requests[this.name] = null; }, - send: function() {} }; ''' @@ -364,66 +406,23 @@ for file_ in data_files: # Preload varname = 'filePreload%d' % counter counter += 1 - dds = crunch and filename.endswith(CRUNCH_INPUT_SUFFIX) - - prepare = '' - finish = "Module['removeRunDependency']('fp %s');\n" % filename - - if dds: - # decompress crunch format into dds - prepare = ''' - var ddsHeader = byteArray.subarray(0, %(dds_header_size)d); - requestDecrunch('%(filename)s', byteArray.subarray(%(dds_header_size)d), function(ddsData) { - byteArray = new Uint8Array(ddsHeader.length + ddsData.length); - byteArray.set(ddsHeader, 0); - byteArray.set(ddsData, %(dds_header_size)d); -''' % { 'filename': filename, 'dds_header_size': DDS_HEADER_SIZE } - - finish += ''' - }); -''' - - code += ''' - var %(varname)s = new %(request)s(); - %(varname)s.open('GET', '%(filename)s', true); - %(varname)s.responseType = 'arraybuffer'; - %(varname)s.onload = function() { - var arrayBuffer = %(varname)s.response; - assert(arrayBuffer, 'Loading file %(filename)s failed.'); - var byteArray = !arrayBuffer.subarray ? new Uint8Array(arrayBuffer) : arrayBuffer; - %(prepare)s - Module['FS_createPreloadedFile']('%(dirname)s', '%(basename)s', byteArray, true, true, function() { - %(finish)s - }%(fail)s); - }; - Module['addRunDependency']('fp %(filename)s'); - %(varname)s.send(null); + code += ''' new DataRequest(%(start)d, %(end)d, %(crunched)s, %(audio)s).open('GET', '%(filename)s'); ''' % { - 'request': 'DataRequest', # In the past we also supported XHRs here - 'varname': varname, - 'filename': filename, - 'dirname': dirname, - 'basename': basename, - 'prepare': prepare, - 'finish': finish, - 'fail': '' if filename[-4:] not in AUDIO_SUFFIXES else ''', function() { Module['removeRunDependency']('fp %s') }''' % filename # workaround for chromium bug 124926 (still no audio with this, but at least we don't hang) - } + 'filename': file_['dstpath'], + 'start': file_['data_start'], + 'end': file_['data_end'], + 'crunched': '1' if crunch and filename.endswith(CRUNCH_INPUT_SUFFIX) else '0', + 'audio': '1' if filename[-4:] in AUDIO_SUFFIXES else '0', + } else: assert 0 if has_preloaded: # Get the big archive and split it up - use_data = '' + use_data = ' DataRequest.prototype.byteArray = byteArray;\n' for file_ in data_files: if file_['mode'] == 'preload': - use_data += ''' - curr = DataRequest.prototype.requests['%s']; - var data = byteArray.subarray(%d, %d); - var ptr = Module['_malloc'](%d); - Module['HEAPU8'].set(data, ptr); - curr.response = Module['HEAPU8'].subarray(ptr, ptr + %d); - curr.onload(); - ''' % (file_['dstpath'], file_['data_start'], file_['data_end'], file_['data_end'] - file_['data_start'], file_['data_end'] - file_['data_start']) + use_data += ' DataRequest.prototype.requests["%s"].onload();\n' % (file_['dstpath']) use_data += " Module['removeRunDependency']('datafile_%s');\n" % data_target if Compression.on: diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index e61317af..9a5104bf 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1236,7 +1236,7 @@ function vacuum(ast) { } } break; case 'label': { - if (node[2][0] === 'toplevel' && (!node[2][1] || node[2][1].length === 0)) { + if (node[2] && node[2][0] === 'toplevel' && (!node[2][1] || node[2][1].length === 0)) { return emptyNode(); } } break; @@ -3026,58 +3026,90 @@ function outline(ast) { if (ignore.indexOf(node) >= 0) continue; var type = node[0]; if (measureSize(node) >= minSize) { - if (type === 'if' && node[3]) { + if ((type === 'if' && node[3]) || type === 'switch') { + var isIf = type === 'if'; var reps = []; var helper = getHelper(); // clear helper reps.push(['stat', ['assign', true, ['name', helper], ['num', 1]]]); // 1 means continue in ifs // gather parts - var parts = []; - var curr = node; - while (1) { - parts.push({ condition: curr[1], body: curr[2] }); - curr = curr[3]; - if (!curr) break; - if (curr[0] != 'if') { - parts.push({ condition: null, body: curr }); - break; + var parts; + if (isIf) { + parts = []; + var curr = node; + while (1) { + parts.push({ condition: curr[1], body: curr[2] }); + curr = curr[3]; + if (!curr) break; + if (curr[0] != 'if') { + parts.push({ condition: null, body: curr }); + break; + } } + } else { // switch + var switchVar = getHelper(); // switch var could be an expression + reps.push(['stat', ['assign', true, ['name', switchVar], node[1]]]); + parts = node[2].map(function(case_) { + return { condition: case_[0], body: case_[1] }; + }); } // chunkify. Each chunk is a chain of if-elses, with the new overhead just on entry and exit var chunks = []; var currSize = 0; var currChunk = []; + var force = false; // when we hit a case X: that falls through, we force inclusion of everything until a full case parts.forEach(function(part) { var size = (part.condition ? measureSize(part.condition) : 0) + measureSize(part.body) + 5; // add constant for overhead of extra code assert(size > 0); - if (size + currSize >= minSize && currSize) { + if (size + currSize >= minSize && currSize && !force) { chunks.push(currChunk); currChunk = []; currSize = 0; } currChunk.push(part); currSize += size; + if (!isIf) { + var last = part.body; + last = last[stats.length-1]; + if (last && last[0] === 'block') last = last[1][last[1].length-1]; + if (last && last[0] === 'stat') last = last[1]; + force = !last || last[0] !== 'break'; + } }); assert(currSize); chunks.push(currChunk); // generate flattened code chunks.forEach(function(chunk) { var pre = ['stat', ['assign', true, ['name', helper], ['num', 0]]]; - var chain = null, tail = null; - chunk.forEach(function(part) { - // add to chain - var contents = makeIf(part.condition || ['num', 1], part.body[1]); - if (chain) { - tail[3] = contents; - } else { - chain = contents; - ignore.push(contents); + if (isIf) { + var chain = null, tail = null; + chunk.forEach(function(part) { + // add to chain + var contents = makeIf(part.condition || ['num', 1], part.body[1]); + if (chain) { + tail[3] = contents; + } else { + chain = contents; + ignore.push(contents); + } + tail = contents; + }); + // if none of the ifs were entered, in the final else note that we need to continue + tail[3] = ['block', [['stat', ['assign', true, ['name', helper], ['num', 1]]]]]; + reps.push(makeIf(['name', helper], [pre, chain])); + } else { // switch + var hasDefault; + var s = makeSwitch(['binary', '|', ['name', switchVar], ['num', 0]], chunk.map(function(part) { + hasDefault = hasDefault || part.condition === null; + return [part.condition, part.body]; + })); + // if no default, add one where we note that we need to continue + if (!hasDefault) { + s[2].push([null, [['block', [['stat', ['assign', true, ['name', helper], ['num', 1]]]]]]]); } - tail = contents; - }); - // if none of the ifs were entered, in the final else note that we need to continue - tail[3] = ['block', [['stat', ['assign', true, ['name', helper], ['num', 1]]]]]; - reps.push(makeIf(['name', helper], [pre, chain])); + ignore.push(s); + reps.push(makeIf(['name', helper], [pre, s])); + } }); // replace code and update i stats.splice.apply(stats, [i, 1].concat(reps)); @@ -3091,6 +3123,8 @@ function outline(ast) { }); } + var maxTotalOutlinings = Infinity; // debugging tool + // Prepares information for spilling of local variables function analyzeFunction(func, asmData) { var stack = []; // list of variables, each gets 8 bytes @@ -3110,7 +3144,7 @@ function outline(ast) { // The control variables are zeroed out when calling an outlined function, and after using // the value after they return. var size = measureSize(func); - asmData.maxOutlinings = Math.round(3*size/extraInfo.sizeToOutline); + asmData.maxOutlinings = Math.min(Math.round(3*size/extraInfo.sizeToOutline), maxTotalOutlinings); asmData.intendedPieces = Math.ceil(size/extraInfo.sizeToOutline); asmData.totalStackSize = stackSize + (stack.length + 2*asmData.maxOutlinings)*8; asmData.controlStackPos = function(i) { return stackSize + (stack.length + i)*8 }; @@ -3440,6 +3474,7 @@ function outline(ast) { asmData.splitCounter--; return []; } + maxTotalOutlinings--; for (var v in owned) { if (v != 'sp') delete asmData.vars[v]; // parent does not need these anymore } @@ -3596,6 +3631,8 @@ function outline(ast) { var funcs = ast[1]; + var maxTotalFunctions = Infinity; // debugging tool + var more = true; while (more) { more = false; @@ -3603,9 +3640,11 @@ function outline(ast) { var newFuncs = []; funcs.forEach(function(func) { + vacuum(func); // clear out empty nodes that affect code size var asmData = normalizeAsm(func); var size = measureSize(func); - if (size >= extraInfo.sizeToOutline) { + if (size >= extraInfo.sizeToOutline && maxTotalFunctions > 0) { + maxTotalFunctions--; aggressiveVariableElimination(func, asmData); flatten(func, asmData); analyzeFunction(func, asmData); diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index acb87460..5d7dc562 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -224,6 +224,10 @@ EMSCRIPTEN_FUNCS(); total_size = len(js) js = None + if 'last' in passes and len(funcs) > 0: + if max([len(func[1]) for func in funcs]) > 200000: + print >> sys.stderr, 'warning: Output contains some very large functions, consider using OUTLINING_LIMIT to break them up (see settings.js)' + # if we are making source maps, we want our debug numbering to start from the # top of the file, so avoid breaking the JS into chunks cores = 1 if source_map else int(os.environ.get('EMCC_CORES') or multiprocessing.cpu_count()) diff --git a/tools/jsrun.py b/tools/jsrun.py index 27c55350..571e9cee 100644 --- a/tools/jsrun.py +++ b/tools/jsrun.py @@ -15,7 +15,7 @@ def timeout_run(proc, timeout, note='unnamed process', full_output=False): def run_js(filename, engine=None, args=[], check_timeout=False, stdout=PIPE, stderr=None, cwd=None, full_output=False): if type(engine) is not list: engine = [engine] - command = engine + [filename] + (['--'] if 'd8' in engine[0] else []) + args + command = engine + [filename] + (['--'] if 'd8' in engine[0] or 'jsc' in engine[0] else []) + args return timeout_run( Popen( command, diff --git a/tools/shared.py b/tools/shared.py index 0d0f20d4..3ee5db23 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -290,7 +290,7 @@ def check_node_version(): # we re-check sanity when the settings are changed) # We also re-check sanity and clear the cache when the version changes -EMSCRIPTEN_VERSION = '1.5.5' +EMSCRIPTEN_VERSION = '1.5.6' def generate_sanity(): return EMSCRIPTEN_VERSION + '|' + get_llvm_target() + '|' + LLVM_ROOT diff --git a/tools/test-js-optimizer-asm-outline1-output.js b/tools/test-js-optimizer-asm-outline1-output.js index d8ea9446..895004d8 100644 --- a/tools/test-js-optimizer-asm-outline1-output.js +++ b/tools/test-js-optimizer-asm-outline1-output.js @@ -321,6 +321,48 @@ function chain() { helper$0 = HEAP32[sp + 8 >> 2] | 0; STACKTOP = sp; } +function switchh() { + var helper$0 = 0, helper$1 = 0, sp = 0; + sp = STACKTOP; + STACKTOP = STACKTOP + 296 | 0; + helper$0 = 1; + helper$1 = x; + if (helper$0) { + helper$0 = 0; + switch (helper$1 | 0) { + case 0: + { + f(0); + g(); + break; + } + default: + { + helper$0 = 1; + } + } + } + HEAP32[sp + 8 >> 2] = helper$0; + HEAP32[sp + 16 >> 2] = helper$1; + HEAP32[sp + 40 >> 2] = 0; + HEAP32[sp + 44 >> 2] = 0; + switchh$2(sp); + helper$0 = HEAP32[sp + 8 >> 2] | 0; + HEAP32[sp + 8 >> 2] = helper$0; + HEAP32[sp + 16 >> 2] = helper$1; + HEAP32[sp + 32 >> 2] = 0; + HEAP32[sp + 36 >> 2] = 0; + switchh$1(sp); + helper$0 = HEAP32[sp + 8 >> 2] | 0; + if (helper$0) { + helper$0 = 0; + HEAP32[sp + 16 >> 2] = helper$1; + HEAP32[sp + 24 >> 2] = 0; + HEAP32[sp + 28 >> 2] = 0; + switchh$0(sp); + } + STACKTOP = sp; +} function lin$0(sp) { sp = sp | 0; c(14); @@ -645,4 +687,98 @@ function chain$4(sp) { } HEAP32[sp + 8 >> 2] = helper$0; } +function switchh$0(sp) { + sp = sp | 0; + var helper$1 = 0; + helper$1 = HEAP32[sp + 16 >> 2] | 0; + switch (helper$1 | 0) { + case 4: + { + f(4); + g(); + } + case 5: + { + f(5); + g(); + } + case 6: + { + f(6); + g(); + } + default: + { + print(9); + } + } +} +function switchh$1(sp) { + sp = sp | 0; + var helper$0 = 0, helper$1 = 0; + helper$0 = HEAP32[sp + 8 >> 2] | 0; + helper$1 = HEAP32[sp + 16 >> 2] | 0; + if (helper$0) { + helper$0 = 0; + switch (helper$1 | 0) { + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 3: + { + f(3); + g(); + break; + } + default: + { + helper$0 = 1; + } + } + } + HEAP32[sp + 8 >> 2] = helper$0; +} +function switchh$2(sp) { + sp = sp | 0; + var helper$0 = 0, helper$1 = 0; + helper$0 = HEAP32[sp + 8 >> 2] | 0; + helper$1 = HEAP32[sp + 16 >> 2] | 0; + if (helper$0) { + helper$0 = 0; + switch (helper$1 | 0) { + case 1: + { + f(1); + g(); + break; + } + default: + { + helper$0 = 1; + } + } + } + if (helper$0) { + helper$0 = 0; + switch (helper$1 | 0) { + case 2: + { + f(2); + g(); + break; + } + default: + { + helper$0 = 1; + } + } + } + HEAP32[sp + 8 >> 2] = helper$0; +} diff --git a/tools/test-js-optimizer-asm-outline1.js b/tools/test-js-optimizer-asm-outline1.js index 311cb206..3c454182 100644 --- a/tools/test-js-optimizer-asm-outline1.js +++ b/tools/test-js-optimizer-asm-outline1.js @@ -259,5 +259,53 @@ function chain() { print(99); } } +function switchh() { + switch (x) { + case 0: { + f(0); + g(); + break; + } + case 1: { + f(1); + g(); + break; + } + case 2: { + f(2); + g(); + break; + } + case 21: // gotta keem em unseparated + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 3: { // these too + f(3); + g(); + break; + } + case 4: { + f(4); + g(); + } + case 5: { + f(5); + g(); + } + case 6: { + f(6); + g(); + } + default: { + print(9); + } + } +} // EMSCRIPTEN_GENERATED_FUNCTIONS // EXTRA_INFO: { "sizeToOutline": 30, "allowCostlyOutlines": 1 } |