diff options
124 files changed, 5363 insertions, 2697 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 @@ -137,7 +137,7 @@ Options that are modified or new in %s include: opt levels, see apply_opt_level() in tools/shared.py and also src/settings.js.) -O2 As -O1, plus the relooper (loop recreation), - LLVM -O2 optimizations, and + LLVM -O3 optimizations, and -s ALIASING_FUNCTION_POINTERS=1 @@ -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 = {} @@ -1621,9 +1650,6 @@ try: js_optimizer_queue += [get_eliminate(), 'simplifyExpressions'] - if shared.Settings.RELOOP and not shared.Settings.ASM_JS: - js_optimizer_queue += ['optimizeShiftsAggressive', get_eliminate()] # aggressive shifts optimization requires loops, it breaks on switches - if closure and not shared.Settings.ASM_JS: flush_js_optimizer_queue() @@ -1634,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 @@ -1657,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 1b1284c7..c5e235d8 100755 --- a/emscripten.py +++ b/emscripten.py @@ -190,6 +190,11 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, open(forwarded_file, 'w').write(forwarded_data) if DEBUG: print >> sys.stderr, ' emscript: phase 1 took %s seconds' % (time.time() - t) + indexed_functions = set() + forwarded_json = json.loads(forwarded_data) + for key in forwarded_json['Functions']['indexedFunctions'].iterkeys(): + indexed_functions.add(key) + # Phase 2 - func cores = int(os.environ.get('EMCC_CORES') or multiprocessing.cpu_count()) @@ -203,8 +208,6 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, chunk_size = MAX_CHUNK_SIZE # if 1 core, just use the max chunk size if DEBUG: t = time.time() - forwarded_json = json.loads(forwarded_data) - indexed_functions = set() if settings.get('ASM_JS'): settings['EXPORTED_FUNCTIONS'] = forwarded_json['EXPORTED_FUNCTIONS'] save_settings() @@ -549,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/analyzer.js b/src/analyzer.js index 931ce421..2a7d64f5 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -953,9 +953,23 @@ function analyzer(data, sidePass) { if (type[0] == '{' || type[0] == '<') { type = nonPointing; var packed = type[0] == '<'; + var internal = type; + if (packed) { + if (internal[internal.length-1] != '>') { + warnOnce('ignoring type ' + internal); + return; // function pointer or such + } + internal = internal.substr(1, internal.length-2); + } + assert(internal[0] == '{', internal); + if (internal[internal.length-1] != '}') { + warnOnce('ignoring type ' + internal); + return; // function pointer or such + } + internal = internal.substr(2, internal.length-4); Types.types[type] = { name_: type, - fields: splitTokenList(tokenize(type.substr(2 + packed, type.length - 4 - 2*packed)).tokens).map(function(segment) { + fields: splitTokenList(tokenize(internal).tokens).map(function(segment) { return segment[0].text; }), packed: packed, diff --git a/src/compiler.js b/src/compiler.js index 365ff32f..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 @@ -203,6 +202,8 @@ if (phase == 'pre') { } } +if (VERBOSE) printErr('VERBOSE is on, this generates a lot of output and can slow down compilation'); + // Load compiler code load('framework.js'); 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/intertyper.js b/src/intertyper.js index 3fc840c4..31e97bd0 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -365,8 +365,17 @@ function intertyper(data, sidePass, baseLineNums) { } if (tokensLength >= 3 && (token0Text == 'call' || token1Text == 'call')) return 'Call'; - if (token0Text == 'target') + if (token0Text == 'target') { + if (token1Text == 'triple') { + var triple = item.tokens[3].text; + triple = triple.substr(1, triple.length-2); + var expected = TARGET_LE32 ? 'le32-unknown-nacl' : 'i386-pc-linux-gnu'; + if (triple !== expected) { + warn('using an unexpected LLVM triple: ' + [triple, ' !== ', expected] + ' (are you using emcc for everything and not clang?)'); + } + } return '/dev/null'; + } if (token0Text == ';') return '/dev/null'; if (tokensLength >= 3 && token0Text == 'invoke') diff --git a/src/jsifier.js b/src/jsifier.js index c92526d2..179a910a 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -16,6 +16,8 @@ var SETJMP_LABEL = -1; var INDENTATION = ' '; +var functionStubSigs = {}; + // JSifier function JSify(data, functionsOnly, givenFunctions) { var mainPass = !functionsOnly; @@ -278,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)) { @@ -407,6 +409,11 @@ function JSify(data, functionsOnly, givenFunctions) { // functionStub substrate.addActor('FunctionStub', { processItem: function(item) { + // note the signature + if (item.returnType && item.params) { + functionStubSigs[item.ident] = Functions.getSignature(item.returnType.text, item.params.map(function(arg) { return arg.type }), false); + } + function addFromLibrary(ident) { if (ident in addedLibraryItems) return ''; addedLibraryItems[ident] = true; @@ -788,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 @@ -1118,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 @@ -1132,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 = []; } @@ -1537,7 +1563,7 @@ function JSify(data, functionsOnly, givenFunctions) { // This is a call through an invoke_*, either a forced one, or a setjmp-required one // note: no need to update argsTypes at this point if (byPointerForced) Functions.unimplementedFunctions[callIdent] = sig; - args.unshift(byPointerForced ? Functions.getIndex(callIdent, undefined, sig) : asmCoercion(callIdent, 'i32')); + args.unshift(byPointerForced ? Functions.getIndex(callIdent, sig) : asmCoercion(callIdent, 'i32')); callIdent = 'invoke_' + sig; } } else if (SAFE_DYNCALLS) { @@ -1628,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 @@ -1672,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'); + } } } @@ -1724,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'); @@ -1795,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 815badc1..9e78db13 100644 --- a/src/library.js +++ b/src/library.js @@ -100,7 +100,7 @@ LibraryManager.library = { } var entries; try { - entries = FS.readdir(stream); + entries = FS.readdir(stream.path); } catch (e) { return FS.handleFSError(e); } @@ -478,8 +478,6 @@ LibraryManager.library = { open: function(path, oflag, varargs) { // int open(const char *path, int oflag, ...); // http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html - // NOTE: This implementation tries to mimic glibc rather than strictly - // following the POSIX standard. var mode = {{{ makeGetValue('varargs', 0, 'i32') }}}; path = Pointer_stringify(path); try { @@ -7237,7 +7235,7 @@ LibraryManager.library = { socket__deps: ['$FS', '$Sockets'], socket: function(family, type, protocol) { var INCOMING_QUEUE_LENGTH = 64; - var stream = FS.createStream({ + var info = FS.createStream({ addr: null, port: null, inQueue: new CircularBuffer(INCOMING_QUEUE_LENGTH), @@ -7246,7 +7244,7 @@ LibraryManager.library = { socket: true, stream_ops: {} }); - assert(stream.fd < 64); // select() assumes socket fd values are in 0..63 + assert(info.fd < 64); // select() assumes socket fd values are in 0..63 var stream = type == {{{ cDefine('SOCK_STREAM') }}}; if (protocol) { assert(stream == (protocol == {{{ cDefine('IPPROTO_TCP') }}})); // if stream, must be tcp @@ -7359,8 +7357,7 @@ LibraryManager.library = { } }; }; - - return stream.fd; + return info.fd; }, mkport__deps: ['$Sockets'], @@ -7454,6 +7451,7 @@ LibraryManager.library = { buffer.set(data, info.header.byteLength); connection.send('unreliable', buffer.buffer); + return ret; }, recvmsg__deps: ['$FS', '$Sockets', 'bind', '__setErrNo', '$ERRNO_CODES', 'htons'], diff --git a/src/library_browser.js b/src/library_browser.js index f65791e4..591a3c11 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -6,6 +6,7 @@ mergeInto(LibraryManager.library, { $Browser__deps: ['$PATH'], $Browser__postset: 'Module["requestFullScreen"] = function(lockPointer, resizeCanvas) { Browser.requestFullScreen(lockPointer, resizeCanvas) };\n' + // exports 'Module["requestAnimationFrame"] = function(func) { Browser.requestAnimationFrame(func) };\n' + + 'Module["setCanvasSize"] = function(width, height, noUpdates) { Browser.setCanvasSize(width, height, noUpdates) };\n' + 'Module["pauseMainLoop"] = function() { Browser.mainLoop.pause() };\n' + 'Module["resumeMainLoop"] = function() { Browser.mainLoop.resume() };\n' + 'Module["getUserMedia"] = function() { Browser.getUserMedia() }', @@ -451,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 @@ -807,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_egl.js b/src/library_egl.js index 0e96e92f..ff912ed2 100644 --- a/src/library_egl.js +++ b/src/library_egl.js @@ -489,6 +489,11 @@ var LibraryEGL = { eglSwapBuffers: function() { EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); }, + + eglGetProcAddress__deps: ['emscripten_GetProcAddress'], + eglGetProcAddress: function(name_) { + return _emscripten_GetProcAddress(Pointer_stringify(name_)); + }, }; autoAddDeps(LibraryEGL, '$EGL'); diff --git a/src/library_fs.js b/src/library_fs.js index 9c83fcad..e1397356 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -18,7 +18,7 @@ mergeInto(LibraryManager.library, { devices: [null], streams: [null], nextInode: 1, - name_table: new Array(4096), + name_table: null, currentPath: '/', initialized: false, // Whether we are currently ignoring permissions. Useful when preparing the @@ -27,16 +27,21 @@ mergeInto(LibraryManager.library, { // to modify the filesystem freely before run() is called. ignorePermissions: true, - ErrnoError: function(errno) { - this.errno = errno; - for (var key in ERRNO_CODES) { - if (ERRNO_CODES[key] === errno) { - this.code = key; - break; + ErrnoError: (function() { + function ErrnoError(errno) { + this.errno = errno; + for (var key in ERRNO_CODES) { + if (ERRNO_CODES[key] === errno) { + this.code = key; + break; + } } - } - this.message = ERRNO_MESSAGES[errno] + ' : ' + new Error().stack; - }, + this.message = ERRNO_MESSAGES[errno]; + }; + ErrnoError.prototype = new Error(); + ErrnoError.prototype.constructor = ErrnoError; + return ErrnoError; + }()), handleFSError: function(e) { if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + new Error().stack; @@ -51,7 +56,7 @@ mergeInto(LibraryManager.library, { for (var i = 0; i < name.length; i++) { hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0; } - return (parentid + hash) % FS.name_table.length; + return ((parentid + hash) >>> 0) % FS.name_table.length; }, hashAddNode: function(node) { var hash = FS.hashName(node.parent.id, node.name); @@ -504,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); @@ -517,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); } @@ -730,6 +735,9 @@ mergeInto(LibraryManager.library, { }); // use a custom read function stream_ops.read = function(stream, buffer, offset, length, position) { + if (!FS.forceLoadFile(node)) { + throw new FS.ErrnoError(ERRNO_CODES.EIO); + } var contents = stream.node.contents; var size = Math.min(contents.length - position, length); if (contents.slice) { // normal array @@ -758,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 @@ -766,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); @@ -860,6 +868,8 @@ mergeInto(LibraryManager.library, { assert(stderr.fd === 3, 'invalid handle for stderr (' + stderr.fd + ')'); }, staticInit: function() { + FS.name_table = new Array(4096); + FS.root = FS.createNode(null, '/', {{{ cDefine('S_IFDIR') }}} | 0777, 0); FS.mount(MEMFS, {}, '/'); @@ -1035,7 +1045,7 @@ mergeInto(LibraryManager.library, { FS.hashRemoveNode(old_node); // do the underlying fs rename try { - old_node.node_ops.rename(old_node, new_dir, new_name); + old_dir.node_ops.rename(old_node, new_dir, new_name); } catch (e) { throw e; } finally { @@ -1062,6 +1072,14 @@ mergeInto(LibraryManager.library, { parent.node_ops.rmdir(parent, name); FS.destroyNode(node); }, + readdir: function(path) { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + if (!node.node_ops.readdir) { + throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); + } + return node.node_ops.readdir(node); + }, unlink: function(path) { var lookup = FS.lookupPath(path, { parent: true }); var parent = lookup.node; @@ -1202,6 +1220,7 @@ mergeInto(LibraryManager.library, { open: function(path, flags, mode, fd_start, fd_end) { path = PATH.normalize(path); flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags; + mode = typeof mode === 'undefined' ? 0666 : mode; if ((flags & {{{ cDefine('O_CREAT') }}})) { mode = (mode & {{{ cDefine('S_IALLUGO') }}}) | {{{ cDefine('S_IFREG') }}}; } else { @@ -1280,12 +1299,6 @@ mergeInto(LibraryManager.library, { } return stream.stream_ops.llseek(stream, offset, whence); }, - readdir: function(stream) { - if (!stream.stream_ops.readdir) { - throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR); - } - return stream.stream_ops.readdir(stream); - }, read: function(stream, buffer, offset, length, position) { if (length < 0 || position < 0) { throw new FS.ErrnoError(ERRNO_CODES.EINVAL); @@ -1310,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); } @@ -1334,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_gl.js b/src/library_gl.js index 8c724245..c134ad97 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -1285,10 +1285,11 @@ var LibraryGL = { return Module.ctx.isFramebuffer(fb); }, -#if DISABLE_GL_EMULATION == 0 +#if LEGACY_GL_EMULATION // GL emulation: provides misc. functionality not present in OpenGL ES 2.0 or WebGL + $GLEmulation__deps: ['$GLImmediateSetup', 'glEnable', 'glDisable', 'glIsEnabled', 'glGetBooleanv', 'glGetIntegerv', 'glGetString', 'glCreateShader', 'glShaderSource', 'glCompileShader', 'glAttachShader', 'glDetachShader', 'glUseProgram', 'glDeleteProgram', 'glBindAttribLocation', 'glLinkProgram', 'glBindBuffer', 'glGetFloatv', 'glHint', 'glEnableVertexAttribArray', 'glDisableVertexAttribArray', 'glVertexAttribPointer', 'glActiveTexture'], $GLEmulation__postset: 'GLEmulation.init();', $GLEmulation: { // Fog support. Partial, we assume shaders are used that implement fog. We just pass them uniforms @@ -1323,7 +1324,7 @@ var LibraryGL = { GLEmulation.fogColor = new Float32Array(4); // Add some emulation workarounds - Module.printErr('WARNING: using emscripten GL emulation. This is a collection of limited workarounds, do not expect it to work. (If you do not want this, build with -s DISABLE_GL_EMULATION=1)'); + Module.printErr('WARNING: using emscripten GL emulation. This is a collection of limited workarounds, do not expect it to work.'); #if GL_UNSAFE_OPTS == 0 Module.printErr('WARNING: using emscripten GL emulation unsafe opts. If weirdness happens, try -s GL_UNSAFE_OPTS=0'); #endif @@ -1618,17 +1619,15 @@ var LibraryGL = { var glCompileShader = _glCompileShader; _glCompileShader = function(shader) { Module.ctx.compileShader(GL.shaders[shader]); +#if GL_DEBUG if (!Module.ctx.getShaderParameter(GL.shaders[shader], Module.ctx.COMPILE_STATUS)) { Module.printErr('Failed to compile shader: ' + Module.ctx.getShaderInfoLog(GL.shaders[shader])); Module.printErr('Info: ' + JSON.stringify(GL.shaderInfos[shader])); -#if GL_DEBUG Module.printErr('Original source: ' + GL.shaderOriginalSources[shader]); Module.printErr('Source: ' + GL.shaderSources[shader]); throw 'Shader compilation halt'; -#else - Module.printErr('Enable GL_DEBUG to see shader source'); -#endif } +#endif }; GL.programShaders = {}; @@ -1775,170 +1774,6 @@ var LibraryGL = { } return attrib; }, - - getProcAddress: function(name) { - name = name.replace('EXT', '').replace('ARB', ''); - // Do the translation carefully because of closure - var ret = 0; - switch (name) { - case 'glCreateShaderObject': case 'glCreateShader': ret = {{{ Functions.getIndex('_glCreateShader', true) }}}; break; - case 'glCreateProgramObject': case 'glCreateProgram': ret = {{{ Functions.getIndex('_glCreateProgram', true) }}}; break; - case 'glAttachObject': case 'glAttachShader': ret = {{{ Functions.getIndex('_glAttachShader', true) }}}; break; - case 'glUseProgramObject': case 'glUseProgram': ret = {{{ Functions.getIndex('_glUseProgram', true) }}}; break; - case 'glDetachObject': case 'glDetachShader': ret = {{{ Functions.getIndex('_glDetachShader', true) }}}; break; - case 'glDeleteObject': ret = {{{ Functions.getIndex('_glDeleteObject', true) }}}; break; - case 'glGetObjectParameteriv': ret = {{{ Functions.getIndex('_glGetObjectParameteriv', true) }}}; break; - case 'glGetInfoLog': ret = {{{ Functions.getIndex('_glGetInfoLog', true) }}}; break; - case 'glBindProgram': ret = {{{ Functions.getIndex('_glBindProgram', true) }}}; break; - case 'glDrawRangeElements': ret = {{{ Functions.getIndex('_glDrawRangeElements', true) }}}; break; - case 'glShaderSource': ret = {{{ Functions.getIndex('_glShaderSource', true) }}}; break; - case 'glCompileShader': ret = {{{ Functions.getIndex('_glCompileShader', true) }}}; break; - case 'glLinkProgram': ret = {{{ Functions.getIndex('_glLinkProgram', true) }}}; break; - case 'glGetUniformLocation': ret = {{{ Functions.getIndex('_glGetUniformLocation', true) }}}; break; - case 'glUniform1f': ret = {{{ Functions.getIndex('_glUniform1f', true) }}}; break; - case 'glUniform2f': ret = {{{ Functions.getIndex('_glUniform2f', true) }}}; break; - case 'glUniform3f': ret = {{{ Functions.getIndex('_glUniform3f', true) }}}; break; - case 'glUniform4f': ret = {{{ Functions.getIndex('_glUniform4f', true) }}}; break; - case 'glUniform1fv': ret = {{{ Functions.getIndex('_glUniform1fv', true) }}}; break; - case 'glUniform2fv': ret = {{{ Functions.getIndex('_glUniform2fv', true) }}}; break; - case 'glUniform3fv': ret = {{{ Functions.getIndex('_glUniform3fv', true) }}}; break; - case 'glUniform4fv': ret = {{{ Functions.getIndex('_glUniform4fv', true) }}}; break; - case 'glUniform1i': ret = {{{ Functions.getIndex('_glUniform1i', true) }}}; break; - case 'glUniform2i': ret = {{{ Functions.getIndex('_glUniform2i', true) }}}; break; - case 'glUniform3i': ret = {{{ Functions.getIndex('_glUniform3i', true) }}}; break; - case 'glUniform4i': ret = {{{ Functions.getIndex('_glUniform4i', true) }}}; break; - case 'glUniform1iv': ret = {{{ Functions.getIndex('_glUniform1iv', true) }}}; break; - case 'glUniform2iv': ret = {{{ Functions.getIndex('_glUniform2iv', true) }}}; break; - case 'glUniform3iv': ret = {{{ Functions.getIndex('_glUniform3iv', true) }}}; break; - case 'glUniform4iv': ret = {{{ Functions.getIndex('_glUniform4iv', true) }}}; break; - case 'glBindAttribLocation': ret = {{{ Functions.getIndex('_glBindAttribLocation', true) }}}; break; - case 'glGetActiveUniform': ret = {{{ Functions.getIndex('_glGetActiveUniform', true) }}}; break; - case 'glGenBuffers': ret = {{{ Functions.getIndex('_glGenBuffers', true) }}}; break; - case 'glBindBuffer': ret = {{{ Functions.getIndex('_glBindBuffer', true) }}}; break; - case 'glBufferData': ret = {{{ Functions.getIndex('_glBufferData', true) }}}; break; - case 'glBufferSubData': ret = {{{ Functions.getIndex('_glBufferSubData', true) }}}; break; - case 'glDeleteBuffers': ret = {{{ Functions.getIndex('_glDeleteBuffers', true) }}}; break; - case 'glActiveTexture': ret = {{{ Functions.getIndex('_glActiveTexture', true) }}}; break; - case 'glClientActiveTexture': ret = {{{ Functions.getIndex('_glClientActiveTexture', true) }}}; break; - case 'glGetProgramiv': ret = {{{ Functions.getIndex('_glGetProgramiv', true) }}}; break; - case 'glEnableVertexAttribArray': ret = {{{ Functions.getIndex('_glEnableVertexAttribArray', true) }}}; break; - case 'glDisableVertexAttribArray': ret = {{{ Functions.getIndex('_glDisableVertexAttribArray', true) }}}; break; - case 'glVertexAttribPointer': ret = {{{ Functions.getIndex('_glVertexAttribPointer', true) }}}; break; - case 'glVertexAttrib1f': ret = {{{ Functions.getIndex('_glVertexAttrib1f', true) }}}; break; - case 'glVertexAttrib2f': ret = {{{ Functions.getIndex('_glVertexAttrib2f', true) }}}; break; - case 'glVertexAttrib3f': ret = {{{ Functions.getIndex('_glVertexAttrib3f', true) }}}; break; - case 'glVertexAttrib4f': ret = {{{ Functions.getIndex('_glVertexAttrib4f', true) }}}; break; - case 'glVertexAttrib1fv': ret = {{{ Functions.getIndex('_glVertexAttrib1fv', true) }}}; break; - case 'glVertexAttrib2fv': ret = {{{ Functions.getIndex('_glVertexAttrib2fv', true) }}}; break; - case 'glVertexAttrib3fv': ret = {{{ Functions.getIndex('_glVertexAttrib3fv', true) }}}; break; - case 'glVertexAttrib4fv': ret = {{{ Functions.getIndex('_glVertexAttrib4fv', true) }}}; break; - case 'glGetVertexAttribfv': ret = {{{ Functions.getIndex('_glGetVertexAttribfv', true) }}}; break; - case 'glGetVertexAttribiv': ret = {{{ Functions.getIndex('_glGetVertexAttribiv', true) }}}; break; - case 'glGetVertexAttribPointerv': ret = {{{ Functions.getIndex('_glGetVertexAttribPointerv', true) }}}; break; - case 'glGetAttribLocation': ret = {{{ Functions.getIndex('_glGetAttribLocation', true) }}}; break; - case 'glGetActiveAttrib': ret = {{{ Functions.getIndex('_glGetActiveAttrib', true) }}}; break; - case 'glBindRenderbuffer': ret = {{{ Functions.getIndex('_glBindRenderbuffer', true) }}}; break; - case 'glDeleteRenderbuffers': ret = {{{ Functions.getIndex('_glDeleteRenderbuffers', true) }}}; break; - case 'glGenRenderbuffers': ret = {{{ Functions.getIndex('_glGenRenderbuffers', true) }}}; break; - case 'glCompressedTexImage2D': ret = {{{ Functions.getIndex('_glCompressedTexImage2D', true) }}}; break; - case 'glCompressedTexSubImage2D': ret = {{{ Functions.getIndex('_glCompressedTexSubImage2D', true) }}}; break; - case 'glBindFramebuffer': ret = {{{ Functions.getIndex('_glBindFramebuffer', true) }}}; break; - case 'glGenFramebuffers': ret = {{{ Functions.getIndex('_glGenFramebuffers', true) }}}; break; - case 'glDeleteFramebuffers': ret = {{{ Functions.getIndex('_glDeleteFramebuffers', true) }}}; break; - case 'glFramebufferRenderbuffer': ret = {{{ Functions.getIndex('_glFramebufferRenderbuffer', true) }}}; break; - case 'glFramebufferTexture2D': ret = {{{ Functions.getIndex('_glFramebufferTexture2D', true) }}}; break; - case 'glGetFramebufferAttachmentParameteriv': ret = {{{ Functions.getIndex('_glGetFramebufferAttachmentParameteriv', true) }}}; break; - case 'glIsFramebuffer': ret = {{{ Functions.getIndex('_glIsFramebuffer', true) }}}; break; - case 'glCheckFramebufferStatus': ret = {{{ Functions.getIndex('_glCheckFramebufferStatus', true) }}}; break; - case 'glRenderbufferStorage': ret = {{{ Functions.getIndex('_glRenderbufferStorage', true) }}}; break; - case 'glGenVertexArrays': ret = {{{ Functions.getIndex('_glGenVertexArrays', true) }}}; break; - case 'glDeleteVertexArrays': ret = {{{ Functions.getIndex('_glDeleteVertexArrays', true) }}}; break; - case 'glBindVertexArray': ret = {{{ Functions.getIndex('_glBindVertexArray', true) }}}; break; - case 'glGetString': ret = {{{ Functions.getIndex('_glGetString', true) }}}; break; - case 'glBindTexture': ret = {{{ Functions.getIndex('_glBindTexture', true) }}}; break; - case 'glGetBufferParameteriv': ret = {{{ Functions.getIndex('_glGetBufferParameteriv', true) }}}; break; - case 'glIsBuffer': ret = {{{ Functions.getIndex('_glIsBuffer', true) }}}; break; - case 'glDeleteShader': ret = {{{ Functions.getIndex('_glDeleteShader', true) }}}; break; - case 'glUniformMatrix2fv': ret = {{{ Functions.getIndex('_glUniformMatrix2fv', true) }}}; break; - case 'glUniformMatrix3fv': ret = {{{ Functions.getIndex('_glUniformMatrix3fv', true) }}}; break; - case 'glUniformMatrix4fv': ret = {{{ Functions.getIndex('_glUniformMatrix4fv', true) }}}; break; - case 'glIsRenderbuffer': ret = {{{ Functions.getIndex('_glIsRenderbuffer', true) }}}; break; - case 'glBlendEquation': ret = {{{ Functions.getIndex('_glBlendEquation', true) }}}; break; - case 'glBlendFunc': ret = {{{ Functions.getIndex('_glBlendFunc', true) }}}; break; - case 'glBlendFuncSeparate': ret = {{{ Functions.getIndex('_glBlendFuncSeparate', true) }}}; break; - case 'glBlendEquationSeparate': ret = {{{ Functions.getIndex('_glBlendEquationSeparate', true) }}}; break; - case 'glDepthRangef': ret = {{{ Functions.getIndex('_glDepthRangef', true) }}}; break; - case 'glClear': ret = {{{ Functions.getIndex('_glClear', true) }}}; break; - case 'glGenerateMipmap': ret = {{{ Functions.getIndex('_glGenerateMipmap', true) }}}; break; - case 'glBlendColor': ret = {{{ Functions.getIndex('_glBlendColor', true) }}}; break; - case 'glClearDepthf': ret = {{{ Functions.getIndex('_glClearDepthf', true) }}}; break; - case 'glDeleteProgram': ret = {{{ Functions.getIndex('_glDeleteProgram', true) }}}; break; - case 'glUniformMatrix3fv': ret = {{{ Functions.getIndex('_glUniformMatrix3fv', true) }}}; break; - case 'glClearColor': ret = {{{ Functions.getIndex('_glClearColor', true) }}}; break; - case 'glGetRenderbufferParameteriv': ret = {{{ Functions.getIndex('_glGetRenderbufferParameteriv', true) }}}; break; - case 'glGetShaderInfoLog': ret = {{{ Functions.getIndex('_glGetShaderInfoLog', true) }}}; break; - case 'glUniformMatrix4fv': ret = {{{ Functions.getIndex('_glUniformMatrix4fv', true) }}}; break; - case 'glClearStencil': ret = {{{ Functions.getIndex('_glClearStencil', true) }}}; break; - case 'glGetProgramInfoLog': ret = {{{ Functions.getIndex('_glGetProgramInfoLog', true) }}}; break; - case 'glGetUniformfv': ret = {{{ Functions.getIndex('_glGetUniformfv', true) }}}; break; - case 'glStencilFuncSeparate': ret = {{{ Functions.getIndex('_glStencilFuncSeparate', true) }}}; break; - case 'glSampleCoverage': ret = {{{ Functions.getIndex('_glSampleCoverage', true) }}}; break; - case 'glColorMask': ret = {{{ Functions.getIndex('_glColorMask', true) }}}; break; - case 'glGetShaderiv': ret = {{{ Functions.getIndex('_glGetShaderiv', true) }}}; break; - case 'glGetUniformiv': ret = {{{ Functions.getIndex('_glGetUniformiv', true) }}}; break; - case 'glCopyTexSubImage2D': ret = {{{ Functions.getIndex('_glCopyTexSubImage2D', true) }}}; break; - case 'glDetachShader': ret = {{{ Functions.getIndex('_glDetachShader', true) }}}; break; - case 'glGetShaderSource': ret = {{{ Functions.getIndex('_glGetShaderSource', true) }}}; break; - case 'glDeleteTextures': ret = {{{ Functions.getIndex('_glDeleteTextures', true) }}}; break; - case 'glGetAttachedShaders': ret = {{{ Functions.getIndex('_glGetAttachedShaders', true) }}}; break; - case 'glValidateProgram': ret = {{{ Functions.getIndex('_glValidateProgram', true) }}}; break; - case 'glDepthFunc': ret = {{{ Functions.getIndex('_glDepthFunc', true) }}}; break; - case 'glIsShader': ret = {{{ Functions.getIndex('_glIsShader', true) }}}; break; - case 'glDepthMask': ret = {{{ Functions.getIndex('_glDepthMask', true) }}}; break; - case 'glStencilMaskSeparate': ret = {{{ Functions.getIndex('_glStencilMaskSeparate', true) }}}; break; - case 'glIsProgram': ret = {{{ Functions.getIndex('_glIsProgram', true) }}}; break; - case 'glDisable': ret = {{{ Functions.getIndex('_glDisable', true) }}}; break; - case 'glStencilOpSeparate': ret = {{{ Functions.getIndex('_glStencilOpSeparate', true) }}}; break; - case 'glDrawArrays': ret = {{{ Functions.getIndex('_glDrawArrays', true) }}}; break; - case 'glDrawElements': ret = {{{ Functions.getIndex('_glDrawElements', true) }}}; break; - case 'glEnable': ret = {{{ Functions.getIndex('_glEnable', true) }}}; break; - case 'glFinish': ret = {{{ Functions.getIndex('_glFinish', true) }}}; break; - case 'glFlush': ret = {{{ Functions.getIndex('_glFlush', true) }}}; break; - case 'glFrontFace': ret = {{{ Functions.getIndex('_glFrontFace', true) }}}; break; - case 'glCullFace': ret = {{{ Functions.getIndex('_glCullFace', true) }}}; break; - case 'glGenTextures': ret = {{{ Functions.getIndex('_glGenTextures', true) }}}; break; - case 'glGetError': ret = {{{ Functions.getIndex('_glGetError', true) }}}; break; - case 'glGetIntegerv': ret = {{{ Functions.getIndex('_glGetIntegerv', true) }}}; break; - case 'glGetBooleanv': ret = {{{ Functions.getIndex('_glGetBooleanv', true) }}}; break; - case 'glGetFloatv': ret = {{{ Functions.getIndex('_glGetFloatv', true) }}}; break; - case 'glHint': ret = {{{ Functions.getIndex('_glHint', true) }}}; break; - case 'glIsTexture': ret = {{{ Functions.getIndex('_glIsTexture', true) }}}; break; - case 'glPixelStorei': ret = {{{ Functions.getIndex('_glPixelStorei', true) }}}; break; - case 'glReadPixels': ret = {{{ Functions.getIndex('_glReadPixels', true) }}}; break; - case 'glScissor': ret = {{{ Functions.getIndex('_glScissor', true) }}}; break; - case 'glStencilFunc': ret = {{{ Functions.getIndex('_glStencilFunc', true) }}}; break; - case 'glStencilMask': ret = {{{ Functions.getIndex('_glStencilMask', true) }}}; break; - case 'glStencilOp': ret = {{{ Functions.getIndex('_glStencilOp', true) }}}; break; - case 'glTexImage2D': ret = {{{ Functions.getIndex('_glTexImage2D', true) }}}; break; - case 'glTexParameterf': ret = {{{ Functions.getIndex('_glTexParameterf', true) }}}; break; - case 'glTexParameterfv': ret = {{{ Functions.getIndex('_glTexParameterfv', true) }}}; break; - case 'glTexParameteri': ret = {{{ Functions.getIndex('_glTexParameteri', true) }}}; break; - case 'glTexParameteriv': ret = {{{ Functions.getIndex('_glTexParameteriv', true) }}}; break; - case 'glGetTexParameterfv': ret = {{{ Functions.getIndex('_glGetTexParameterfv', true) }}}; break; - case 'glGetTexParameteriv': ret = {{{ Functions.getIndex('_glGetTexParameteriv', true) }}}; break; - case 'glTexSubImage2D': ret = {{{ Functions.getIndex('_glTexSubImage2D', true) }}}; break; - case 'glCopyTexImage2D': ret = {{{ Functions.getIndex('_glCopyTexImage2D', true) }}}; break; - case 'glViewport': ret = {{{ Functions.getIndex('_glViewport', true) }}}; break; - case 'glIsEnabled': ret = {{{ Functions.getIndex('_glIsEnabled', true) }}}; break; - case 'glLineWidth': ret = {{{ Functions.getIndex('_glLineWidth', true) }}}; break; - case 'glPolygonOffset': ret = {{{ Functions.getIndex('_glPolygonOffset', true) }}}; break; - case 'glReleaseShaderCompiler': ret = {{{ Functions.getIndex('_glReleaseShaderCompiler', true) }}}; break; - case 'glGetShaderPrecisionFormat': ret = {{{ Functions.getIndex('_glGetShaderPrecisionFormat', true) }}}; break; - case 'glShaderBinary': ret = {{{ Functions.getIndex('_glShaderBinary', true) }}}; break; - } - if (!ret) Module.printErr('WARNING: getProcAddress failed for ' + name); - return ret; - } }, glGetShaderPrecisionFormat__sig: 'v', @@ -4202,7 +4037,43 @@ var LibraryGL = { glBindVertexArrayOES: 'glBindVertexArray', glFramebufferTexture2DOES: 'glFramebufferTexture2D', -#endif // DISABLE_GL_EMULATION == 0 +#else // LEGACY_GL_EMULATION + + // Warn if code tries to use various emulation stuff, when emulation is disabled + // (do not warn if INCLUDE_FULL_LIBRARY is one, because then likely the gl code will + // not be called anyhow, leave only the runtime aborts) + glVertexPointer__deps: [function() { +#if INCLUDE_FULL_LIBRARY == 0 + warn('Legacy GL function (glVertexPointer) called. You need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation.'); +#endif + }], + glVertexPointer: function(){ throw 'Legacy GL function (glVertexPointer) called. You need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation.'; }, + glGenVertexArrays__deps: [function() { +#if INCLUDE_FULL_LIBRARY == 0 + warn('Legacy GL function (glGenVertexArrays) called. You need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation.'); +#endif + }], + glGenVertexArrays: function(){ throw 'Legacy GL function (glGenVertexArrays) called. You need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation.'; }, + glMatrixMode__deps: [function() { +#if INCLUDE_FULL_LIBRARY == 0 + warn('Legacy GL function (glMatrixMode) called. You need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation.'); +#endif + }], + glMatrixMode: function(){ throw 'Legacy GL function (glMatrixMode) called. You need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation.'; }, + glBegin__deps: [function() { +#if INCLUDE_FULL_LIBRARY == 0 + warn('Legacy GL function (glBegin) called. You need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation.'); +#endif + }], + glBegin: function(){ throw 'Legacy GL function (glBegin) called. You need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation.'; }, + glLoadIdentity__deps: [function() { +#if INCLUDE_FULL_LIBRARY == 0 + warn('Legacy GL function (glLoadIdentity) called. You need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation.'); +#endif + }], + glLoadIdentity: function(){ throw 'Legacy GL function (glLoadIdentity) called. You need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation.'; }, + +#endif // LEGACY_GL_EMULATION // GLU @@ -4438,28 +4309,60 @@ var LibraryGL = { autoAddDeps(LibraryGL, '$GL'); -if (!DISABLE_GL_EMULATION) { - // Emulation requires everything else, potentially - LibraryGL.$GLEmulation__deps = LibraryGL.$GLEmulation__deps.slice(0); // the __deps object is shared - var glFuncs = []; - for (var item in LibraryGL) { - if (item != '$GLEmulation' && item.substr(-6) != '__deps' && item.substr(-9) != '__postset' && item.substr(-5) != '__sig' && item.substr(0, 2) == 'gl') { - glFuncs.push(item); +// Legacy GL emulation +if (LEGACY_GL_EMULATION) { + DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.push('$GLEmulation'); +} + +// GL proc address retrieval +LibraryGL.emscripten_GetProcAddress__deps = [function() { + // ProcAddress is used, so include everything in GL. This runs before we go to the $ProcAddressTable object, + // and we fill its deps just in time, and create the lookup table + var table = {}; + LibraryManager.library.emscripten_procAddressTable__deps = keys(LibraryGL).map(function(x) { + if (x.substr(-6) == '__deps' || x.substr(-9) == '__postset' || x.substr(-5) == '__sig' || x.substr(-5) == '__asm' || x.substr(0, 2) != 'gl') return null; + var original = x; + if (('_' + x) in Functions.implementedFunctions) { + // a user-implemented function aliases this one, but we still want it to be accessible by name, so rename it + var y = x + '__procTable'; + LibraryManager.library[y] = LibraryManager.library[x]; + LibraryManager.library[y + '__deps'] = LibraryManager.library[x + '__deps']; + LibraryManager.library[y + '__postset'] = LibraryManager.library[x + '__postset']; + LibraryManager.library[y + '__sig'] = LibraryManager.library[x + '__sig'];//|| Functions.implementedFunctions['_' + x]; + LibraryManager.library[y + '__asm'] = LibraryManager.library[x + '__asm']; + x = y; + assert(!(y in Functions.implementedFunctions) && !Functions.unimplementedFunctions['_' + y]); } - } - LibraryGL.$GLEmulation__deps = LibraryGL.$GLEmulation__deps.concat(glFuncs); - LibraryGL.$GLEmulation__deps.push(function() { - for (var func in Functions.getIndex.tentative) { - Functions.getIndex(func); - Functions.unimplementedFunctions[func] = LibraryGL[func.substr(1) + '__sig']; + var longX = '_' + x; + var sig = LibraryManager.library[x + '__sig'] || functionStubSigs[longX]; + if (sig) { + table[original] = Functions.getIndex(longX, sig); + if (!(longX in Functions.implementedFunctions)) Functions.unimplementedFunctions[longX] = sig; } - }); - - if (FORCE_GL_EMULATION) { - LibraryGL.glDrawElements__deps = LibraryGL.glDrawElements__deps.concat('$GLEmulation'); - LibraryGL.glDrawArrays__deps = LibraryGL.glDrawArrays__deps.concat('$GLEmulation'); + return x; + }).filter(function(x) { return x !== null }); + // convert table into function with switch, to not confuse closure compiler + var tableImpl = 'switch(name) {\n'; + for (var x in table) tableImpl += 'case "' + x + '": return ' + table[x] + '; break;\n'; + tableImpl += '}\nreturn 0;'; + LibraryManager.library.emscripten_procAddressTable = new Function('name', tableImpl); +}, 'emscripten_procAddressTable']; +LibraryGL.emscripten_GetProcAddress = function(name) { + name = name.replace('EXT', '').replace('ARB', ''); + switch(name) { // misc renamings + case 'glCreateProgramObject': name = 'glCreateProgram'; break; + case 'glUseProgramObject': name = 'glUseProgram'; break; + case 'glCreateShaderObject': name = 'glCreateShader'; break; + case 'glAttachObject': name = 'glAttachShader'; break; + case 'glDetachObject': name = 'glDetachShader'; break; } + var ret = _emscripten_procAddressTable(name); + if (!ret) Module.printErr('WARNING: getProcAddress failed for ' + name); + return ret; } +// Final merge mergeInto(LibraryManager.library, LibraryGL); +assert(!(FULL_ES2 && LEGACY_GL_EMULATION), 'cannot emulate both ES2 and legacy GL'); + 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 a044e0c6..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); }, @@ -10,16 +26,49 @@ mergeInto(LibraryManager.library, { throw new FS.ErrnoError(ERRNO_CODES.EPERM); } var node = FS.createNode(parent, name, mode, dev); - node.node_ops = MEMFS.node_ops; if (FS.isDir(node.mode)) { - node.stream_ops = MEMFS.stream_ops; + node.node_ops = { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr, + lookup: MEMFS.node_ops.lookup, + mknod: MEMFS.node_ops.mknod, + mknod: MEMFS.node_ops.mknod, + rename: MEMFS.node_ops.rename, + unlink: MEMFS.node_ops.unlink, + rmdir: MEMFS.node_ops.rmdir, + readdir: MEMFS.node_ops.readdir, + symlink: MEMFS.node_ops.symlink + }; + node.stream_ops = { + llseek: MEMFS.stream_ops.llseek + }; node.contents = {}; } else if (FS.isFile(node.mode)) { - node.stream_ops = MEMFS.stream_ops; + node.node_ops = { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr + }; + node.stream_ops = { + llseek: MEMFS.stream_ops.llseek, + read: MEMFS.stream_ops.read, + write: MEMFS.stream_ops.write, + allocate: MEMFS.stream_ops.allocate, + mmap: MEMFS.stream_ops.mmap + }; node.contents = []; + node.contentMode = MEMFS.CONTENT_FLEXIBLE; } else if (FS.isLink(node.mode)) { - node.stream_ops = MEMFS.stream_ops; + node.node_ops = { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr, + readlink: MEMFS.node_ops.readlink + }; + node.stream_ops = {}; } else if (FS.isChrdev(node.mode)) { + node.node_ops = { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr + }; node.stream_ops = FS.chrdev_stream_ops; } node.timestamp = Date.now(); @@ -66,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); @@ -106,6 +156,16 @@ mergeInto(LibraryManager.library, { } delete parent.contents[name]; }, + readdir: function(node) { + var entries = ['.', '..'] + for (var key in node.contents) { + if (!node.contents.hasOwnProperty(key)) { + continue; + } + entries.push(key); + } + return entries; + }, symlink: function(parent, newname, oldpath) { var node = MEMFS.create_node(parent, newname, 0777 | {{{ cDefine('S_IFLNK') }}}, 0); node.link = oldpath; @@ -119,24 +179,11 @@ mergeInto(LibraryManager.library, { }, }, stream_ops: { - open: function(stream) { - if (FS.isDir(stream.node.mode)) { - // cache off the directory entries when open'd - var entries = ['.', '..'] - for (var key in stream.node.contents) { - if (!stream.node.contents.hasOwnProperty(key)) { - continue; - } - entries.push(key); - } - stream.entries = entries; - } - }, read: function(stream, buffer, offset, length, position) { 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 @@ -147,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) { @@ -172,10 +236,8 @@ mergeInto(LibraryManager.library, { stream.position = position; return position; }, - readdir: function(stream) { - return stream.entries; - }, 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); @@ -188,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 { @@ -214,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 574fe294..1fb75724 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -258,7 +258,7 @@ var LibrarySDL = { makeSurface: function(width, height, flags, usePageCanvas, source, rmask, gmask, bmask, amask) { flags = flags || 0; - var surf = _malloc(14*Runtime.QUANTUM_SIZE); // SDL_Surface has 14 fields of quantum size + var surf = _malloc(15*Runtime.QUANTUM_SIZE); // SDL_Surface has 15 fields of quantum size var buffer = _malloc(width*height*4); // TODO: only allocate when locked the first time var pixelFormat = _malloc(18*Runtime.QUANTUM_SIZE); flags |= 1; // SDL_HWSURFACE - this tells SDL_MUSTLOCK that this needs to be locked @@ -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; }, @@ -595,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; } @@ -760,6 +782,11 @@ var LibrarySDL = { return depth; // all modes are ok. }, + SDL_AudioDriverName__deps: ['SDL_VideoDriverName'], + SDL_AudioDriverName: function(buf, max_size) { + return _SDL_VideoDriverName(buf, max_size); + }, + SDL_VideoDriverName: function(buf, max_size) { if (SDL.startTime === null) { return 0; //return NULL @@ -2067,9 +2094,9 @@ var LibrarySDL = { console.log('TODO: SDL_GL_SetAttribute'); }, - SDL_GL_GetProcAddress__deps: ['$GLEmulation'], + SDL_GL_GetProcAddress__deps: ['emscripten_GetProcAddress'], SDL_GL_GetProcAddress: function(name_) { - return GLEmulation.getProcAddress(Pointer_stringify(name_)); + return _emscripten_GetProcAddress(Pointer_stringify(name_)); }, SDL_GL_SwapBuffers: function() {}, diff --git a/src/modules.js b/src/modules.js index 13561777..fa6c0983 100644 --- a/src/modules.js +++ b/src/modules.js @@ -275,20 +275,15 @@ var Functions = { }, // Mark a function as needing indexing. Python will coordinate them all - getIndex: function(ident, doNotCreate, sig) { - if (doNotCreate && !(ident in this.indexedFunctions)) { - if (!Functions.getIndex.tentative) Functions.getIndex.tentative = {}; // only used by GL emulation; TODO: generalize when needed - Functions.getIndex.tentative[ident] = 0; - } + getIndex: function(ident, sig) { var ret; if (phase != 'post' && singlePhase) { - if (!doNotCreate) this.indexedFunctions[ident] = 0; // tell python we need this indexized ret = "'{{ FI_" + toNiceIdent(ident) + " }}'"; // something python will replace later + this.indexedFunctions[ident] = 0; } else { if (!singlePhase) return 'NO_INDEX'; // Should not index functions in post ret = this.indexedFunctions[ident]; if (!ret) { - if (doNotCreate) return '0'; ret = this.nextIndex; this.nextIndex += 2; // Need to have indexes be even numbers, see |polymorph| test this.indexedFunctions[ident] = ret; @@ -326,7 +321,7 @@ var Functions = { tables[sig][index] = ident; } var generated = false; - var wrapped = {}; + var wrapped = {}; // whether we wrapped a lib func var maxTable = 0; for (var t in tables) { if (t == 'pre') continue; @@ -349,10 +344,11 @@ var Functions = { if (ASM_JS) { var curr = table[i]; if (curr && curr != '0' && !Functions.implementedFunctions[curr]) { - curr = toNiceIdent(curr); // fix Math.* to Math_* + var short = toNiceIdent(curr); // fix Math.* to Math_* + curr = t + '_' + short; // libfuncs can alias with different sigs, wrap each separately // This is a library function, we can't just put it in the function table, need a wrapper if (!wrapped[curr]) { - var args = '', arg_coercions = '', call = curr + '(', retPre = '', retPost = ''; + var args = '', arg_coercions = '', call = short + '(', retPre = '', retPost = ''; if (t[0] != 'v') { if (t[0] == 'i') { retPre = 'return '; @@ -367,7 +363,7 @@ var Functions = { call += (j > 1 ? ',' : '') + asmCoercion('a' + j, t[j] != 'i' ? 'float' : 'i32'); } call += ')'; - if (curr == '_setjmp') printErr('WARNING: setjmp used via a function pointer. If this is for libc setjmp (not something of your own with the same name), it will break things'); + if (short == '_setjmp') printErr('WARNING: setjmp used via a function pointer. If this is for libc setjmp (not something of your own with the same name), it will break things'); tables.pre += 'function ' + curr + '__wrapper(' + args + ') { ' + arg_coercions + ' ; ' + retPre + call + retPost + ' }\n'; wrapped[curr] = 1; } diff --git a/src/parseTools.js b/src/parseTools.js index f11c867a..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) { @@ -1244,7 +1266,7 @@ function indexizeFunctions(value, type) { if (!sig) { sig = Functions.unimplementedFunctions[value] = Functions.getSignature(out.returnType, out.segments ? out.segments.map(function(segment) { return segment[0].text }) : [], isVarArgsFunctionType(type)); } - return Functions.getIndex(value, undefined, sig); + return Functions.getIndex(value, sig); } return value; } diff --git a/src/postamble.js b/src/postamble.js index c4ca3aae..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; @@ -127,6 +135,7 @@ Module['exit'] = Module.exit = exit; function abort(text) { if (text) { Module.print(text); + Module.printErr(text); } ABORT = true; 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 3ecac040..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 @@ -191,9 +206,8 @@ var GL_TESTING = 0; // When enabled, sets preserveDrawingBuffer in the context, var GL_MAX_TEMP_BUFFER_SIZE = 2097152; // How large GL emulation temp buffers are var GL_UNSAFE_OPTS = 1; // Enables some potentially-unsafe optimizations in GL emulation code var FULL_ES2 = 0; // Forces support for all GLES2 features, not just the WebGL-friendly subset. -var FORCE_GL_EMULATION = 0; // Forces inclusion of full GL emulation code. -var DISABLE_GL_EMULATION = 0; // Disable inclusion of full GL emulation code. Useful when you don't want emulation - // but do need INCLUDE_FULL_LIBRARY or MAIN_MODULE. +var LEGACY_GL_EMULATION = 0; // Includes code to emulate various desktop GL features. Incomplete but useful + // in some cases, see https://github.com/kripken/emscripten/wiki/OpenGL-support var STB_IMAGE = 0; // Enables building of stb-image, a tiny public-domain library for decoding images, allowing // decoding of images without using the browser's built-in decoders. The benefit is that this @@ -316,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. @@ -380,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/src/shell.js b/src/shell.js index bac4eaa3..f91aa96a 100644 --- a/src/shell.js +++ b/src/shell.js @@ -74,7 +74,12 @@ else if (ENVIRONMENT_IS_SHELL) { Module['print'] = print; if (typeof printErr != 'undefined') Module['printErr'] = printErr; // not present in v8 or older sm - Module['read'] = read; + if (typeof read != 'undefined') { + Module['read'] = read; + } else { + Module['read'] = function() { throw 'no read() available (jsc?)' }; + } + Module['readBinary'] = function(f) { return read(f, 'binary'); }; diff --git a/system/include/compat/math.h b/system/include/compat/math.h new file mode 100644 index 00000000..089cf66b --- /dev/null +++ b/system/include/compat/math.h @@ -0,0 +1,14 @@ +#ifndef _COMPAT_MATH_H_ +#define _COMPAT_MATH_H_ + +#ifndef isinff + #define isinff isinf +#endif + +#ifndef isnanf + #define isnanf isnan +#endif + +#include_next <math.h> + +#endif /* _COMPAT_MATH_H_ */ diff --git a/system/include/compat/stdlib.h b/system/include/compat/stdlib.h new file mode 100644 index 00000000..dc01947d --- /dev/null +++ b/system/include/compat/stdlib.h @@ -0,0 +1,16 @@ +#ifndef _COMPAT_STDLIB_H +#define _COMPAT_STDLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +int getloadavg(double loadavg[], int nelem); + +#ifdef __cplusplus +} +#endif + +#include_next <stdlib.h> + +#endif diff --git a/system/include/compat/string.h b/system/include/compat/string.h new file mode 100644 index 00000000..880089cc --- /dev/null +++ b/system/include/compat/string.h @@ -0,0 +1,17 @@ +#ifndef _COMPAT_STRING_H +#define _COMPAT_STRING_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern char* strlwr(char *); +extern char* strupr(char *); + +#ifdef __cplusplus +} +#endif + +#include_next <string.h> + +#endif diff --git a/system/include/compat/sys/stat.h b/system/include/compat/sys/stat.h new file mode 100644 index 00000000..731502ea --- /dev/null +++ b/system/include/compat/sys/stat.h @@ -0,0 +1,20 @@ +#ifndef _COMPAT_STAT_H +#define _COMPAT_STAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include_next <sys/stat.h> + +#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO) +#define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO) +#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH) +#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH) +#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/system/include/libc/sys/timeb.h b/system/include/compat/sys/timeb.h index 0a2c3de8..0a2c3de8 100644 --- a/system/include/libc/sys/timeb.h +++ b/system/include/compat/sys/timeb.h diff --git a/system/include/compat/unistd.h b/system/include/compat/unistd.h new file mode 100644 index 00000000..07c3afde --- /dev/null +++ b/system/include/compat/unistd.h @@ -0,0 +1,16 @@ +#ifndef _COMPAT_UNISTD_H +#define _COMPAT_UNISTD_H + +#ifdef __cplusplus +extern "C" { +#endif + +char * getwd(char *__buf ); + +#ifdef __cplusplus +} +#endif + +#include_next <unistd.h> + +#endif diff --git a/system/include/compat/xlocale.h b/system/include/compat/xlocale.h new file mode 100644 index 00000000..4bafa27d --- /dev/null +++ b/system/include/compat/xlocale.h @@ -0,0 +1,21 @@ +#ifndef _COMPAT_XLOCALE_H_ +#define _COMPAT_XLOCALE_H_ + +#include <locale.h> + +#ifdef __cplusplus +extern "C" { +#endif + +long long strtoll_l(const char *start, char **end, int base, locale_t loc); +unsigned long long strtoull_l(const char *start, char **end, int base, locale_t loc); +double strtold_l(const char *start, char **end, locale_t loc); + +#ifdef __cplusplus +} +#endif + +#include_next <xlocale.h> + +#endif /* _COMPAT_XLOCALE_H_ */ + diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h index 28e6063c..1b9a8f25 100644 --- a/system/include/emscripten/emscripten.h +++ b/system/include/emscripten/emscripten.h @@ -19,15 +19,24 @@ extern "C" { #endif /* - * Forces LLVM to not dead-code-eliminate a function. Note that - * closure may still eliminate it at the JS level, for which you - * should use EXPORTED_FUNCTIONS (see settings.js). + * Convenient syntax for inline assembly/js. Allows stuff like + * + * EM_ASM(window.alert('hai')); * - * **DEPRECATED**: Use EXPORTED_FUNCTIONS instead, which will work - * with closure, asm.js, etc. For example - * -s EXPORTED_FUNCTIONS=["_main", "myfunc"] + * Note: double-quotes (") are not supported, but you can use + * single-quotes (') in js anyhow. */ -/* #define EMSCRIPTEN_KEEPALIVE __attribute__((used)) */ +#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. + * emcc -s EXPORTED_FUNCTIONS=["_main", "_myfunc"] + * and in the source file + * void EMSCRIPTEN_KEEPALIVE myfunc() {..} + */ +#define EMSCRIPTEN_KEEPALIVE __attribute__((used)) /* * Interface to the underlying JS engine. This function will @@ -161,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/system/include/libc/stdlib.h b/system/include/libc/stdlib.h index 888b6041..6fdef40b 100644 --- a/system/include/libc/stdlib.h +++ b/system/include/libc/stdlib.h @@ -223,8 +223,6 @@ extern long double strtold (const char *, char **); extern long double wcstold (const wchar_t *, wchar_t **); #endif /* _LDBL_EQ_DBL */ -int getloadavg(double loadavg[], int nelem); /* XXX Emscripten */ - _END_STD_C #endif /* _STDLIB_H_ */ diff --git a/system/include/libc/string.h b/system/include/libc/string.h index 515c71a7..8fd9ea43 100644 --- a/system/include/libc/string.h +++ b/system/include/libc/string.h @@ -72,8 +72,6 @@ size_t _EXFUN(strlcpy,(char *, const char *, size_t)); int _EXFUN(strncasecmp,(const char *, const char *, size_t)); size_t _EXFUN(strnlen,(const char *, size_t)); char *_EXFUN(strsep,(char **, const char *)); -char *_EXFUN(strlwr,(char *)); -char *_EXFUN(strupr,(char *)); #if defined(__CYGWIN__) || defined(EMSCRIPTEN) #ifndef DEFS_H /* Kludge to work around problem compiling in gdb */ char *_EXFUN(strsignal, (int __signo)); diff --git a/system/include/libc/sys/unistd.h b/system/include/libc/sys/unistd.h index 1a414b3c..a4219d4d 100644 --- a/system/include/libc/sys/unistd.h +++ b/system/include/libc/sys/unistd.h @@ -102,7 +102,6 @@ uid_t _EXFUN(getuid, (void )); #endif #if defined(EMSCRIPTEN) || defined(__CYGWIN__) char * _EXFUN(getusershell, (void)); -char * _EXFUN(getwd, (char *__buf )); int _EXFUN(iruserok, (unsigned long raddr, int superuser, const char *ruser, const char *luser)); #endif int _EXFUN(isatty, (int __fildes )); diff --git a/system/include/xlocale.h b/system/include/xlocale.h index bb3b50e5..6867d25f 100644 --- a/system/include/xlocale.h +++ b/system/include/xlocale.h @@ -1,4 +1,3 @@ - #ifndef _XLOCALE_H_ #define _XLOCALE_H_ @@ -9,10 +8,6 @@ extern "C" { #endif -long long strtoll_l(const char *start, char **end, int base, locale_t loc); -unsigned long long strtoull_l(const char *start, char **end, int base, locale_t loc); -double strtold_l(const char *start, char **end, locale_t loc); - int strcoll_l(const char *s1, const char *s2, locale_t locale); int wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t locale); @@ -43,5 +38,5 @@ size_t strftime_l(char *s, size_t maxsize, const char *format, const struct tm * } #endif -#endif /* _LOCALE_H_ */ +#endif /* _XLOCALE_H_ */ diff --git a/tests/aniso.c b/tests/aniso.c index 1126265e..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> @@ -161,7 +162,7 @@ int main(int argc, char *argv[]) for (int x = 0; x < n; x++) { int start = x*w*2; glBegin( GL_TRIANGLES ); - glTexCoord2i( 1, 0 ); glVertex3f( start , 0, 0 ); + glTexCoord2i( 1, 0 ); glVertex2i( start , 0 ); glTexCoord2i( 0, 0 ); glVertex3f( start+w, 300, 0 ); glTexCoord2i( 1, 1 ); glVertex3f( start-w, 300, 0 ); glEnd(); @@ -209,5 +210,11 @@ int main(int argc, char *argv[]) SDL_Quit(); - return 0; + // check for asm compilation bug with aliased functions with different sigs + void (*f)(int, int) = glVertex2i; + if ((int)f % 16 == 4) f(5, 7); + void (*g)(int, int) = glVertex3f; + if ((int)g % 16 == 4) g(5, 7); + return (int)f + (int)g; } + diff --git a/tests/cases/phi24_ta2.ll b/tests/cases/phi24_ta2.ll index 4894d5e6..2d9b6646 100644 --- a/tests/cases/phi24_ta2.ll +++ b/tests/cases/phi24_ta2.ll @@ -252,6 +252,7 @@ target triple = "i386-pc-linux-gnu" @g_287 = internal constant i32 -1, align 4 define i32 @main(i32 %argc, i8** nocapture %argv) nounwind { + %msgdummy = alloca { i8*, { i64, i8* } (i8*)* } ; test for parsing of this kind of stuff, compilation-only test %p_6.i.i = alloca %union.U3, align 8 %1 = icmp eq i32 %argc, 2 br i1 %1, label %2, label %7 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/runner.py b/tests/runner.py index 41fd5b90..bbbc23e5 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -48,6 +48,9 @@ class RunnerCore(unittest.TestCase): env = {} + def skipme(self): # used by tests we ask on the commandline to be skipped, see right before call to unittest.main + return self.skip('requested to be skipped') + def setUp(self): Settings.reset() self.banned_js_engines = [] @@ -272,6 +275,18 @@ process(sys.argv[1]) print "Output: " + output[0] return output[0] + # Tests that the given two paths are identical, modulo path delimiters. E.g. "C:/foo" is equal to "C:\foo". + def assertPathsIdentical(self, path1, path2): + path1 = path1.replace('\\', '/') + path2 = path2.replace('\\', '/') + return self.assertIdentical(path1, path2) + + # Tests that the given two multiline text content are identical, modulo line ending differences (\r\n on Windows, \n on Unix). + def assertTextDataIdentical(self, text1, text2): + text1 = text1.replace('\r\n', '\n') + text2 = text2.replace('\r\n', '\n') + return self.assertIdentical(text1, text2) + def assertIdentical(self, values, y): if type(values) not in [list, tuple]: values = [values] for x in values: @@ -477,7 +492,7 @@ def server_func(dir, q): if 'report_' in s.path: q.put(s.path) else: - filename = s.path[1:] + filename = s.path.split('?')[0][1:] if os.path.exists(filename): s.send_response(200) s.send_header("Content-type", "text/html") @@ -646,6 +661,7 @@ class BrowserCore(RunnerCore): self.reftest(path_from_root('tests', reference)) args = args + ['--pre-js', 'reftest.js', '-s', 'GL_TESTING=1'] Popen([PYTHON, EMCC, temp_filepath, '-o', outfile] + args).communicate() + assert os.path.exists(outfile) if type(expected) is str: expected = [expected] self.run_browser(outfile, message, ['/report_result?' + e for e in expected]) @@ -660,9 +676,55 @@ if __name__ == '__main__': elif len(JS_ENGINES) < total_engines: print 'WARNING: Not all the JS engines in JS_ENGINES appears to work, ignoring those.' + # Create a list of modules to load tests from + modules = [] + for filename in glob.glob(os.path.join(os.path.dirname(__file__), 'test*.py')): + module_dir, module_file = os.path.split(filename) + module_name, module_ext = os.path.splitext(module_file) + __import__(module_name) + modules.append(sys.modules[module_name]) + + # Extract the JS engine override from the arguments (used by benchmarks) + for i in range(1, len(sys.argv)): + arg = sys.argv[i] + if arg.isupper(): + print 'Interpreting all capital argument "%s" as JS_ENGINE override' % arg + Building.JS_ENGINE_OVERRIDE = eval(arg) + sys.argv[i] = None + sys.argv = filter(lambda arg: arg is not None, sys.argv) + # If an argument comes in as test_*, treat it as a test of the default suite sys.argv = map(lambda arg: arg if not arg.startswith('test_') else 'default.' + arg, sys.argv) + # If a test (e.g. test_html) is specified as ALL.test_html, add an entry for each test_mode + if len(sys.argv) == 2 and sys.argv[1].startswith('ALL.'): + ignore, test = sys.argv[1].split('.') + print 'Running all test modes on test "%s"' % test + sys.argv = [sys.argv[0]] + map(lambda mode: mode+'.'+test, test_modes) + + # Skip requested tests + for i in range(len(sys.argv)): + arg = sys.argv[i] + if arg.startswith('skip:'): + which = arg.split('skip:')[1] + if which.startswith('ALL.'): + ignore, test = which.split('.') + which = map(lambda mode: mode+'.'+test, test_modes) + else: + which = [which] + + print >> sys.stderr, ','.join(which) + for test in which: + print >> sys.stderr, 'will skip "%s"' % test + for m in modules: + try: + exec('m.' + test + ' = RunnerCore("skipme")') + break + except: + pass + sys.argv[i] = None + sys.argv = filter(lambda arg: arg is not None, sys.argv) + # If no tests were specified, run the core suite if len(sys.argv) == 1: sys.argv = [sys.argv[0]] + map(lambda mode: mode, test_modes) @@ -670,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 @@ -706,55 +769,6 @@ an individual test with ''' time.sleep(2) - # If a test (e.g. test_html) is specified as ALL.test_html, add an entry for each test_mode - if len(sys.argv) == 2 and sys.argv[1].startswith('ALL.'): - ignore, test = sys.argv[1].split('.') - print 'Running all test modes on test "%s"' % test - sys.argv = [sys.argv[0]] + map(lambda mode: mode+'.'+test, test_modes) - - # Extract the JS engine override from the arguments (used by benchmarks) - for i in range(1, len(sys.argv)): - arg = sys.argv[i] - if arg.isupper(): - print 'Interpreting all capital argument "%s" as JS_ENGINE override' % arg - Building.JS_ENGINE_OVERRIDE = eval(arg) - sys.argv[i] = None - sys.argv = filter(lambda arg: arg is not None, sys.argv) - - # Create a list of modules to load tests from - modules = [] - for filename in glob.glob(os.path.join(os.path.dirname(__file__), 'test*.py')): - module_dir, module_file = os.path.split(filename) - module_name, module_ext = os.path.splitext(module_file) - __import__(module_name) - modules.append(sys.modules[module_name]) - - # Skip requested tests - def skipme(self): - return self.skip('requested to be skipped') - - for i in range(len(sys.argv)): - arg = sys.argv[i] - if arg.startswith('skip:'): - which = arg.split('skip:')[1] - if which.startswith('ALL.'): - ignore, test = which.split('.') - which = map(lambda mode: mode+'.'+test, test_modes) - else: - which = [which] - - print >> sys.stderr, ','.join(which) - for test in which: - print >> sys.stderr, 'will skip "%s"' % test - for m in modules: - try: - exec('m.' + test + ' = skipme') - break - except: - pass - sys.argv[i] = None - sys.argv = filter(lambda arg: arg is not None, sys.argv) - # Filter and load tests from the discovered modules loader = unittest.TestLoader() names = sys.argv[1:] @@ -765,10 +779,17 @@ an individual test with except: pass + numFailures = 0 # Keep count of the total number of failing tests. + # Run the discovered tests if not len(suites): print >> sys.stderr, 'No tests found for %s' % str(sys.argv[1:]) + numFailures = 1 else: testRunner = unittest.TextTestRunner(verbosity=2) for suite in suites: - testRunner.run(suite) + results = testRunner.run(suite) + numFailures += len(results.errors) + len(results.failures) + + # Return the number of failures as the process exit code for automating success/failure reporting. + exit(numFailures) 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_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_ogl_proc_alias.c b/tests/sdl_ogl_proc_alias.c new file mode 100644 index 00000000..c96da81b --- /dev/null +++ b/tests/sdl_ogl_proc_alias.c @@ -0,0 +1,180 @@ +/******************************************************************* + * * + * Using SDL With OpenGL * + * * + * Tutorial by Kyle Foley (sdw) * + * * + * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL * + * * + *******************************************************************/ + +/* +THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION +AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN. + +THE ORIGINAL AUTHOR IS KYLE FOLEY. + +THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY +OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF +MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, +ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE +RESULTING FROM THE USE, MODIFICATION, OR +REDISTRIBUTION OF THIS SOFTWARE. +*/ + +#include "SDL/SDL.h" +#include "SDL/SDL_image.h" +#include "SDL/SDL_opengl.h" + +#include <stdio.h> +#include <string.h> + +void (*true_glGenTextures)(GLsizei, GLuint*) = NULL; + +void glGenTextures(GLsizei n, GLuint *textures) { + printf("num? %d\n", n); + true_glGenTextures(n + 1, textures); // correct the error, ensures we are gone through +} + +int main(int argc, char *argv[]) +{ + SDL_Surface *screen; + + // Slightly different SDL initialization + if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) { + printf("Unable to initialize SDL: %s\n", SDL_GetError()); + return 1; + } + + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new* + + screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed* + if ( !screen ) { + printf("Unable to set video mode: %s\n", SDL_GetError()); + return 1; + } + + // Set the OpenGL state after creating the context with SDL_SetVideoMode + + glClearColor( 0, 0, 0, 0 ); + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. + + glViewport( 0, 0, 640, 480 ); + + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); // just for testing + glLoadIdentity(); + + glOrtho( 0, 640, 480, 0, -1, 1 ); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + + // Load the OpenGL texture + + GLuint texture; // Texture object handle + SDL_Surface *surface; // Gives us the information to make the texture + + if ( (surface = IMG_Load("screenshot.png")) ) { + + // Check that the image's width is a power of 2 + if ( (surface->w & (surface->w - 1)) != 0 ) { + printf("warning: image.bmp's width is not a power of 2\n"); + } + + // Also check if the height is a power of 2 + if ( (surface->h & (surface->h - 1)) != 0 ) { + printf("warning: image.bmp's height is not a power of 2\n"); + } + + true_glGenTextures = SDL_GL_GetProcAddress("glGenTextures"); + + // Have OpenGL generate a texture object handle for us + glGenTextures( 0, &texture ); + + // Bind the texture object + glBindTexture( GL_TEXTURE_2D, texture ); + + // Set the texture's stretching properties + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + //SDL_LockSurface(surface); + + // Add some greyness + memset(surface->pixels, 0x66, surface->w*surface->h); + + // Edit the texture object's image data using the information SDL_Surface gives us + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); + + //SDL_UnlockSurface(surface); + } + else { + printf("SDL could not load image.bmp: %s\n", SDL_GetError()); + SDL_Quit(); + return 1; + } + + // Free the SDL_Surface only if it was successfully created + if ( surface ) { + SDL_FreeSurface( surface ); + } + + // Clear the screen before drawing + glClear( GL_COLOR_BUFFER_BIT ); + + // Bind the texture to which subsequent calls refer to + glBindTexture( GL_TEXTURE_2D, texture ); + + glBegin( GL_QUADS ); + glTexCoord2i( 0, 0 ); glVertex3f( 10, 10, 0 ); + glTexCoord2i( 1, 0 ); glVertex3f( 300, 10, 0 ); + glTexCoord2i( 1, 1 ); glVertex3f( 300, 128, 0 ); + glTexCoord2i( 0, 1 ); glVertex3f( 10, 128, 0 ); + + glTexCoord2f( 0, 0.5 ); glVertex3f( 410, 10, 0 ); + glTexCoord2f( 1, 0.5 ); glVertex3f( 600, 10, 0 ); + glTexCoord2f( 1, 1 ); glVertex3f( 630, 200, 0 ); + glTexCoord2f( 0.5, 1 ); glVertex3f( 310, 250, 0 ); + glEnd(); + + glBegin( GL_TRIANGLE_STRIP ); + glTexCoord2i( 0, 0 ); glVertex3f( 100, 300, 0 ); + glTexCoord2i( 1, 0 ); glVertex3f( 300, 300, 0 ); + glTexCoord2i( 1, 1 ); glVertex3f( 300, 400, 0 ); + glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 0 ); + glEnd(); + + glDisable(GL_TEXTURE_2D); + + glColor3ub(90, 255, 255); + glBegin( GL_QUADS ); + glVertex3f( 10, 410, 0 ); + glVertex3f( 300, 410, 0 ); + glVertex3f( 300, 480, 0 ); + glVertex3f( 10, 470, 0 ); + glEnd(); + + glBegin( GL_QUADS ); + glColor3f(1.0, 0, 1.0); glVertex3f( 410, 410, 0 ); + glColor3f(0, 1.0, 0); glVertex3f( 600, 410, 0 ); + glColor3f(0, 0, 1.0); glVertex3f( 600, 480, 0 ); + glColor3f(1.0, 1.0, 1.0); glVertex3f( 410, 470, 0 ); + glEnd(); + + SDL_GL_SwapBuffers(); + +#if !EMSCRIPTEN + // Wait for 3 seconds to give us a chance to see the image + SDL_Delay(3000); +#endif + + // Now we can delete the OpenGL texture and close down SDL + glDeleteTextures( 1, &texture ); + + SDL_Quit(); + + return 0; +} diff --git a/tests/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 8a48b878..f01004c3 100644 --- a/tests/sockets/test_sockets_echo_server.c +++ b/tests/sockets/test_sockets_echo_server.c @@ -37,6 +37,11 @@ typedef struct { server_t server; client_t client; +void cleanup() { + if (server.fd) close(server.fd); + if (client.fd) close(client.fd); +} + void main_loop(void *arg) { int res; fd_set fdr; @@ -105,6 +110,9 @@ int main() { struct sockaddr_in addr; int res; + atexit(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 57fae84b..44ad40a3 100644 --- a/tests/sockets/test_sockets_partial_server.c +++ b/tests/sockets/test_sockets_partial_server.c @@ -14,18 +14,13 @@ #include <emscripten.h> #endif -int serverfd = -1; -int clientfd = -1; - -// csock.send("\x09\x01\x02\x03\x04\x05\x06\x07\x08\x09") -// csock.send("\x08\x01\x02\x03\x04\x05\x06\x07\x08") -// csock.send("\x07\x01\x02\x03\x04\x05\x06\x07") -// csock.send("\x06\x01\x02\x03\x04\x05\x06") -// csock.send("\x05\x01\x02\x03\x04\x05") -// csock.send("\x04\x01\x02\x03\x04") -// csock.send("\x03\x01\x02\x03") -// csock.send("\x02\x01\x02") -// csock.send("\x01\x01") +int serverfd = 0; +int clientfd = 0; + +void cleanup() { + if (serverfd) close(serverfd); + if (clientfd) close(clientfd); +} void do_send(int sockfd) { static char* buffers[] = { @@ -43,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); @@ -69,7 +63,7 @@ void iter(void *arg) { FD_ZERO(&fdr); FD_ZERO(&fdw); FD_SET(serverfd, &fdr); - if (clientfd != -1) FD_SET(clientfd, &fdw); + if (clientfd) FD_SET(clientfd, &fdw); res = select(64, &fdr, &fdw, NULL, NULL); if (res == -1) { perror("select failed"); @@ -91,6 +85,9 @@ int main() { struct sockaddr_in addr; int res; + atexit(cleanup); + //signal(SIGTERM, cleanup); + // create the socket serverfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (serverfd == -1) { 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/sockets/webrtc_host.c b/tests/sockets/webrtc_host.c new file mode 100644 index 00000000..770e59e0 --- /dev/null +++ b/tests/sockets/webrtc_host.c @@ -0,0 +1,89 @@ +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <assert.h> +#if EMSCRIPTEN +#include <emscripten.h> +#endif + +#define EXPECTED_BYTES 5 +#define BUFLEN 16 + +int result = 0; +int sock; +char buf[BUFLEN]; +char expected[] = "emscripten"; +struct sockaddr_in si_host, + si_peer; +struct iovec iov[1]; +struct msghdr hdr; +int done = 0; + +void iter(void* arg) { + int n; + n = recvmsg(sock, &hdr, 0); + + if(0 < n) { + done = 1; + fprintf(stderr, "received %d bytes: %s", n, (char*)hdr.msg_iov[0].iov_base); + + shutdown(sock, SHUT_RDWR); + close(sock); + +#if EMSCRIPTEN + int result = 1; + REPORT_RESULT(); + exit(EXIT_SUCCESS); + emscripten_cancel_main_loop(); +#endif + } else if(EWOULDBLOCK != errno) { + perror("recvmsg failed"); + exit(EXIT_FAILURE); + emscripten_cancel_main_loop(); + } +} + +int main(void) +{ + memset(&si_host, 0, sizeof(struct sockaddr_in)); + memset(&si_peer, 0, sizeof(struct sockaddr_in)); + + si_host.sin_family = AF_INET; + si_host.sin_port = htons(8991); + si_host.sin_addr.s_addr = htonl(INADDR_ANY); + + if(-1 == (sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP))) { + perror("cannot create host socket"); + exit(EXIT_FAILURE); + } + + if(-1 == bind(sock, (struct sockaddr*)&si_host, sizeof(struct sockaddr))) { + perror("cannot bind host socket"); + exit(EXIT_FAILURE); + } + + iov[0].iov_base = buf; + iov[0].iov_len = sizeof(buf); + + memset (&hdr, 0, sizeof (struct msghdr)); + + hdr.msg_name = &si_peer; + hdr.msg_namelen = sizeof(struct sockaddr_in); + hdr.msg_iov = iov; + hdr.msg_iovlen = 1; + +#if EMSCRIPTEN + emscripten_set_main_loop(iter, 0, 0); +#else + while (!done) iter(NULL); +#endif + + return EXIT_SUCCESS; +}
\ No newline at end of file diff --git a/tests/sockets/webrtc_peer.c b/tests/sockets/webrtc_peer.c new file mode 100644 index 00000000..d24979e7 --- /dev/null +++ b/tests/sockets/webrtc_peer.c @@ -0,0 +1,81 @@ +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <assert.h> +#if EMSCRIPTEN +#include <emscripten.h> +#endif + +#define EXPECTED_BYTES 5 +#define BUFLEN 16 +#define HOST_ADDR "10.0.0.1" + +int result = 0; +int sock; +char buf[16] = "emscripten"; +struct sockaddr_in si_host; +struct iovec iov[1]; +struct msghdr hdr; +int done = 0; + +void iter(void* arg) { + int n; + n = sendmsg(sock, &hdr, 0); + + if(0 < n) { + done = 1; + fprintf(stderr, "sent %d bytes: %s", n, (char*)hdr.msg_iov[0].iov_base); + + shutdown(sock, SHUT_RDWR); + close(sock); + + exit(EXIT_SUCCESS); + emscripten_cancel_main_loop(); + } else if(EWOULDBLOCK != errno) { + perror("sendmsg failed"); + exit(EXIT_FAILURE); + emscripten_cancel_main_loop(); + } +} + +int main(void) +{ + memset(&si_host, 0, sizeof(struct sockaddr_in)); + + si_host.sin_family = AF_INET; + si_host.sin_port = htons(8991); + if(0 == inet_pton(AF_INET, HOST_ADDR, &si_host.sin_addr)) { + perror("inet_aton failed"); + exit(EXIT_FAILURE); + } + + if(-1 == (sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP))) { + perror("cannot create socket"); + exit(EXIT_FAILURE); + } + + iov[0].iov_base = buf; + iov[0].iov_len = sizeof(buf); + + memset (&hdr, 0, sizeof (struct msghdr)); + + hdr.msg_name = &si_host; + hdr.msg_namelen = sizeof(struct sockaddr_in); + hdr.msg_iov = iov; + hdr.msg_iovlen = 1; + +#if EMSCRIPTEN + emscripten_set_main_loop(iter, 0, 0); +#else + while (!done) iter(NULL); +#endif + + return EXIT_SUCCESS; +}
\ No newline at end of file diff --git a/tests/test_browser.py b/tests/test_browser.py index e424aae9..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') @@ -620,7 +624,7 @@ Press any key to continue.''' def test_sdl_canvas(self): open(os.path.join(self.get_dir(), 'sdl_canvas.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_canvas.c')).read())) - Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_canvas.c'), '-o', 'page.html']).communicate() + Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_canvas.c'), '-o', 'page.html', '-s', 'LEGACY_GL_EMULATION=1']).communicate() self.run_browser('page.html', '', '/report_result?1') def test_sdl_key(self): @@ -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(''' @@ -843,50 +850,55 @@ Press any key to continue.''' def test_sdl_ogl(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_ogl.c', reference='screenshot-gray-purple.png', reference_slack=1, - args=['-O2', '--minify', '0', '--preload-file', 'screenshot.png'], + args=['-O2', '--minify', '0', '--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1'], message='You should see an image with gray at the top.') def test_sdl_ogl_defaultmatrixmode(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_ogl_defaultMatrixMode.c', reference='screenshot-gray-purple.png', reference_slack=1, - args=['--minify', '0', '--preload-file', 'screenshot.png'], + args=['--minify', '0', '--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1'], message='You should see an image with gray at the top.') def test_sdl_ogl_p(self): # Immediate mode with pointers shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_ogl_p.c', reference='screenshot-gray.png', reference_slack=1, - args=['--preload-file', 'screenshot.png'], + args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1'], message='You should see an image with gray at the top.') + def test_sdl_ogl_proc_alias(self): + shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) + self.btest('sdl_ogl_proc_alias.c', reference='screenshot-gray-purple.png', reference_slack=1, + args=['-O2', '-g2', '-s', 'INLINING_LIMIT=1', '--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1', '-s', 'VERBOSE=1']) + def test_sdl_fog_simple(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_fog_simple.c', reference='screenshot-fog-simple.png', - args=['-O2', '--minify', '0', '--preload-file', 'screenshot.png'], + args=['-O2', '--minify', '0', '--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1'], message='You should see an image with fog.') def test_sdl_fog_negative(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_fog_negative.c', reference='screenshot-fog-negative.png', - args=['--preload-file', 'screenshot.png'], + args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1'], message='You should see an image with fog.') def test_sdl_fog_density(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_fog_density.c', reference='screenshot-fog-density.png', - args=['--preload-file', 'screenshot.png'], + args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1'], message='You should see an image with fog.') def test_sdl_fog_exp2(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_fog_exp2.c', reference='screenshot-fog-exp2.png', - args=['--preload-file', 'screenshot.png'], + args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1'], message='You should see an image with fog.') def test_sdl_fog_linear(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('sdl_fog_linear.c', reference='screenshot-fog-linear.png', reference_slack=1, - args=['--preload-file', 'screenshot.png'], + args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1'], message='You should see an image with fog.') def test_openal_playback(self): @@ -903,7 +915,7 @@ Press any key to continue.''' def test_glfw(self): open(os.path.join(self.get_dir(), 'glfw.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'glfw.c')).read())) - Popen([PYTHON, EMCC, '-O2', os.path.join(self.get_dir(), 'glfw.c'), '-o', 'page.html']).communicate() + Popen([PYTHON, EMCC, '-O2', os.path.join(self.get_dir(), 'glfw.c'), '-o', 'page.html', '-s', 'LEGACY_GL_EMULATION=1']).communicate() self.run_browser('page.html', '', '/report_result?1') def test_egl_width_height(self): @@ -1056,30 +1068,26 @@ Press any key to continue.''' server.terminate() def test_glgears(self): - self.btest('hello_world_gles.c', reference='gears.png', + self.btest('hello_world_gles.c', reference='gears.png', reference_slack=1, args=['-DHAVE_BUILTIN_SINCOS'], outfile='something.html', message='You should see animating gears.') def test_glgears_animation(self): es2_suffix = ['', '_full', '_full_944'] for full_es2 in [0, 1, 2]: - for emulation in [0, 1]: - if full_es2 and emulation: continue - print full_es2, emulation - Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles%s.c' % es2_suffix[full_es2]), '-o', 'something.html', - '-DHAVE_BUILTIN_SINCOS', '-s', 'GL_TESTING=1', - '--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')] + - (['-s', 'FORCE_GL_EMULATION=1'] if emulation else []) + - (['-s', 'FULL_ES2=1'] if full_es2 else []), - ).communicate() - self.run_browser('something.html', 'You should see animating gears.', '/report_gl_result?true') - assert ('var GLEmulation' in open(self.in_dir('something.html')).read()) == emulation, "emulation code should be added when asked for" + print full_es2 + Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles%s.c' % es2_suffix[full_es2]), '-o', 'something.html', + '-DHAVE_BUILTIN_SINCOS', '-s', 'GL_TESTING=1', + '--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')] + + (['-s', 'FULL_ES2=1'] if full_es2 else []), + ).communicate() + self.run_browser('something.html', 'You should see animating gears.', '/report_gl_result?true') def test_fulles2_sdlproc(self): self.btest('full_es2_sdlproc.c', '1', args=['-s', 'GL_TESTING=1', '-DHAVE_BUILTIN_SINCOS', '-s', 'FULL_ES2=1']) def test_glgears_deriv(self): - self.btest('hello_world_gles_deriv.c', reference='gears.png', + self.btest('hello_world_gles_deriv.c', reference='gears.png', reference_slack=1, args=['-DHAVE_BUILTIN_SINCOS'], outfile='something.html', message='You should see animating gears.') with open('something.html') as f: @@ -1163,90 +1171,90 @@ Press any key to continue.''' self.btest('glgetattachedshaders.c', '1') def test_sdlglshader(self): - self.btest('sdlglshader.c', reference='sdlglshader.png', args=['-O2', '--closure', '1']) + self.btest('sdlglshader.c', reference='sdlglshader.png', args=['-O2', '--closure', '1', '-s', 'LEGACY_GL_EMULATION=1']) def test_gl_ps(self): # pointers and a shader shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) - self.btest('gl_ps.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png'], reference_slack=1) + self.btest('gl_ps.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1'], reference_slack=1) def test_gl_ps_packed(self): # packed data that needs to be strided shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) - self.btest('gl_ps_packed.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png'], reference_slack=1) + self.btest('gl_ps_packed.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1'], reference_slack=1) def test_gl_ps_strides(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) - self.btest('gl_ps_strides.c', reference='gl_ps_strides.png', args=['--preload-file', 'screenshot.png']) + self.btest('gl_ps_strides.c', reference='gl_ps_strides.png', args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1']) def test_gl_renderers(self): - self.btest('gl_renderers.c', reference='gl_renderers.png', args=['-s', 'GL_UNSAFE_OPTS=0']) + self.btest('gl_renderers.c', reference='gl_renderers.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1']) def test_gl_stride(self): - self.btest('gl_stride.c', reference='gl_stride.png', args=['-s', 'GL_UNSAFE_OPTS=0']) + self.btest('gl_stride.c', reference='gl_stride.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1']) def test_matrix_identity(self): - self.btest('gl_matrix_identity.c', expected=['-1882984448', '460451840']) + self.btest('gl_matrix_identity.c', expected=['-1882984448', '460451840'], args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_pre(self): - self.btest('cubegeom_pre.c', reference='cubegeom_pre.png') + self.btest('cubegeom_pre.c', reference='cubegeom_pre.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_pre2(self): - self.btest('cubegeom_pre2.c', reference='cubegeom_pre2.png', args=['-s', 'GL_DEBUG=1']) # some coverage for GL_DEBUG not breaking the build + self.btest('cubegeom_pre2.c', reference='cubegeom_pre2.png', args=['-s', 'GL_DEBUG=1', '-s', 'LEGACY_GL_EMULATION=1']) # some coverage for GL_DEBUG not breaking the build def test_cubegeom_pre3(self): - self.btest('cubegeom_pre3.c', reference='cubegeom_pre2.png') + self.btest('cubegeom_pre3.c', reference='cubegeom_pre2.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom(self): - self.btest('cubegeom.c', args=['-O2', '-g'], reference='cubegeom.png') + self.btest('cubegeom.c', reference='cubegeom.png', args=['-O2', '-g', '-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_glew(self): - self.btest('cubegeom_glew.c', args=['-O2', '--closure', '1'], reference='cubegeom.png') + self.btest('cubegeom_glew.c', reference='cubegeom.png', args=['-O2', '--closure', '1', '-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_color(self): - self.btest('cubegeom_color.c', reference='cubegeom_color.png') + self.btest('cubegeom_color.c', reference='cubegeom_color.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_normal(self): - self.btest('cubegeom_normal.c', reference='cubegeom_normal.png') + self.btest('cubegeom_normal.c', reference='cubegeom_normal.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_normal_dap(self): # draw is given a direct pointer to clientside memory, no element array buffer - self.btest('cubegeom_normal_dap.c', reference='cubegeom_normal.png') + self.btest('cubegeom_normal_dap.c', reference='cubegeom_normal.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_normal_dap_far(self): # indices do nto start from 0 - self.btest('cubegeom_normal_dap_far.c', reference='cubegeom_normal.png') + self.btest('cubegeom_normal_dap_far.c', reference='cubegeom_normal.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_normal_dap_far_range(self): # glDrawRangeElements - self.btest('cubegeom_normal_dap_far_range.c', reference='cubegeom_normal.png') + self.btest('cubegeom_normal_dap_far_range.c', reference='cubegeom_normal.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_normal_dap_far_glda(self): # use glDrawArrays - self.btest('cubegeom_normal_dap_far_glda.c', reference='cubegeom_normal_dap_far_glda.png') + self.btest('cubegeom_normal_dap_far_glda.c', reference='cubegeom_normal_dap_far_glda.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_normal_dap_far_glda_quad(self): # with quad - self.btest('cubegeom_normal_dap_far_glda_quad.c', reference='cubegeom_normal_dap_far_glda_quad.png') + self.btest('cubegeom_normal_dap_far_glda_quad.c', reference='cubegeom_normal_dap_far_glda_quad.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_mt(self): - self.btest('cubegeom_mt.c', reference='cubegeom_mt.png') # multitexture + self.btest('cubegeom_mt.c', reference='cubegeom_mt.png', args=['-s', 'LEGACY_GL_EMULATION=1']) # multitexture def test_cubegeom_color2(self): - self.btest('cubegeom_color2.c', reference='cubegeom_color2.png') + self.btest('cubegeom_color2.c', reference='cubegeom_color2.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_texturematrix(self): - self.btest('cubegeom_texturematrix.c', reference='cubegeom_texturematrix.png') + self.btest('cubegeom_texturematrix.c', reference='cubegeom_texturematrix.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_fog(self): - self.btest('cubegeom_fog.c', reference='cubegeom_fog.png') + self.btest('cubegeom_fog.c', reference='cubegeom_fog.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_pre_vao(self): - self.btest('cubegeom_pre_vao.c', reference='cubegeom_pre_vao.png') + self.btest('cubegeom_pre_vao.c', reference='cubegeom_pre_vao.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_pre2_vao(self): - self.btest('cubegeom_pre2_vao.c', reference='cubegeom_pre_vao.png') + self.btest('cubegeom_pre2_vao.c', reference='cubegeom_pre_vao.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cubegeom_pre2_vao2(self): - self.btest('cubegeom_pre2_vao2.c', reference='cubegeom_pre2_vao2.png') + self.btest('cubegeom_pre2_vao2.c', reference='cubegeom_pre2_vao2.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_cube_explosion(self): - self.btest('cube_explosion.c', reference='cube_explosion.png') + self.btest('cube_explosion.c', reference='cube_explosion.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_sdl_canvas_blank(self): self.btest('sdl_canvas_blank.c', reference='sdl_canvas_blank.png') @@ -1298,11 +1306,11 @@ Press any key to continue.''' def test_glbegin_points(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) - self.btest('glbegin_points.c', reference='glbegin_points.png', args=['--preload-file', 'screenshot.png']) + self.btest('glbegin_points.c', reference='glbegin_points.png', args=['--preload-file', 'screenshot.png', '-s', 'LEGACY_GL_EMULATION=1']) def test_s3tc(self): shutil.copyfile(path_from_root('tests', 'screenshot.dds'), os.path.join(self.get_dir(), 'screenshot.dds')) - self.btest('s3tc.c', reference='s3tc.png', args=['--preload-file', 'screenshot.dds']) + self.btest('s3tc.c', reference='s3tc.png', args=['--preload-file', 'screenshot.dds', '-s', 'LEGACY_GL_EMULATION=1']) def test_s3tc_crunch(self): shutil.copyfile(path_from_root('tests', 'ship.dds'), 'ship.dds') @@ -1313,7 +1321,7 @@ Press any key to continue.''' shutil.move('ship.dds', 'ship.donotfindme.dds') # make sure we load from the compressed shutil.move('bloom.dds', 'bloom.donotfindme.dds') # make sure we load from the compressed shutil.move('water.dds', 'water.donotfindme.dds') # make sure we load from the compressed - self.btest('s3tc_crunch.c', reference='s3tc_crunch.png', reference_slack=11, args=['--pre-js', 'pre.js']) + self.btest('s3tc_crunch.c', reference='s3tc_crunch.png', reference_slack=11, args=['--pre-js', 'pre.js', '-s', 'LEGACY_GL_EMULATION=1']) def test_s3tc_crunch_split(self): # load several datafiles/outputs of file packager shutil.copyfile(path_from_root('tests', 'ship.dds'), 'ship.dds') @@ -1324,14 +1332,20 @@ Press any key to continue.''' shutil.move('ship.dds', 'ship.donotfindme.dds') # make sure we load from the compressed shutil.move('bloom.dds', 'bloom.donotfindme.dds') # make sure we load from the compressed shutil.move('water.dds', 'water.donotfindme.dds') # make sure we load from the compressed - self.btest('s3tc_crunch.c', reference='s3tc_crunch.png', reference_slack=11, args=['--pre-js', 'asset_a.js', '--pre-js', 'asset_b.js']) + self.btest('s3tc_crunch.c', reference='s3tc_crunch.png', reference_slack=11, args=['--pre-js', 'asset_a.js', '--pre-js', 'asset_b.js', '-s', 'LEGACY_GL_EMULATION=1']) def test_aniso(self): + if SPIDERMONKEY_ENGINE in JS_ENGINES: + # asm.js-ification check + Popen([PYTHON, EMCC, path_from_root('tests', 'aniso.c'), '-O2', '-g2', '-s', 'LEGACY_GL_EMULATION=1']).communicate() + Settings.ASM_JS = 1 + self.run_generated_code(SPIDERMONKEY_ENGINE, 'a.out.js') + shutil.copyfile(path_from_root('tests', 'water.dds'), 'water.dds') - self.btest('aniso.c', reference='aniso.png', reference_slack=2, args=['--preload-file', 'water.dds']) + self.btest('aniso.c', reference='aniso.png', reference_slack=2, args=['--preload-file', 'water.dds', '-s', 'LEGACY_GL_EMULATION=1']) def test_tex_nonbyte(self): - self.btest('tex_nonbyte.c', reference='tex_nonbyte.png') + self.btest('tex_nonbyte.c', reference='tex_nonbyte.png', args=['-s', 'LEGACY_GL_EMULATION=1']) def test_float_tex(self): self.btest('float_tex.cpp', reference='float_tex.png') @@ -1340,10 +1354,10 @@ Press any key to continue.''' self.btest('gl_subdata.cpp', reference='float_tex.png') def test_perspective(self): - self.btest('perspective.c', reference='perspective.png') + 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 31db6ca5..7eff0d2f 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) @@ -5451,7 +5545,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 +5564,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 +5617,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 +5713,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 +5817,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 +5874,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 +6761,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 +6788,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 +7130,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 +8327,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]' @@ -9582,15 +9679,15 @@ def process(filename): self.assertIdentical(clean(no_maps_file), clean(out_file)) map_filename = out_filename + '.map' data = json.load(open(map_filename, 'r')) - self.assertIdentical(out_filename, data['file']) - self.assertIdentical(src_filename, data['sources'][0]) - self.assertIdentical(src, data['sourcesContent'][0]) + self.assertPathsIdentical(out_filename, data['file']) + self.assertPathsIdentical(src_filename, data['sources'][0]) + self.assertTextDataIdentical(src, data['sourcesContent'][0]) mappings = json.loads(jsrun.run_js( path_from_root('tools', 'source-maps', 'sourcemap2json.js'), tools.shared.NODE_JS, [map_filename])) seen_lines = set() for m in mappings: - self.assertIdentical(src_filename, m['source']) + self.assertPathsIdentical(src_filename, m['source']) seen_lines.add(m['originalLine']) # ensure that all the 'meaningful' lines in the original code get mapped assert seen_lines.issuperset([6, 7, 11, 12]) @@ -10071,4 +10168,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..d6e67e59 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -802,8 +802,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 +1033,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') diff --git a/tests/test_sockets.py b/tests/test_sockets.py index 03593674..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); @@ -198,3 +199,71 @@ class sockets(BrowserCore): # ]: # with harness: # self.btest(os.path.join('sockets', 'test_enet_client.c'), expected='0', args=['-DSOCKK=9011'] + enet) + + def test_webrtc(self): + host_src = 'webrtc_host.c' + peer_src = 'webrtc_peer.c' + + host_outfile = 'host.html' + peer_outfile = 'peer.html' + + host_filepath = path_from_root('tests', 'sockets', host_src) + temp_host_filepath = os.path.join(self.get_dir(), os.path.basename(host_src)) + with open(host_filepath) as f: host_src = f.read() + with open(temp_host_filepath, 'w') as f: f.write(self.with_report_result(host_src)) + + peer_filepath = path_from_root('tests', 'sockets', peer_src) + temp_peer_filepath = os.path.join(self.get_dir(), os.path.basename(peer_src)) + with open(peer_filepath) as f: peer_src = f.read() + with open(temp_peer_filepath, 'w') as f: f.write(self.with_report_result(peer_src)) + + open(os.path.join(self.get_dir(), 'host_pre.js'), 'w').write(''' + var Module = { + webrtc: { + broker: 'https://mdsw.ch:8080', + session: undefined, + onpeer: function(peer, route) { + window.open('http://localhost:8888/peer.html?' + route); + // iframe = document.createElement("IFRAME"); + // iframe.setAttribute("src", "http://localhost:8888/peer.html?" + route); + // iframe.style.display = "none"; + // document.body.appendChild(iframe); + peer.listen(); + }, + onconnect: function(peer) { + }, + ondisconnect: function(peer) { + }, + onerror: function(error) { + console.error(error); + } + }, + }; + ''') + + open(os.path.join(self.get_dir(), 'peer_pre.js'), 'w').write(''' + var Module = { + webrtc: { + broker: 'https://mdsw.ch:8080', + session: window.location.toString().split('?')[1], + onpeer: function(peer, route) { + peer.connect(Module['webrtc']['session']); + }, + onconnect: function(peer) { + }, + ondisconnect: function(peer) { + // Calling window.close() from this handler hangs my browser, so run it in the next turn + setTimeout(window.close, 0); + }, + onerror: function(error) { + console.error(error); + } + } + }; + ''') + + Popen([PYTHON, EMCC, temp_host_filepath, '-o', host_outfile] + ['-s', 'GL_TESTING=1', '--pre-js', 'host_pre.js', '-s', 'SOCKET_WEBRTC=1', '-s', 'SOCKET_DEBUG=1']).communicate() + Popen([PYTHON, EMCC, temp_peer_filepath, '-o', peer_outfile] + ['-s', 'GL_TESTING=1', '--pre-js', 'peer_pre.js', '-s', 'SOCKET_WEBRTC=1', '-s', 'SOCKET_DEBUG=1']).communicate() + + expected = '1' + self.run_browser(host_outfile, '.', ['/report_result?' + e for e in expected])
\ No newline at end of file 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/find_bigfuncs.py b/tools/find_bigfuncs.py index 6fdec3a9..79136343 100644 --- a/tools/find_bigfuncs.py +++ b/tools/find_bigfuncs.py @@ -1,5 +1,5 @@ ''' -Simple tool to find big functions in an .ll file. +Simple tool to find big functions in a js or ll file ''' import os, sys, re @@ -11,7 +11,7 @@ curr = None data = [] for line in open(filename): i += 1 - if line.startswith('function '): + if line.startswith(('function ', 'define ')): start = i curr = line elif line.startswith('}') and curr: diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index ff6aee67..9a5104bf 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -801,7 +801,10 @@ function simplifyExpressions(ast) { // HEAP[x >> 2] // very often. We can in some cases do the shift on the variable itself when it is set, // to greatly reduce the number of shift operations. -// TODO: when shifting a variable, if there are other uses, keep an unshifted version too, to prevent slowdowns? +// XXX this optimization is deprecated and currently invalid: does not handle overflows +// or non-aligned (round numbers, x >> 2 is a multiple of 4). Both are ok to assume +// for pointers (undefined behavior otherwise), but invalid in general, and we do +// no sufficiently-well distinguish the cases. function optimizeShiftsInternal(ast, conservative) { var MAX_SHIFTS = 3; traverseGeneratedFunctions(ast, function(fun) { @@ -1233,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; @@ -3001,7 +3004,7 @@ function outline(ast) { // Try to flatten out code as much as possible, to make outlining more feasible. function flatten(func, asmData) { - var minSize = sizeToOutline; + var minSize = extraInfo.sizeToOutline/4; var helperId = 0; function getHelper() { while (1) { @@ -3023,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)); @@ -3088,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 @@ -3107,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 }; @@ -3437,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 } @@ -3475,6 +3513,9 @@ function outline(ast) { } } } + function done() { + return asmData.splitCounter >= asmData.maxOutlinings || measureSize(func) <= extraInfo.sizeToOutline; + } while (1) { i--; calcMinIndex(); // TODO: optimize @@ -3530,7 +3571,7 @@ function outline(ast) { if (ret.length > pre) { // we outlined recursively, reset our state here //printErr('successful outline in recursion ' + func[1] + ' due to recursive in level ' + level); - if (measureSize(func) <= extraInfo.sizeToOutline) break; + if (done()) break; end = i-1; sizeSeen = 0; canRestart = true; @@ -3570,7 +3611,7 @@ function outline(ast) { if (newFuncs.length) { ret.push.apply(ret, newFuncs); } - if (measureSize(func) <= extraInfo.sizeToOutline) break; + if (done()) break; sizeSeen = 0; end = i-1; canRestart = true; @@ -3590,6 +3631,8 @@ function outline(ast) { var funcs = ast[1]; + var maxTotalFunctions = Infinity; // debugging tool + var more = true; while (more) { more = false; @@ -3597,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/response_file.py b/tools/response_file.py index 312cda73..f19cf8af 100644 --- a/tools/response_file.py +++ b/tools/response_file.py @@ -6,8 +6,8 @@ def create_response_file(args, directory): (response_fd, response_filename) = tempfile.mkstemp(prefix='emscripten_', suffix='.rsp', dir=directory, text=True) response_fd = os.fdopen(response_fd, "w") #print >> sys.stderr, "Creating response file '%s'" % response_filename - args = map(lambda p: p.replace(' ', '').replace('\\', '\\\\').replace('"', '\\"'), args) - response_fd.write(' '.join(args)) + args = map(lambda p: p.replace('\\', '\\\\').replace('"', '\\"'), args) + response_fd.write('"' + '" "'.join(args) + '"') response_fd.close() return response_filename diff --git a/tools/shared.py b/tools/shared.py index 917f548e..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 @@ -550,6 +550,7 @@ if USE_EMSDK: # allows projects to override them) EMSDK_OPTS = ['-nostdinc', '-Xclang', '-nobuiltininc', '-Xclang', '-nostdsysteminc', '-Xclang', '-isystem' + path_from_root('system', 'local', 'include'), + '-Xclang', '-isystem' + path_from_root('system', 'include', 'compat'), '-Xclang', '-isystem' + path_from_root('system', 'include', 'libcxx'), '-Xclang', '-isystem' + path_from_root('system', 'include'), '-Xclang', '-isystem' + path_from_root('system', 'include', 'emscripten'), diff --git a/tools/source-maps/sourcemapper.js b/tools/source-maps/sourcemapper.js index fa908900..06c9a227 100755 --- a/tools/source-maps/sourcemapper.js +++ b/tools/source-maps/sourcemapper.js @@ -16,6 +16,38 @@ function countLines(s) { return count; } +// For a minor optimization, only do win32->unix normalization if we are actually on Windows, +// which avoids redundantly scanning files if not needed. +var isWindows = (process.platform === 'win32'); + +var unixPathRe = new RegExp('\\\\', 'g'); +// Returns the given (possibly Windows) path p normalized to unix path separators '/'. +function toUnixPath(p) { + if (isWindows) { + return p.replace(unixPathRe, '/'); + } else { + return p; + } +} + +var unixLineEndRe = new RegExp('\r\n', 'g'); +// Returns the given (possibly Windows) text data t normalized to unix line endings '\n'. +function toUnixLineEnding(t) { + if (isWindows) { + return t.replace(unixLineEndRe, '\n'); + } else { + return t; + } +} + +// If path "p2" is a relative path, joins paths p1 and p2 to form "p1/p2". If p2 is an absolute path, "p2" is returned. +function joinPath(p1, p2) { + if (p2[0] == '/' || (p2.length >= 3 && p2[1] == ':' && (p2[2] == '/' || p2[2] == '\\'))) // Is p2 an absolute path? + return p2; + else + return toUnixPath(path.join(p1, p2)); +} + /* * Extracts the line (not block) comments from the generated function code and * invokes commentHandler with (comment content, line number of comment). This @@ -105,8 +137,7 @@ function generateMap(mappings, sourceRoot, mapFileBaseName, generatedLineOffset) // avoid doing it unnecessarily if (!(originalFileName in seenFiles)) { seenFiles[originalFileName] = true; - var rootedPath = originalFileName[0] === path.sep ? - originalFileName : path.join(sourceRoot, originalFileName); + var rootedPath = joinPath(sourceRoot, originalFileName); try { generator.setSourceContent(originalFileName, fs.readFileSync(rootedPath, 'utf-8')); } catch (e) { @@ -144,15 +175,15 @@ if (require.main === module) { } else { var opts = parseArgs(process.argv.slice(2)); var fileName = opts._[0]; - var sourceRoot = opts.sourceRoot ? opts.sourceRoot : "."; - var mapFileBaseName = opts.mapFileBaseName ? opts.mapFileBaseName : fileName; + var sourceRoot = opts.sourceRoot ? toUnixPath(opts.sourceRoot) : "."; + var mapFileBaseName = toUnixPath(opts.mapFileBaseName ? opts.mapFileBaseName : fileName); var generatedLineOffset = opts.offset ? parseInt(opts.offset, 10) : 0; - var generatedSource = fs.readFileSync(fileName, 'utf-8'); + var generatedSource = toUnixLineEnding(fs.readFileSync(fileName, 'utf-8')); var source = generatedSource; var mappings = getMappings(generatedSource); for (var i = 1, l = opts._.length; i < l; i ++) { - var optimizedSource = fs.readFileSync(opts._[i], 'utf-8') + var optimizedSource = toUnixLineEnding(fs.readFileSync(opts._[i], 'utf-8')) var optimizedMappings = getMappings(optimizedSource); var newMappings = {}; // uglify processes the code between EMSCRIPTEN_START_FUNCS and diff --git a/tools/test-js-optimizer-asm-outline1-output.js b/tools/test-js-optimizer-asm-outline1-output.js index 904e56cf..895004d8 100644 --- a/tools/test-js-optimizer-asm-outline1-output.js +++ b/tools/test-js-optimizer-asm-outline1-output.js @@ -276,8 +276,29 @@ function vars_w_stack(x, y) { function chain() { var helper$0 = 0, sp = 0; sp = STACKTOP; - STACKTOP = STACKTOP + 240 | 0; + STACKTOP = STACKTOP + 464 | 0; helper$0 = 1; + if (helper$0) { + helper$0 = 0; + if (x == 1) { + print(1); + } else { + helper$0 = 1; + } + } + if (helper$0) { + helper$0 = 0; + if (x == 2) { + print(2); + } else { + helper$0 = 1; + } + } + HEAP32[sp + 8 >> 2] = helper$0; + HEAP32[sp + 48 >> 2] = 0; + HEAP32[sp + 52 >> 2] = 0; + chain$4(sp); + helper$0 = HEAP32[sp + 8 >> 2] | 0; HEAP32[sp + 8 >> 2] = helper$0; HEAP32[sp + 40 >> 2] = 0; HEAP32[sp + 44 >> 2] = 0; @@ -288,6 +309,58 @@ function chain() { HEAP32[sp + 36 >> 2] = 0; chain$2(sp); helper$0 = HEAP32[sp + 8 >> 2] | 0; + HEAP32[sp + 8 >> 2] = helper$0; + HEAP32[sp + 24 >> 2] = 0; + HEAP32[sp + 28 >> 2] = 0; + chain$1(sp); + helper$0 = HEAP32[sp + 8 >> 2] | 0; + HEAP32[sp + 8 >> 2] = helper$0; + HEAP32[sp + 16 >> 2] = 0; + HEAP32[sp + 20 >> 2] = 0; + chain$0(sp); + 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) { @@ -500,22 +573,21 @@ function chain$0(sp) { sp = sp | 0; var helper$0 = 0; helper$0 = HEAP32[sp + 8 >> 2] | 0; - if (x == 7) { - print(7); - } else if (x == 8) { - print(8); - } else if (x == 9) { - print(9); - } else if (x == 10) { - print(10); - } else if (x == 11) { - print(11); - } else if (x == 12) { - print(12); - } else if (1) { - print(99); - } else { - helper$0 = 1; + if (helper$0) { + helper$0 = 0; + if (x == 12) { + print(12); + } else { + helper$0 = 1; + } + } + if (helper$0) { + helper$0 = 0; + if (1) { + print(99); + } else { + helper$0 = 1; + } } HEAP32[sp + 8 >> 2] = helper$0; } @@ -523,20 +595,21 @@ function chain$1(sp) { sp = sp | 0; var helper$0 = 0; helper$0 = HEAP32[sp + 8 >> 2] | 0; - if (x == 1) { - print(1); - } else if (x == 2) { - print(2); - } else if (x == 3) { - print(3); - } else if (x == 4) { - print(4); - } else if (x == 5) { - print(5); - } else if (x == 6) { - print(6); - } else { - helper$0 = 1; + if (helper$0) { + helper$0 = 0; + if (x == 10) { + print(10); + } else { + helper$0 = 1; + } + } + if (helper$0) { + helper$0 = 0; + if (x == 11) { + print(11); + } else { + helper$0 = 1; + } } HEAP32[sp + 8 >> 2] = helper$0; } @@ -546,11 +619,19 @@ function chain$2(sp) { helper$0 = HEAP32[sp + 8 >> 2] | 0; if (helper$0) { helper$0 = 0; - HEAP32[sp + 8 >> 2] = helper$0; - HEAP32[sp + 16 >> 2] = 0; - HEAP32[sp + 20 >> 2] = 0; - chain$0(sp); - helper$0 = HEAP32[sp + 8 >> 2] | 0; + if (x == 8) { + print(8); + } else { + helper$0 = 1; + } + } + if (helper$0) { + helper$0 = 0; + if (x == 9) { + print(9); + } else { + helper$0 = 1; + } } HEAP32[sp + 8 >> 2] = helper$0; } @@ -560,11 +641,143 @@ function chain$3(sp) { helper$0 = HEAP32[sp + 8 >> 2] | 0; if (helper$0) { helper$0 = 0; - HEAP32[sp + 8 >> 2] = helper$0; - HEAP32[sp + 24 >> 2] = 0; - HEAP32[sp + 28 >> 2] = 0; - chain$1(sp); - helper$0 = HEAP32[sp + 8 >> 2] | 0; + if (x == 6) { + print(6); + } else { + helper$0 = 1; + } + } + if (helper$0) { + helper$0 = 0; + if (x == 7) { + print(7); + } else { + helper$0 = 1; + } + } + HEAP32[sp + 8 >> 2] = helper$0; +} +function chain$4(sp) { + sp = sp | 0; + var helper$0 = 0; + helper$0 = HEAP32[sp + 8 >> 2] | 0; + if (helper$0) { + helper$0 = 0; + if (x == 3) { + print(3); + } else { + helper$0 = 1; + } + } + if (helper$0) { + helper$0 = 0; + if (x == 4) { + print(4); + } else { + helper$0 = 1; + } + } + if (helper$0) { + helper$0 = 0; + if (x == 5) { + print(5); + } else { + helper$0 = 1; + } + } + 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 } diff --git a/tools/test-js-optimizer-asm-outline2-output.js b/tools/test-js-optimizer-asm-outline2-output.js index 28feb6cb..2658fda0 100644 --- a/tools/test-js-optimizer-asm-outline2-output.js +++ b/tools/test-js-optimizer-asm-outline2-output.js @@ -23,7 +23,7 @@ function linear() { } function _free($mem) { $mem = $mem | 0; - var $5 = 0, $10 = 0, $16 = 0, $21 = 0, $25 = 0, $26 = 0, $psize_0 = 0, $p_0 = 0, $189 = 0, $194 = 0, sp = 0; + var $5 = 0, $10 = 0, $16 = 0, $21 = 0, $25 = 0, $26 = 0, $psize_0 = 0, $p_0 = 0, $189 = 0, $194 = 0, sp = 0, helper$0 = 0; sp = STACKTOP; if (($mem | 0) == 0) { STACKTOP = sp; @@ -39,59 +39,71 @@ function _free($mem) { } $16 = $mem + (($10 & -8) - 8) | 0; L621 : do { - if (($10 & 1 | 0) == 0) { - $21 = HEAP32[($mem - 8 | 0) >> 2] | 0; - if (($10 & 3 | 0) == 0) { - return; - } - $25 = $mem + (-8 - $21 | 0) | 0; - $26 = $21 + ($10 & -8) | 0; - if (($mem + (-8 - $21 | 0) | 0) >>> 0 < $5 >>> 0) { - _abort(); - } - if (($25 | 0) == (HEAP32[25] | 0)) { - if ((HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] & 3 | 0) != 3) { - $p_0 = $25; - $psize_0 = $26; + helper$0 = 1; + if (helper$0) { + helper$0 = 0; + if (($10 & 1 | 0) == 0) { + $21 = HEAP32[($mem - 8 | 0) >> 2] | 0; + if (($10 & 3 | 0) == 0) { + return; + } + $25 = $mem + (-8 - $21 | 0) | 0; + $26 = $21 + ($10 & -8) | 0; + if (($mem + (-8 - $21 | 0) | 0) >>> 0 < $5 >>> 0) { + _abort(); + } + if (($25 | 0) == (HEAP32[25] | 0)) { + if ((HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] & 3 | 0) != 3) { + $p_0 = $25; + $psize_0 = $26; + break; + } + HEAP32[22] = $26; + HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] = HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] & -2; + HEAP32[$mem + ((-8 - $21 | 0) + 4) >> 2] = $26 | 1; + HEAP32[($mem + (($10 & -8) - 8) | 0) >> 2] = $26; + return; + } + HEAP32[sp + 8 >> 2] = $mem; + HEAP32[sp + 16 >> 2] = $5; + HEAP32[sp + 40 >> 2] = $21; + HEAP32[sp + 48 >> 2] = $25; + HEAP32[sp + 56 >> 2] = $26; + HEAP32[sp + 216 >> 2] = $psize_0; + HEAP32[sp + 224 >> 2] = $p_0; + HEAP32[sp + 696 >> 2] = 0; + HEAP32[sp + 700 >> 2] = 0; + _free$1(sp); + $psize_0 = HEAP32[sp + 216 >> 2] | 0; + $p_0 = HEAP32[sp + 224 >> 2] | 0; + tempValue = HEAP32[sp + 696 >> 2] | 0; + tempInt = HEAP32[sp + 700 >> 2] | 0; + tempDouble = +HEAPF32[sp + 700 >> 2]; + HEAP32[sp + 696 >> 2] = 0; + HEAP32[sp + 700 >> 2] = 0; + if ((tempValue | 0) == 1) { break; } - HEAP32[22] = $26; - HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] = HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] & -2; - HEAP32[$mem + ((-8 - $21 | 0) + 4) >> 2] = $26 | 1; - HEAP32[($mem + (($10 & -8) - 8) | 0) >> 2] = $26; - return; - } - HEAP32[sp + 8 >> 2] = $mem; - HEAP32[sp + 16 >> 2] = $5; - HEAP32[sp + 40 >> 2] = $21; - HEAP32[sp + 48 >> 2] = $25; - HEAP32[sp + 56 >> 2] = $26; - HEAP32[sp + 216 >> 2] = $psize_0; - HEAP32[sp + 224 >> 2] = $p_0; - HEAP32[sp + 648 >> 2] = 0; - HEAP32[sp + 652 >> 2] = 0; - _free$1(sp); - $psize_0 = HEAP32[sp + 216 >> 2] | 0; - $p_0 = HEAP32[sp + 224 >> 2] | 0; - tempValue = HEAP32[sp + 648 >> 2] | 0; - tempInt = HEAP32[sp + 652 >> 2] | 0; - tempDouble = +HEAPF32[sp + 652 >> 2]; - HEAP32[sp + 648 >> 2] = 0; - HEAP32[sp + 652 >> 2] = 0; - if ((tempValue | 0) == 1) { - break; - } - if ((tempValue | 0) == 2) { - switch (tempInt | 0) { - case 2: - { - break L621; + if ((tempValue | 0) == 2) { + switch (tempInt | 0) { + case 2: + { + break L621; + } } } + } else { + helper$0 = 1; + } + } + if (helper$0) { + helper$0 = 0; + if (1) { + $p_0 = $mem - 8 | 0; + $psize_0 = $10 & -8; + } else { + helper$0 = 1; } - } else { - $p_0 = $mem - 8 | 0; - $psize_0 = $10 & -8; } } while (0); $189 = $p_0; @@ -109,14 +121,14 @@ function _free($mem) { HEAP32[sp + 224 >> 2] = $p_0; HEAP32[sp + 232 >> 2] = $189; HEAP32[sp + 240 >> 2] = $194; - HEAP32[sp + 656 >> 2] = 0; - HEAP32[sp + 660 >> 2] = 0; + HEAP32[sp + 704 >> 2] = 0; + HEAP32[sp + 708 >> 2] = 0; _free$2(sp); - tempValue = HEAP32[sp + 656 >> 2] | 0; - tempInt = HEAP32[sp + 660 >> 2] | 0; - tempDouble = +HEAPF32[sp + 660 >> 2]; - HEAP32[sp + 656 >> 2] = 0; - HEAP32[sp + 660 >> 2] = 0; + tempValue = HEAP32[sp + 704 >> 2] | 0; + tempInt = HEAP32[sp + 708 >> 2] | 0; + tempDouble = +HEAPF32[sp + 708 >> 2]; + HEAP32[sp + 704 >> 2] = 0; + HEAP32[sp + 708 >> 2] = 0; if ((tempValue | 0) == 5) { return; } @@ -153,175 +165,200 @@ function linear$1(sp) { } function _free$0(sp) { sp = sp | 0; - var $194 = 0, $233 = 0, $mem = 0, $10 = 0, $236 = 0, $16 = 0, $_pre_phi305 = 0, $267 = 0, $270 = 0, $273 = 0, $294 = 0, $299 = 0, $R7_1 = 0, $R7_0 = 0, $RP9_0 = 0, $301 = 0, $302 = 0, $305 = 0, $306 = 0, $278 = 0, $320 = 0, $351 = 0, $364 = 0; + var helper$3 = 0, $194 = 0, $233 = 0, $mem = 0, $10 = 0, $236 = 0, $16 = 0, $_pre_phi305 = 0, $267 = 0, $270 = 0, $273 = 0, helper$4 = 0, $294 = 0, $299 = 0, $R7_1 = 0, $R7_0 = 0, $RP9_0 = 0, $301 = 0, $302 = 0, $305 = 0, $306 = 0, $278 = 0, $320 = 0, $351 = 0, $364 = 0; $mem = HEAP32[sp + 8 >> 2] | 0; $10 = HEAP32[sp + 24 >> 2] | 0; $16 = HEAP32[sp + 32 >> 2] | 0; $194 = HEAP32[sp + 240 >> 2] | 0; + helper$3 = HEAP32[sp + 664 >> 2] | 0; OL : do { - if ($194 >>> 0 < 256) { - $233 = HEAP32[$mem + ($10 & -8) >> 2] | 0; - $236 = HEAP32[$mem + ($10 & -8 | 4) >> 2] | 0; - do { - if (($233 | 0) != (120 + ($194 >>> 3 << 1 << 2) | 0 | 0)) { - if ($233 >>> 0 < (HEAP32[24] | 0) >>> 0) { + if (helper$3) { + helper$3 = 0; + if ($194 >>> 0 < 256) { + $233 = HEAP32[$mem + ($10 & -8) >> 2] | 0; + $236 = HEAP32[$mem + ($10 & -8 | 4) >> 2] | 0; + do { + if (($233 | 0) != (120 + ($194 >>> 3 << 1 << 2) | 0 | 0)) { + if ($233 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + if ((HEAP32[$233 + 12 >> 2] | 0) == ($16 | 0)) { + break; + } _abort(); } - if ((HEAP32[$233 + 12 >> 2] | 0) == ($16 | 0)) { - break; - } - _abort(); + } while (0); + if (($236 | 0) == ($233 | 0)) { + HEAP32[20] = HEAP32[20] & (1 << ($194 >>> 3) ^ -1); + HEAP32[sp + 688 >> 2] = 1; + break OL; } - } while (0); - if (($236 | 0) == ($233 | 0)) { - HEAP32[20] = HEAP32[20] & (1 << ($194 >>> 3) ^ -1); - HEAP32[sp + 640 >> 2] = 1; - break OL; - } - do { - if (($236 | 0) == (120 + ($194 >>> 3 << 1 << 2) | 0 | 0)) { - $_pre_phi305 = $236 + 8 | 0; - } else { - if ($236 >>> 0 < (HEAP32[24] | 0) >>> 0) { - _abort(); - } - if ((HEAP32[($236 + 8 | 0) >> 2] | 0) == ($16 | 0)) { + do { + if (($236 | 0) == (120 + ($194 >>> 3 << 1 << 2) | 0 | 0)) { $_pre_phi305 = $236 + 8 | 0; - break; - } - _abort(); - } - } while (0); - HEAP32[$233 + 12 >> 2] = $236; - HEAP32[$_pre_phi305 >> 2] = $233; - } else { - $267 = $mem + (($10 & -8) - 8) | 0; - $270 = HEAP32[$mem + (($10 & -8) + 16) >> 2] | 0; - $273 = HEAP32[$mem + ($10 & -8 | 4) >> 2] | 0; - do { - if (($273 | 0) == ($267 | 0)) { - $294 = HEAP32[($mem + (($10 & -8) + 12) | 0) >> 2] | 0; - if (($294 | 0) == 0) { - $299 = HEAP32[($mem + (($10 & -8) + 8) | 0) >> 2] | 0; - if (($299 | 0) == 0) { - $R7_1 = 0; - break; - } else { - $R7_0 = $299; - $RP9_0 = $mem + (($10 & -8) + 8) | 0; - } } else { - $R7_0 = $294; - $RP9_0 = $mem + (($10 & -8) + 12) | 0; - } - while (1) { - $301 = $R7_0 + 20 | 0; - $302 = HEAP32[$301 >> 2] | 0; - if (($302 | 0) != 0) { - $R7_0 = $302; - $RP9_0 = $301; - continue; + if ($236 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); } - $305 = $R7_0 + 16 | 0; - $306 = HEAP32[$305 >> 2] | 0; - if (($306 | 0) == 0) { + if ((HEAP32[($236 + 8 | 0) >> 2] | 0) == ($16 | 0)) { + $_pre_phi305 = $236 + 8 | 0; break; - } else { - $R7_0 = $306; - $RP9_0 = $305; } - } - if ($RP9_0 >>> 0 < (HEAP32[24] | 0) >>> 0) { _abort(); - } else { - HEAP32[$RP9_0 >> 2] = 0; - $R7_1 = $R7_0; - break; } - } else { - $278 = HEAP32[$mem + ($10 & -8) >> 2] | 0; - if ($278 >>> 0 < (HEAP32[24] | 0) >>> 0) { - _abort(); + } while (0); + HEAP32[$233 + 12 >> 2] = $236; + HEAP32[$_pre_phi305 >> 2] = $233; + } else { + helper$3 = 1; + } + } + if (helper$3) { + helper$3 = 0; + if (1) { + $267 = $mem + (($10 & -8) - 8) | 0; + $270 = HEAP32[$mem + (($10 & -8) + 16) >> 2] | 0; + $273 = HEAP32[$mem + ($10 & -8 | 4) >> 2] | 0; + do { + helper$4 = 1; + if (helper$4) { + helper$4 = 0; + if (($273 | 0) == ($267 | 0)) { + $294 = HEAP32[($mem + (($10 & -8) + 12) | 0) >> 2] | 0; + if (($294 | 0) == 0) { + $299 = HEAP32[($mem + (($10 & -8) + 8) | 0) >> 2] | 0; + if (($299 | 0) == 0) { + $R7_1 = 0; + break; + } else { + $R7_0 = $299; + $RP9_0 = $mem + (($10 & -8) + 8) | 0; + } + } else { + $R7_0 = $294; + $RP9_0 = $mem + (($10 & -8) + 12) | 0; + } + while (1) { + $301 = $R7_0 + 20 | 0; + $302 = HEAP32[$301 >> 2] | 0; + if (($302 | 0) != 0) { + $R7_0 = $302; + $RP9_0 = $301; + continue; + } + $305 = $R7_0 + 16 | 0; + $306 = HEAP32[$305 >> 2] | 0; + if (($306 | 0) == 0) { + break; + } else { + $R7_0 = $306; + $RP9_0 = $305; + } + } + if ($RP9_0 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$RP9_0 >> 2] = 0; + $R7_1 = $R7_0; + break; + } + } else { + helper$4 = 1; + } } - if ((HEAP32[($278 + 12 | 0) >> 2] | 0) != ($267 | 0)) { - _abort(); + if (helper$4) { + helper$4 = 0; + if (1) { + $278 = HEAP32[$mem + ($10 & -8) >> 2] | 0; + if ($278 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + if ((HEAP32[($278 + 12 | 0) >> 2] | 0) != ($267 | 0)) { + _abort(); + } + if ((HEAP32[($273 + 8 | 0) >> 2] | 0) == ($267 | 0)) { + HEAP32[($278 + 12 | 0) >> 2] = $273; + HEAP32[($273 + 8 | 0) >> 2] = $278; + $R7_1 = $273; + break; + } else { + _abort(); + } + } else { + helper$4 = 1; + } } - if ((HEAP32[($273 + 8 | 0) >> 2] | 0) == ($267 | 0)) { - HEAP32[($278 + 12 | 0) >> 2] = $273; - HEAP32[($273 + 8 | 0) >> 2] = $278; - $R7_1 = $273; - break; + } while (0); + if (($270 | 0) == 0) { + HEAP32[sp + 688 >> 2] = 1; + break OL; + } + $320 = 384 + (HEAP32[($mem + (($10 & -8) + 20) | 0) >> 2] << 2) | 0; + do { + if (($267 | 0) == (HEAP32[$320 >> 2] | 0)) { + HEAP32[$320 >> 2] = $R7_1; + if (($R7_1 | 0) != 0) { + break; + } + HEAP32[21] = HEAP32[21] & (1 << HEAP32[($mem + (($10 & -8) + 20) | 0) >> 2] ^ -1); + HEAP32[sp + 688 >> 2] = 2; + HEAP32[sp + 692 >> 2] = 2; + break OL; } else { - _abort(); + if ($270 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } + if ((HEAP32[($270 + 16 | 0) >> 2] | 0) == ($267 | 0)) { + HEAP32[($270 + 16 | 0) >> 2] = $R7_1; + } else { + HEAP32[$270 + 20 >> 2] = $R7_1; + } + if (($R7_1 | 0) == 0) { + HEAP32[sp + 688 >> 2] = 2; + HEAP32[sp + 692 >> 2] = 2; + break OL; + } } + } while (0); + if ($R7_1 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); } - } while (0); - if (($270 | 0) == 0) { - HEAP32[sp + 640 >> 2] = 1; - break OL; - } - $320 = 384 + (HEAP32[($mem + (($10 & -8) + 20) | 0) >> 2] << 2) | 0; - do { - if (($267 | 0) == (HEAP32[$320 >> 2] | 0)) { - HEAP32[$320 >> 2] = $R7_1; - if (($R7_1 | 0) != 0) { - break; + HEAP32[$R7_1 + 24 >> 2] = $270; + $351 = HEAP32[$mem + (($10 & -8) + 8) >> 2] | 0; + do { + if (($351 | 0) != 0) { + if ($351 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$R7_1 + 16 >> 2] = $351; + HEAP32[$351 + 24 >> 2] = $R7_1; + break; + } } - HEAP32[21] = HEAP32[21] & (1 << HEAP32[($mem + (($10 & -8) + 20) | 0) >> 2] ^ -1); - HEAP32[sp + 640 >> 2] = 2; - HEAP32[sp + 644 >> 2] = 2; + } while (0); + $364 = HEAP32[$mem + (($10 & -8) + 12) >> 2] | 0; + if (($364 | 0) == 0) { + HEAP32[sp + 688 >> 2] = 1; break OL; - } else { - if ($270 >>> 0 < (HEAP32[24] | 0) >>> 0) { - _abort(); - } - if ((HEAP32[($270 + 16 | 0) >> 2] | 0) == ($267 | 0)) { - HEAP32[($270 + 16 | 0) >> 2] = $R7_1; - } else { - HEAP32[$270 + 20 >> 2] = $R7_1; - } - if (($R7_1 | 0) == 0) { - HEAP32[sp + 640 >> 2] = 2; - HEAP32[sp + 644 >> 2] = 2; - break OL; - } } - } while (0); - if ($R7_1 >>> 0 < (HEAP32[24] | 0) >>> 0) { - _abort(); - } - HEAP32[$R7_1 + 24 >> 2] = $270; - $351 = HEAP32[$mem + (($10 & -8) + 8) >> 2] | 0; - do { - if (($351 | 0) != 0) { - if ($351 >>> 0 < (HEAP32[24] | 0) >>> 0) { - _abort(); - } else { - HEAP32[$R7_1 + 16 >> 2] = $351; - HEAP32[$351 + 24 >> 2] = $R7_1; - break; - } + if ($364 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$R7_1 + 20 >> 2] = $364; + HEAP32[$364 + 24 >> 2] = $R7_1; + HEAP32[sp + 688 >> 2] = 1; + break OL; } - } while (0); - $364 = HEAP32[$mem + (($10 & -8) + 12) >> 2] | 0; - if (($364 | 0) == 0) { - HEAP32[sp + 640 >> 2] = 1; - break OL; - } - if ($364 >>> 0 < (HEAP32[24] | 0) >>> 0) { - _abort(); } else { - HEAP32[$R7_1 + 20 >> 2] = $364; - HEAP32[$364 + 24 >> 2] = $R7_1; - HEAP32[sp + 640 >> 2] = 1; - break OL; + helper$3 = 1; } } } while (0); + HEAP32[sp + 664 >> 2] = helper$3; } function _free$1(sp) { sp = sp | 0; - var $21 = 0, $37 = 0, $mem = 0, $40 = 0, $5 = 0, $25 = 0, $26 = 0, $_pre_phi307 = 0, $69 = 0, $72 = 0, $75 = 0, $95 = 0, $100 = 0, $R_1 = 0, $R_0 = 0, $RP_0 = 0, $102 = 0, $103 = 0, $106 = 0, $107 = 0, $80 = 0, $120 = 0, $151 = 0, $164 = 0, $p_0 = 0, $psize_0 = 0; + var $21 = 0, $37 = 0, $mem = 0, $40 = 0, $5 = 0, $25 = 0, $26 = 0, $_pre_phi307 = 0, $69 = 0, $72 = 0, $75 = 0, helper$1 = 0, $95 = 0, $100 = 0, $R_1 = 0, $R_0 = 0, $RP_0 = 0, $102 = 0, $103 = 0, $106 = 0, $107 = 0, $80 = 0, $120 = 0, $151 = 0, $164 = 0, $p_0 = 0, $psize_0 = 0; $mem = HEAP32[sp + 8 >> 2] | 0; $5 = HEAP32[sp + 16 >> 2] | 0; $21 = HEAP32[sp + 40 >> 2] | 0; @@ -348,7 +385,7 @@ function _free$1(sp) { HEAP32[20] = HEAP32[20] & (1 << ($21 >>> 3) ^ -1); $p_0 = $25; $psize_0 = $26; - HEAP32[sp + 648 >> 2] = 1; + HEAP32[sp + 696 >> 2] = 1; break OL; } do { @@ -369,74 +406,86 @@ function _free$1(sp) { HEAP32[$_pre_phi307 >> 2] = $37; $p_0 = $25; $psize_0 = $26; - HEAP32[sp + 648 >> 2] = 1; + HEAP32[sp + 696 >> 2] = 1; break OL; } $69 = $mem + (-8 - $21 | 0) | 0; $72 = HEAP32[$mem + ((-8 - $21 | 0) + 24) >> 2] | 0; $75 = HEAP32[$mem + ((-8 - $21 | 0) + 12) >> 2] | 0; do { - if (($75 | 0) == ($69 | 0)) { - $95 = HEAP32[($mem + ((-8 - $21 | 0) + 20) | 0) >> 2] | 0; - if (($95 | 0) == 0) { - $100 = HEAP32[($mem + ((-8 - $21 | 0) + 16) | 0) >> 2] | 0; - if (($100 | 0) == 0) { - $R_1 = 0; - break; + helper$1 = 1; + if (helper$1) { + helper$1 = 0; + if (($75 | 0) == ($69 | 0)) { + $95 = HEAP32[($mem + ((-8 - $21 | 0) + 20) | 0) >> 2] | 0; + if (($95 | 0) == 0) { + $100 = HEAP32[($mem + ((-8 - $21 | 0) + 16) | 0) >> 2] | 0; + if (($100 | 0) == 0) { + $R_1 = 0; + break; + } else { + $R_0 = $100; + $RP_0 = $mem + ((-8 - $21 | 0) + 16) | 0; + } + } else { + $R_0 = $95; + $RP_0 = $mem + ((-8 - $21 | 0) + 20) | 0; + } + while (1) { + $102 = $R_0 + 20 | 0; + $103 = HEAP32[$102 >> 2] | 0; + if (($103 | 0) != 0) { + $R_0 = $103; + $RP_0 = $102; + continue; + } + $106 = $R_0 + 16 | 0; + $107 = HEAP32[$106 >> 2] | 0; + if (($107 | 0) == 0) { + break; + } else { + $R_0 = $107; + $RP_0 = $106; + } + } + if ($RP_0 >>> 0 < $5 >>> 0) { + _abort(); } else { - $R_0 = $100; - $RP_0 = $mem + ((-8 - $21 | 0) + 16) | 0; + HEAP32[$RP_0 >> 2] = 0; + $R_1 = $R_0; + break; } } else { - $R_0 = $95; - $RP_0 = $mem + ((-8 - $21 | 0) + 20) | 0; + helper$1 = 1; } - while (1) { - $102 = $R_0 + 20 | 0; - $103 = HEAP32[$102 >> 2] | 0; - if (($103 | 0) != 0) { - $R_0 = $103; - $RP_0 = $102; - continue; + } + if (helper$1) { + helper$1 = 0; + if (1) { + $80 = HEAP32[$mem + ((-8 - $21 | 0) + 8) >> 2] | 0; + if ($80 >>> 0 < $5 >>> 0) { + _abort(); + } + if ((HEAP32[($80 + 12 | 0) >> 2] | 0) != ($69 | 0)) { + _abort(); } - $106 = $R_0 + 16 | 0; - $107 = HEAP32[$106 >> 2] | 0; - if (($107 | 0) == 0) { + if ((HEAP32[($75 + 8 | 0) >> 2] | 0) == ($69 | 0)) { + HEAP32[($80 + 12 | 0) >> 2] = $75; + HEAP32[($75 + 8 | 0) >> 2] = $80; + $R_1 = $75; break; } else { - $R_0 = $107; - $RP_0 = $106; + _abort(); } - } - if ($RP_0 >>> 0 < $5 >>> 0) { - _abort(); } else { - HEAP32[$RP_0 >> 2] = 0; - $R_1 = $R_0; - break; - } - } else { - $80 = HEAP32[$mem + ((-8 - $21 | 0) + 8) >> 2] | 0; - if ($80 >>> 0 < $5 >>> 0) { - _abort(); - } - if ((HEAP32[($80 + 12 | 0) >> 2] | 0) != ($69 | 0)) { - _abort(); - } - if ((HEAP32[($75 + 8 | 0) >> 2] | 0) == ($69 | 0)) { - HEAP32[($80 + 12 | 0) >> 2] = $75; - HEAP32[($75 + 8 | 0) >> 2] = $80; - $R_1 = $75; - break; - } else { - _abort(); + helper$1 = 1; } } } while (0); if (($72 | 0) == 0) { $p_0 = $25; $psize_0 = $26; - HEAP32[sp + 648 >> 2] = 1; + HEAP32[sp + 696 >> 2] = 1; break OL; } $120 = 384 + (HEAP32[($mem + ((-8 - $21 | 0) + 28) | 0) >> 2] << 2) | 0; @@ -449,8 +498,8 @@ function _free$1(sp) { HEAP32[21] = HEAP32[21] & (1 << HEAP32[($mem + ((-8 - $21 | 0) + 28) | 0) >> 2] ^ -1); $p_0 = $25; $psize_0 = $26; - HEAP32[sp + 648 >> 2] = 2; - HEAP32[sp + 652 >> 2] = 2; + HEAP32[sp + 696 >> 2] = 2; + HEAP32[sp + 700 >> 2] = 2; break OL; } else { if ($72 >>> 0 < (HEAP32[24] | 0) >>> 0) { @@ -464,8 +513,8 @@ function _free$1(sp) { if (($R_1 | 0) == 0) { $p_0 = $25; $psize_0 = $26; - HEAP32[sp + 648 >> 2] = 2; - HEAP32[sp + 652 >> 2] = 2; + HEAP32[sp + 696 >> 2] = 2; + HEAP32[sp + 700 >> 2] = 2; break OL; } } @@ -490,7 +539,7 @@ function _free$1(sp) { if (($164 | 0) == 0) { $p_0 = $25; $psize_0 = $26; - HEAP32[sp + 648 >> 2] = 1; + HEAP32[sp + 696 >> 2] = 1; break OL; } if ($164 >>> 0 < (HEAP32[24] | 0) >>> 0) { @@ -500,7 +549,7 @@ function _free$1(sp) { HEAP32[$164 + 24 >> 2] = $R_1; $p_0 = $25; $psize_0 = $26; - HEAP32[sp + 648 >> 2] = 1; + HEAP32[sp + 696 >> 2] = 1; break OL; } } while (0); @@ -509,7 +558,7 @@ function _free$1(sp) { } function _free$2(sp) { sp = sp | 0; - var $194 = 0, $16 = 0, $204 = 0, $psize_0 = 0, $p_0 = 0, $220 = 0, $189 = 0, $227 = 0, $mem = 0, $10 = 0, $psize_1 = 0, $390 = 0, $396 = 0, $F16_0 = 0, $_pre_phi = 0, $404 = 0, $414 = 0, $415 = 0, $I18_0 = 0, $428 = 0, $436 = 0, $443 = 0, $447 = 0, $448 = 0, $463 = 0, $K19_0 = 0, $T_0 = 0, $472 = 0, $473 = 0, label = 0, $486 = 0, $487 = 0, $489 = 0, $501 = 0, $sp_0_in_i = 0, $sp_0_i = 0; + var helper$2 = 0, $194 = 0, $16 = 0, $204 = 0, $psize_0 = 0, $p_0 = 0, $220 = 0, $189 = 0, $227 = 0, helper$3 = 0, $mem = 0, $10 = 0, $psize_1 = 0, $390 = 0, $396 = 0, $F16_0 = 0, $_pre_phi = 0, $404 = 0, $414 = 0, $415 = 0, $I18_0 = 0, $428 = 0, $436 = 0, $443 = 0, $447 = 0, $448 = 0, helper$5 = 0, $463 = 0, $K19_0 = 0, $T_0 = 0, $472 = 0, $473 = 0, label = 0, $486 = 0, $487 = 0, $489 = 0, $501 = 0, $sp_0_in_i = 0, $sp_0_i = 0; $mem = HEAP32[sp + 8 >> 2] | 0; $10 = HEAP32[sp + 24 >> 2] | 0; $16 = HEAP32[sp + 32 >> 2] | 0; @@ -519,73 +568,88 @@ function _free$2(sp) { $194 = HEAP32[sp + 240 >> 2] | 0; OL : do { do { - if (($194 & 2 | 0) == 0) { - if (($16 | 0) == (HEAP32[26] | 0)) { - $204 = (HEAP32[23] | 0) + $psize_0 | 0; - HEAP32[23] = $204; - HEAP32[26] = $p_0; - HEAP32[$p_0 + 4 >> 2] = $204 | 1; - if (($p_0 | 0) == (HEAP32[25] | 0)) { - HEAP32[25] = 0; - HEAP32[22] = 0; - } - if ($204 >>> 0 <= (HEAP32[27] | 0) >>> 0) { - HEAP32[sp + 656 >> 2] = 5; + helper$2 = 1; + if (helper$2) { + helper$2 = 0; + if (($194 & 2 | 0) == 0) { + if (($16 | 0) == (HEAP32[26] | 0)) { + $204 = (HEAP32[23] | 0) + $psize_0 | 0; + HEAP32[23] = $204; + HEAP32[26] = $p_0; + HEAP32[$p_0 + 4 >> 2] = $204 | 1; + if (($p_0 | 0) == (HEAP32[25] | 0)) { + HEAP32[25] = 0; + HEAP32[22] = 0; + } + if ($204 >>> 0 <= (HEAP32[27] | 0) >>> 0) { + HEAP32[sp + 704 >> 2] = 5; + break OL; + } + _sys_trim(0) | 0; + HEAP32[sp + 704 >> 2] = 5; break OL; } - _sys_trim(0) | 0; - HEAP32[sp + 656 >> 2] = 5; - break OL; - } - if (($16 | 0) == (HEAP32[25] | 0)) { - $220 = (HEAP32[22] | 0) + $psize_0 | 0; - HEAP32[22] = $220; - HEAP32[25] = $p_0; - HEAP32[$p_0 + 4 >> 2] = $220 | 1; - HEAP32[$189 + $220 >> 2] = $220; - HEAP32[sp + 656 >> 2] = 5; - break OL; - } - $227 = ($194 & -8) + $psize_0 | 0; - L726 : do { - HEAP32[sp + 8 >> 2] = $mem; - HEAP32[sp + 24 >> 2] = $10; - HEAP32[sp + 32 >> 2] = $16; - HEAP32[sp + 240 >> 2] = $194; - HEAP32[sp + 640 >> 2] = 0; - HEAP32[sp + 644 >> 2] = 0; - _free$0(sp); - tempValue = HEAP32[sp + 640 >> 2] | 0; - tempInt = HEAP32[sp + 644 >> 2] | 0; - tempDouble = +HEAPF32[sp + 644 >> 2]; - HEAP32[sp + 640 >> 2] = 0; - HEAP32[sp + 644 >> 2] = 0; - if ((tempValue | 0) == 1) { - break; + if (($16 | 0) == (HEAP32[25] | 0)) { + $220 = (HEAP32[22] | 0) + $psize_0 | 0; + HEAP32[22] = $220; + HEAP32[25] = $p_0; + HEAP32[$p_0 + 4 >> 2] = $220 | 1; + HEAP32[$189 + $220 >> 2] = $220; + HEAP32[sp + 704 >> 2] = 5; + break OL; } - if ((tempValue | 0) == 2) { - switch (tempInt | 0) { - case 2: - { - break L726; + $227 = ($194 & -8) + $psize_0 | 0; + L726 : do { + helper$3 = 1; + HEAP32[sp + 8 >> 2] = $mem; + HEAP32[sp + 24 >> 2] = $10; + HEAP32[sp + 32 >> 2] = $16; + HEAP32[sp + 240 >> 2] = $194; + HEAP32[sp + 664 >> 2] = helper$3; + HEAP32[sp + 688 >> 2] = 0; + HEAP32[sp + 692 >> 2] = 0; + _free$0(sp); + helper$3 = HEAP32[sp + 664 >> 2] | 0; + tempValue = HEAP32[sp + 688 >> 2] | 0; + tempInt = HEAP32[sp + 692 >> 2] | 0; + tempDouble = +HEAPF32[sp + 692 >> 2]; + HEAP32[sp + 688 >> 2] = 0; + HEAP32[sp + 692 >> 2] = 0; + if ((tempValue | 0) == 1) { + break; + } + if ((tempValue | 0) == 2) { + switch (tempInt | 0) { + case 2: + { + break L726; + } } } + } while (0); + HEAP32[$p_0 + 4 >> 2] = $227 | 1; + HEAP32[$189 + $227 >> 2] = $227; + if (($p_0 | 0) != (HEAP32[25] | 0)) { + $psize_1 = $227; + break; } - } while (0); - HEAP32[$p_0 + 4 >> 2] = $227 | 1; - HEAP32[$189 + $227 >> 2] = $227; - if (($p_0 | 0) != (HEAP32[25] | 0)) { - $psize_1 = $227; - break; + HEAP32[22] = $227; + HEAP32[sp + 704 >> 2] = 5; + break OL; + } else { + helper$2 = 1; + } + } + if (helper$2) { + helper$2 = 0; + if (1) { + HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] = $194 & -2; + HEAP32[$p_0 + 4 >> 2] = $psize_0 | 1; + HEAP32[$189 + $psize_0 >> 2] = $psize_0; + $psize_1 = $psize_0; + } else { + helper$2 = 1; } - HEAP32[22] = $227; - HEAP32[sp + 656 >> 2] = 5; - break OL; - } else { - HEAP32[($mem + (($10 & -8) - 4) | 0) >> 2] = $194 & -2; - HEAP32[$p_0 + 4 >> 2] = $psize_0 | 1; - HEAP32[$189 + $psize_0 >> 2] = $psize_0; - $psize_1 = $psize_0; } } while (0); $390 = $psize_1 >>> 3; @@ -610,7 +674,7 @@ function _free$2(sp) { HEAP32[$F16_0 + 12 >> 2] = $p_0; HEAP32[$p_0 + 8 >> 2] = $F16_0; HEAP32[$p_0 + 12 >> 2] = 120 + ($390 << 1 << 2) | 0; - HEAP32[sp + 656 >> 2] = 5; + HEAP32[sp + 704 >> 2] = 5; break OL; } $414 = $p_0; @@ -635,60 +699,72 @@ function _free$2(sp) { $447 = HEAP32[21] | 0; $448 = 1 << $I18_0; do { - if (($447 & $448 | 0) == 0) { - HEAP32[21] = $447 | $448; - HEAP32[$443 >> 2] = $414; - HEAP32[$p_0 + 24 >> 2] = $443; - HEAP32[$p_0 + 12 >> 2] = $p_0; - HEAP32[$p_0 + 8 >> 2] = $p_0; - } else { - if (($I18_0 | 0) == 31) { - $463 = 0; + helper$5 = 1; + if (helper$5) { + helper$5 = 0; + if (($447 & $448 | 0) == 0) { + HEAP32[21] = $447 | $448; + HEAP32[$443 >> 2] = $414; + HEAP32[$p_0 + 24 >> 2] = $443; + HEAP32[$p_0 + 12 >> 2] = $p_0; + HEAP32[$p_0 + 8 >> 2] = $p_0; } else { - $463 = 25 - ($I18_0 >>> 1) | 0; + helper$5 = 1; } - $K19_0 = $psize_1 << $463; - $T_0 = HEAP32[$443 >> 2] | 0; - while (1) { - if ((HEAP32[$T_0 + 4 >> 2] & -8 | 0) == ($psize_1 | 0)) { - break; - } - $472 = $T_0 + 16 + ($K19_0 >>> 31 << 2) | 0; - $473 = HEAP32[$472 >> 2] | 0; - if (($473 | 0) == 0) { - label = 569; - break; + } + if (helper$5) { + helper$5 = 0; + if (1) { + if (($I18_0 | 0) == 31) { + $463 = 0; } else { - $K19_0 = $K19_0 << 1; - $T_0 = $473; + $463 = 25 - ($I18_0 >>> 1) | 0; } - } - if ((label | 0) == 569) { - if ($472 >>> 0 < (HEAP32[24] | 0) >>> 0) { + $K19_0 = $psize_1 << $463; + $T_0 = HEAP32[$443 >> 2] | 0; + while (1) { + if ((HEAP32[$T_0 + 4 >> 2] & -8 | 0) == ($psize_1 | 0)) { + break; + } + $472 = $T_0 + 16 + ($K19_0 >>> 31 << 2) | 0; + $473 = HEAP32[$472 >> 2] | 0; + if (($473 | 0) == 0) { + label = 569; + break; + } else { + $K19_0 = $K19_0 << 1; + $T_0 = $473; + } + } + if ((label | 0) == 569) { + if ($472 >>> 0 < (HEAP32[24] | 0) >>> 0) { + _abort(); + } else { + HEAP32[$472 >> 2] = $414; + HEAP32[$p_0 + 24 >> 2] = $T_0; + HEAP32[$p_0 + 12 >> 2] = $p_0; + HEAP32[$p_0 + 8 >> 2] = $p_0; + break; + } + } + $486 = $T_0 + 8 | 0; + $487 = HEAP32[$486 >> 2] | 0; + $489 = HEAP32[24] | 0; + if ($T_0 >>> 0 < $489 >>> 0) { + _abort(); + } + if ($487 >>> 0 < $489 >>> 0) { _abort(); } else { - HEAP32[$472 >> 2] = $414; - HEAP32[$p_0 + 24 >> 2] = $T_0; - HEAP32[$p_0 + 12 >> 2] = $p_0; - HEAP32[$p_0 + 8 >> 2] = $p_0; + HEAP32[$487 + 12 >> 2] = $414; + HEAP32[$486 >> 2] = $414; + HEAP32[$p_0 + 8 >> 2] = $487; + HEAP32[$p_0 + 12 >> 2] = $T_0; + HEAP32[$p_0 + 24 >> 2] = 0; break; } - } - $486 = $T_0 + 8 | 0; - $487 = HEAP32[$486 >> 2] | 0; - $489 = HEAP32[24] | 0; - if ($T_0 >>> 0 < $489 >>> 0) { - _abort(); - } - if ($487 >>> 0 < $489 >>> 0) { - _abort(); } else { - HEAP32[$487 + 12 >> 2] = $414; - HEAP32[$486 >> 2] = $414; - HEAP32[$p_0 + 8 >> 2] = $487; - HEAP32[$p_0 + 12 >> 2] = $T_0; - HEAP32[$p_0 + 24 >> 2] = 0; - break; + helper$5 = 1; } } } while (0); @@ -697,7 +773,7 @@ function _free$2(sp) { if (($501 | 0) == 0) { $sp_0_in_i = 536; } else { - HEAP32[sp + 656 >> 2] = 5; + HEAP32[sp + 704 >> 2] = 5; break OL; } while (1) { @@ -710,7 +786,7 @@ function _free$2(sp) { } HEAP32[28] = -1; STACKTOP = sp; - HEAP32[sp + 656 >> 2] = 5; + HEAP32[sp + 704 >> 2] = 5; break OL; } while (0); } |