diff options
-rw-r--r-- | AUTHORS | 3 | ||||
-rw-r--r-- | docs/paper.pdf | bin | 220318 -> 220476 bytes | |||
-rw-r--r-- | docs/paper.tex | 10 | ||||
-rwxr-xr-x | emcc | 4 | ||||
-rw-r--r-- | src/analyzer.js | 78 | ||||
-rw-r--r-- | src/compiler.js | 2 | ||||
-rw-r--r-- | src/library.js | 133 | ||||
-rw-r--r-- | src/library_browser.js | 41 | ||||
-rw-r--r-- | src/library_gl.js | 52 | ||||
-rw-r--r-- | src/library_glfw.js | 29 | ||||
-rw-r--r-- | src/library_glut.js | 41 | ||||
-rw-r--r-- | src/library_sdl.js | 106 | ||||
-rw-r--r-- | src/modules.js | 2 | ||||
-rw-r--r-- | src/parseTools.js | 8 | ||||
-rw-r--r-- | src/settings.js | 6 | ||||
-rw-r--r-- | tests/box2d/Benchmark.cpp | 2 | ||||
-rw-r--r-- | tests/cases/trace.ll | 2 | ||||
-rw-r--r-- | tests/nbody-java/nbody_nbody.c | 16 | ||||
-rwxr-xr-x | tests/runner.py | 135 | ||||
-rw-r--r-- | tools/eliminator/asm-eliminator-test-output.js | 243 | ||||
-rw-r--r-- | tools/eliminator/asm-eliminator-test.js | 429 | ||||
-rw-r--r-- | tools/js-optimizer.js | 43 | ||||
-rw-r--r-- | tools/shared.py | 4 |
23 files changed, 1156 insertions, 233 deletions
@@ -72,5 +72,8 @@ a license to everyone to use it as detailed in LICENSE.) * Robert Bragg <robert.bragg@intel.com> (copyright owned by Intel Corporation) * Sylvestre Ledru <sylvestre@debian.org> * Tom Fairfield <fairfield@cs.xu.edu> +* Anthony J. Thibault <ajt@hyperlogic.org> +* John Allwine <jallwine86@gmail.com> +* Martin Gerhardy <martin.gerhardy@gmail.com> diff --git a/docs/paper.pdf b/docs/paper.pdf Binary files differindex 401162ac..fc8ecf7c 100644 --- a/docs/paper.pdf +++ b/docs/paper.pdf diff --git a/docs/paper.tex b/docs/paper.tex index 3b8da618..9e460bac 100644 --- a/docs/paper.tex +++ b/docs/paper.tex @@ -214,7 +214,7 @@ following simple example of a C program: int main() { int sum = 0; - for (int i = 1; i < 100; i++) + for (int i = 1; i <= 100; i++) sum += i; printf("1+...+100=%d\n", sum); return 0; @@ -239,7 +239,7 @@ define i32 @main() { ; <label>:2 %3 = load i32* %i, align 4 - %4 = icmp slt i32 %3, 100 + %4 = icmp sle i32 %3, 100 br i1 %4, label %5, label %12 ; <label>:5 @@ -314,7 +314,7 @@ function _main() { __label__ = 0; break; case 0: var $3 = HEAP[$i]; - var $4 = $3 < 100; + var $4 = $3 <= 100; if ($4) { __label__ = 1; break; } else { __label__ = 2; break; } case 1: @@ -594,7 +594,7 @@ function _main() { $i = 0; $2$2: while(1) { var $3 = $i; - var $4 = $3 < 100; + var $4 = $3 <= 100; if (!($4)) { __label__ = 2; break $2$2; } var $6 = $i; var $7 = $sum; @@ -616,7 +616,7 @@ function K() { var a, b; b = a = 0; a:for(;;) { - if(!(b < 100)) { + if(!(b <= 100)) { break a } a += b; @@ -167,6 +167,7 @@ Options that are modified or new in %s include: -O3 As -O2, plus dangerous optimizations that may break the generated code! This adds + -s FORCE_ALIGNED_MEMORY=1 -s DOUBLE_MODE=0 -s PRECISE_I64_MATH=0 --closure 1 @@ -174,7 +175,8 @@ Options that are modified or new in %s include: This is not recommended at all. A better idea is to try each of these separately on top of - -O2 to see what works. See the wiki for more + -O2 to see what works. See the wiki and + src/settings.js (for the -s options) for more information. -s OPTION=VALUE JavaScript code generation option passed diff --git a/src/analyzer.js b/src/analyzer.js index 3f9025da..a131406c 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -20,6 +20,7 @@ var BRANCH_INVOKE = set('branch', 'invoke'); var LABEL_ENDERS = set('branch', 'return', 'switch'); var SIDE_EFFECT_CAUSERS = set('call', 'invoke', 'atomic'); var UNUNFOLDABLE = set('value', 'structvalue', 'type', 'phiparam'); +var I64_DOUBLE_FLIP = { i64: 'double', double: 'i64' }; // Analyzer @@ -103,61 +104,81 @@ function analyzer(data, sidePass) { } }); - // CastAway - try to remove bitcasts of double to i64, which LLVM sometimes generates unnecessarily + // CastAway - try to remove bitcasts of double<-->i64, which LLVM sometimes generates unnecessarily // (load a double, convert to i64, use as i64). - // We optimize this by checking if the value is later converted to an i64. If so we create a shadow - // variable that is a load of an i64, and use that in those places. (As SSA, this is valid, and + // We optimize this by checking if there are such bitcasts. If so we create a shadow + // variable that is of the other type, and use that in the relevant places. (As SSA, this is valid, and // variable elimination later will remove the double load if it is no longer needed.) // + // Note that aside from being an optimization, this is needed for correctness in some cases: If code + // assumes it can bitcast a double to an i64 and back and forth without loss, that may be violated + // due to NaN canonicalization. substrate.addActor('CastAway', { processItem: function(item) { this.forwardItem(item, 'Legalizer'); if (USE_TYPED_ARRAYS != 2) return; item.functions.forEach(function(func) { - var changed = false; + var has = false; + func.labels.forEach(function(label) { + var lines = label.lines; + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + if (line.intertype == 'bitcast' && line.type in I64_DOUBLE_FLIP) { + has = true; + } + } + }); + if (!has) return; + // there are i64<-->double bitcasts, create shadows for everything + var shadowed = {}; func.labels.forEach(function(label) { - var doubleVars = {}; var lines = label.lines; var i = 0; while (i < lines.length) { + var lines = label.lines; var line = lines[i]; - if (line.intertype == 'load' && line.type == 'double') { - doubleVars[line.assignTo] = i; - } else if (line.intertype == 'bitcast' && line.type == 'i64' && line.ident in doubleVars) { - // this is a bitcast of a loaded double into an i64. create shadow var - var shadow = line.ident + '$$i64doubleSHADOW'; - var loadI = doubleVars[line.ident]; - var load = lines[loadI]; - if (load.pointer.intertype != 'value') { i++; continue } // TODO - // create shadow - lines.splice(loadI + 1, 0, { // this element will be legalized in the next phase + if (line.intertype == 'load' && line.type in I64_DOUBLE_FLIP) { + if (line.pointer.intertype != 'value') { i++; continue } // TODO + shadowed[line.assignTo] = 1; + var shadow = line.assignTo + '$$SHADOW'; + var flip = I64_DOUBLE_FLIP[line.type]; + lines.splice(i + 1, 0, { // if necessary this element will be legalized in the next phase tokens: null, indent: 2, - lineNum: load.lineNum + 0.5, + lineNum: line.lineNum + 0.5, assignTo: shadow, intertype: 'load', - pointerType: 'i64*', - type: 'i64', - valueType: 'i64', + pointerType: flip + '*', + type: flip, + valueType: flip, pointer: { intertype: 'value', - ident: load.pointer.ident, - type: 'i64*' + ident: line.pointer.ident, + type: flip + '*' }, - align: load.align, - ident: load.ident + align: line.align, + ident: line.ident }); - // use shadow - line.params[0].ident = shadow; - line.params[0].type = 'i64'; - line.type2 = 'i64'; // note: no need to update func.lines, it is generated in a later pass i++; } i++; } }); + // use shadows where possible + func.labels.forEach(function(label) { + var lines = label.lines; + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + if (line.intertype == 'bitcast' && line.type in I64_DOUBLE_FLIP && line.ident in shadowed) { + var shadow = line.ident + '$$SHADOW'; + line.params[0].ident = shadow; + line.params[0].type = line.type; + line.type2 = line.type; + } + } + }); }); } }); @@ -233,12 +254,15 @@ function analyzer(data, sidePass) { var factor = (next - prev)/(4*toAdd.length+3); for (var k = 0; k < toAdd.length; k++) { toAdd[k].lineNum = prev + ((k+1)*factor); + assert(k == 0 || toAdd[k].lineNum > toAdd[k-1].lineNum); } } function removeAndAdd(lines, i, toAdd) { var item = lines[i]; interpLines(lines, i, toAdd); Array.prototype.splice.apply(lines, [i, 1].concat(toAdd)); + if (i > 0) assert(lines[i].lineNum > lines[i-1].lineNum); + if (i + toAdd.length < lines.length) assert(lines[i + toAdd.length - 1].lineNum < lines[i + toAdd.length].lineNum); return toAdd.length; } function legalizeFunctionParameters(params) { diff --git a/src/compiler.js b/src/compiler.js index 8b9606f1..94e77e26 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -183,8 +183,8 @@ 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(!(!NAMED_GLOBALS && BUILD_AS_SHARED_LIB)); // shared libraries must have named globals assert(!BUILD_AS_SHARED_LIB, 'shared libs are deprecated'); +//assert(!(!NAMED_GLOBALS && BUILD_AS_SHARED_LIB), 'shared libraries must have named globals'); // Output some info and warnings based on settings diff --git a/src/library.js b/src/library.js index cfe83c6e..84071b68 100644 --- a/src/library.js +++ b/src/library.js @@ -296,74 +296,97 @@ LibraryManager.library = { if (typeof XMLHttpRequest !== 'undefined') { if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'; // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse. - var LazyUint8Array = function(chunkSize, length) { - this.length = length; - this.chunkSize = chunkSize; + var LazyUint8Array = function() { + this.lengthKnown = false; this.chunks = []; // Loaded chunks. Index is the chunk number } LazyUint8Array.prototype.get = function(idx) { if (idx > this.length-1 || idx < 0) { return undefined; } - var chunkOffset = idx % chunkSize; - var chunkNum = Math.floor(idx / chunkSize); + var chunkOffset = idx % this.chunkSize; + var chunkNum = Math.floor(idx / this.chunkSize); return this.getter(chunkNum)[chunkOffset]; } LazyUint8Array.prototype.setDataGetter = function(getter) { this.getter = getter; } - - // Find length - var xhr = new XMLHttpRequest(); - xhr.open('HEAD', url, false); - xhr.send(null); - if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); - var datalength = Number(xhr.getResponseHeader("Content-length")); - var header; - var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes"; + + LazyUint8Array.prototype.cacheLength = function() { + // Find length + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', url, false); + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + var datalength = Number(xhr.getResponseHeader("Content-length")); + var header; + var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes"; #if SMALL_XHR_CHUNKS - var chunkSize = 1024; // Chunk size in bytes + var chunkSize = 1024; // Chunk size in bytes #else - var chunkSize = 1024*1024; // Chunk size in bytes + var chunkSize = 1024*1024; // Chunk size in bytes #endif - if (!hasByteServing) chunkSize = datalength; - - // Function to get a range from the remote URL. - var doXHR = (function(from, to) { - if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); - if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); - - // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. - var xhr = new XMLHttpRequest(); - xhr.open('GET', url, false); - if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); - - // Some hints to the browser that we want binary data. - if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer'; - if (xhr.overrideMimeType) { - xhr.overrideMimeType('text/plain; charset=x-user-defined'); - } + if (!hasByteServing) chunkSize = datalength; + + // Function to get a range from the remote URL. + var doXHR = (function(from, to) { + if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); + if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); + + // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + + // Some hints to the browser that we want binary data. + if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer'; + if (xhr.overrideMimeType) { + xhr.overrideMimeType('text/plain; charset=x-user-defined'); + } + + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + if (xhr.response !== undefined) { + return new Uint8Array(xhr.response || []); + } else { + return intArrayFromString(xhr.responseText || '', true); + } + }); + var lazyArray = this; + lazyArray.setDataGetter(function(chunkNum) { + var start = chunkNum * chunkSize; + var end = (chunkNum+1) * chunkSize - 1; // including this byte + end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") { + lazyArray.chunks[chunkNum] = doXHR(start, end); + } + if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!"); + return lazyArray.chunks[chunkNum]; + }); + + this._length = datalength; + this._chunkSize = chunkSize; + this.lengthKnown = true; + } - xhr.send(null); - if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); - if (xhr.response !== undefined) { - return new Uint8Array(xhr.response || []); - } else { - return intArrayFromString(xhr.responseText || '', true); - } + var lazyArray = new LazyUint8Array(); + Object.defineProperty(lazyArray, "length", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._length; + } }); - - var lazyArray = new LazyUint8Array(chunkSize, datalength); - lazyArray.setDataGetter(function(chunkNum) { - var start = chunkNum * lazyArray.chunkSize; - var end = (chunkNum+1) * lazyArray.chunkSize - 1; // including this byte - end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block - if (typeof(lazyArray.chunks[chunkNum]) === "undefined") { - lazyArray.chunks[chunkNum] = doXHR(start, end); - } - if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!"); - return lazyArray.chunks[chunkNum]; + Object.defineProperty(lazyArray, "chunkSize", { + get: function() { + if(!this.lengthKnown) { + this.cacheLength(); + } + return this._chunkSize; + } }); + var properties = { isDevice: false, contents: lazyArray }; } else { var properties = { isDevice: false, url: url }; @@ -2465,9 +2488,15 @@ LibraryManager.library = { __scanString.whiteSpace[{{{ charCode(' ') }}}] = 1; __scanString.whiteSpace[{{{ charCode('\t') }}}] = 1; __scanString.whiteSpace[{{{ charCode('\n') }}}] = 1; + __scanString.whiteSpace[{{{ charCode('\v') }}}] = 1; + __scanString.whiteSpace[{{{ charCode('\f') }}}] = 1; + __scanString.whiteSpace[{{{ charCode('\r') }}}] = 1; __scanString.whiteSpace[' '] = 1; __scanString.whiteSpace['\t'] = 1; __scanString.whiteSpace['\n'] = 1; + __scanString.whiteSpace['\v'] = 1; + __scanString.whiteSpace['\f'] = 1; + __scanString.whiteSpace['\r'] = 1; } // Supports %x, %4x, %d.%d, %lld, %s, %f, %lf. // TODO: Support all format specifiers. @@ -2840,7 +2869,7 @@ LibraryManager.library = { } else if (next == {{{ charCode('o') }}}) { argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8); } else if (next == {{{ charCode('x') }}} || next == {{{ charCode('X') }}}) { - prefix = flagAlternative ? '0x' : ''; + prefix = (flagAlternative && currArg != 0) ? '0x' : ''; #if PRECISE_I64_MATH if (argSize == 8 && i64Math) { if (origArg[1]) { diff --git a/src/library_browser.js b/src/library_browser.js index 85eb93f7..97233c36 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -374,6 +374,47 @@ mergeInto(LibraryManager.library, { 0; }, + mouseX: 0, + mouseY: 0, + mouseMovementX: 0, + mouseMovementY: 0, + + calculateMouseEvent: function(event) { // event should be mousemove, mousedown or mouseup + if (Browser.pointerLock) { + // When the pointer is locked, calculate the coordinates + // based on the movement of the mouse. + // Workaround for Firefox bug 764498 + if (event.type != 'mousemove' && + ('mozMovementX' in event)) { + Browser.mouseMovementX = Browser.mouseMovementY = 0; + } else { + Browser.mouseMovementX = Browser.getMovementX(event); + Browser.mouseMovementY = Browser.getMovementY(event); + } + Browser.mouseX = SDL.mouseX + Browser.mouseMovementX; + Browser.mouseY = SDL.mouseY + Browser.mouseMovementY; + } else { + // 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); + + // the canvas might be CSS-scaled compared to its backbuffer; + // SDL-using content will want mouse coordinates in terms + // of backbuffer units. + var cw = Module["canvas"].width; + var ch = Module["canvas"].height; + x = x * (cw / rect.width); + y = y * (ch / rect.height); + + Browser.mouseMovementX = x - Browser.mouseX; + Browser.mouseMovementY = y - Browser.mouseY; + Browser.mouseX = x; + Browser.mouseY = y; + } + }, + xhrLoad: function(url, onload, onerror) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); diff --git a/src/library_gl.js b/src/library_gl.js index 813da761..0f6fb670 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -339,6 +339,9 @@ var LibraryGL = { Module.ctx.getExtension('WEBKIT_EXT_texture_filter_anisotropic'); GL.floatExt = Module.ctx.getExtension('OES_texture_float'); + + GL.elementIndexUintExt = Module.ctx.getExtension('OES_element_index_uint'); + GL.standardDerivativesExt = Module.ctx.getExtension('OES_standard_derivatives'); } }, @@ -781,7 +784,7 @@ var LibraryGL = { program = GL.programs[program]; var info = Module.ctx.getActiveUniform(program, index); - var infoname = info.name.slice(0, bufSize - 1); + var infoname = info.name.slice(0, Math.max(0, bufSize - 1)); writeStringToMemory(infoname, name); if (length) { @@ -795,25 +798,25 @@ var LibraryGL = { } }, - glUniform1f__sig: 'vid', + glUniform1f__sig: 'vif', glUniform1f: function(location, v0) { location = GL.uniforms[location]; Module.ctx.uniform1f(location, v0); }, - glUniform2f__sig: 'vidd', + glUniform2f__sig: 'viff', glUniform2f: function(location, v0, v1) { location = GL.uniforms[location]; Module.ctx.uniform2f(location, v0, v1); }, - glUniform3f__sig: 'viddd', + glUniform3f__sig: 'vifff', glUniform3f: function(location, v0, v1, v2) { location = GL.uniforms[location]; Module.ctx.uniform3f(location, v0, v1, v2); }, - glUniform4f__sig: 'vidddd', + glUniform4f__sig: 'viffff', glUniform4f: function(location, v0, v1, v2, v3) { location = GL.uniforms[location]; Module.ctx.uniform4f(location, v0, v1, v2, v3); @@ -1031,7 +1034,7 @@ var LibraryGL = { program = GL.programs[program]; var info = Module.ctx.getActiveAttrib(program, index); - var infoname = info.name.slice(0, bufSize - 1); + var infoname = info.name.slice(0, Math.max(0, bufSize - 1)); writeStringToMemory(infoname, name); if (length) { @@ -1058,12 +1061,6 @@ var LibraryGL = { GL.shaders[shader] = null; }, - glDetachShader__sig: 'vii', - glDetachShader: function(program, shader) { - Module.ctx.detachShader(GL.programs[program], - GL.shaders[shader]); - }, - glGetAttachedShaders__sig: 'viiii', glGetAttachedShaders: function(program, maxCount, count, shaders) { var result = Module.ctx.getAttachedShaders(GL.programs[program]); @@ -1086,7 +1083,7 @@ var LibraryGL = { glGetShaderSource__sig: 'viiii', glGetShaderSource: function(shader, bufSize, length, source) { var result = Module.ctx.getShaderSource(GL.shaders[shader]); - result = result.slice(0, bufSize - 1); + result = result.slice(0, Math.max(0, bufSize - 1)); writeStringToMemory(result, source); if (length) { {{{ makeSetValue('length', '0', 'result.length', 'i32') }}}; @@ -1157,6 +1154,12 @@ var LibraryGL = { GL.shaders[shader]); }, + glDetachShader__sig: 'vii', + glDetachShader: function(program, shader) { + Module.ctx.detachShader(GL.programs[program], + GL.shaders[shader]); + }, + glGetShaderPrecisionFormat: function(shaderType, precisionType, range, precision) { var result = Module.ctx.getShaderPrecisionFormat(shaderType, precisionType); {{{ makeSetValue('range', '0', 'result.rangeMin', 'i32') }}}; @@ -1194,7 +1197,7 @@ var LibraryGL = { Module.ctx.validateProgram(GL.programs[program]); }, - glIsProgram__sig: 'vi', + glIsProgram__sig: 'ii', glIsProgram: function(program) { var program = GL.programs[program]; if (!program) return 0; @@ -1583,6 +1586,18 @@ var LibraryGL = { glAttachShader(program, shader); }; + var glDetachShader = _glDetachShader; + _glDetachShader = function(program, shader) { + var programShader = GL.programShaders[program]; + if (!programShader) { + Module.printErr('WARNING: _glDetachShader received invalid program: ' + program); + return; + } + var index = programShader.indexOf(shader); + programShader.splice(index, 1); + glDetachShader(program, shader); + }; + var glUseProgram = _glUseProgram; _glUseProgram = function(program) { #if GL_DEBUG @@ -1713,6 +1728,7 @@ var LibraryGL = { 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; @@ -1786,7 +1802,9 @@ var LibraryGL = { 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 '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; @@ -1900,6 +1918,9 @@ var LibraryGL = { if (type == 0x8B84) { // GL_OBJECT_INFO_LOG_LENGTH_ARB {{{ makeSetValue('result', '0', 'Module.ctx.getShaderInfoLog(GL.shaders[id]).length', 'i32') }}}; return; + } else if (type == 0x8B88) { // GL_OBJECT_SHADER_SOURCE_LENGTH_ARB + {{{ makeSetValue('result', '0', 'Module.ctx.getShaderSource(GL.shaders[id]).length', 'i32') }}}; + return; } _glGetShaderiv(id, type, result); } else { @@ -3107,6 +3128,7 @@ var LibraryGL = { glTexGeni: function() { throw 'glTexGeni: TODO' }, glTexGenfv: function() { throw 'glTexGenfv: TODO' }, glTexEnvi: function() { Runtime.warnOnce('glTexEnvi: TODO') }, + glTexEnvf: function() { Runtime.warnOnce('glTexEnvf: TODO') }, glTexEnvfv: function() { Runtime.warnOnce('glTexEnvfv: TODO') }, glTexImage1D: function() { throw 'glTexImage1D: TODO' }, diff --git a/src/library_glfw.js b/src/library_glfw.js index 8bf3616f..5e76071f 100644 --- a/src/library_glfw.js +++ b/src/library_glfw.js @@ -35,8 +35,6 @@ var LibraryGLFW = { params: null, initTime: null, wheelPos: 0, - lastX: 0, - lastY: 0, buttons: 0, keys: 0, initWindowWidth: 640, @@ -145,28 +143,20 @@ var LibraryGLFW = { GLFW.onKeyChanged(event, 0);//GLFW_RELEASE }, - savePosition: function(event) { - /* TODO maybe loop here ala http://www.quirksmode.org/js/findpos.html */ - GLFW.lastX = event['clientX'] - Module['canvas'].offsetLeft; - GLFW.lastY = event['clientY'] - Module['canvas'].offsetTop; - }, - onMousemove: function(event) { /* Send motion event only if the motion changed, prevents * spamming our app with uncessary callback call. It does happen in * Chrome on Windows. */ - var newX = event['clientX'] - Module['canvas'].offsetLeft; - var newY = event['clientY'] - Module['canvas'].offsetTop; - if (newX == GLFW.lastX && newY == GLFW.lastY) { - return; - } - - GLFW.savePosition(event); + var lastX = Browser.mouseX; + var lastY = Browser.mouseY; + Browser.calculateMouseEvent(event); + var newX = Browser.mouseX; + var newY = Browser.mouseY; if (event.target == Module["canvas"] && GLFW.mousePosFunc) { event.preventDefault(); - Runtime.dynCall('vii', GLFW.mousePosFunc, [GLFW.lastX, GLFW.lastY]); + Runtime.dynCall('vii', GLFW.mousePosFunc, [lastX, lastY]); } }, @@ -175,7 +165,8 @@ var LibraryGLFW = { return; } - GLFW.savePosition(event); + Browser.calculateMouseEvent(event); + if (event.target != Module["canvas"]) { return; } @@ -441,8 +432,8 @@ var LibraryGLFW = { }, glfwGetMousePos: function(xpos, ypos) { - setValue(xpos, GLFW.lastX, 'i32'); - setValue(ypos, GLFW.lastY, 'i32'); + setValue(xpos, Browser.mouseX, 'i32'); + setValue(ypos, Browser.mouseY, 'i32'); }, //I believe it is not possible to move the mouse with javascript diff --git a/src/library_glut.js b/src/library_glut.js index 49380367..35348028 100644 --- a/src/library_glut.js +++ b/src/library_glut.js @@ -12,8 +12,6 @@ var LibraryGLUT = { motionFunc: null, passiveMotionFunc: null, mouseFunc: null, - lastX: 0, - lastY: 0, buttons: 0, modifiers: 0, initWindowWidth: 256, @@ -24,12 +22,6 @@ var LibraryGLUT = { windowWidth: 0, windowHeight: 0, - savePosition: function(event) { - /* TODO maybe loop here ala http://www.quirksmode.org/js/findpos.html */ - GLUT.lastX = event['clientX'] - Module['canvas'].offsetLeft; - GLUT.lastY = event['clientY'] - Module['canvas'].offsetTop; - }, - saveModifiers: function(event) { GLUT.modifiers = 0; if (event['shiftKey']) @@ -45,20 +37,21 @@ var LibraryGLUT = { * spamming our app with uncessary callback call. It does happen in * Chrome on Windows. */ - var newX = event['clientX'] - Module['canvas'].offsetLeft; - var newY = event['clientY'] - Module['canvas'].offsetTop; - if (newX == GLUT.lastX && newY == GLUT.lastY) - return; + var lastX = Browser.mouseX; + var lastY = Browser.mouseY; + Browser.calculateMouseEvent(event); + var newX = Browser.mouseX; + var newY = Browser.mouseY; + if (newX == lastX && newY == lastY) return; - GLUT.savePosition(event); if (GLUT.buttons == 0 && event.target == Module["canvas"] && GLUT.passiveMotionFunc) { event.preventDefault(); GLUT.saveModifiers(event); - Runtime.dynCall('vii', GLUT.passiveMotionFunc, [GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('vii', GLUT.passiveMotionFunc, [lastX, lastY]); } else if (GLUT.buttons != 0 && GLUT.motionFunc) { event.preventDefault(); GLUT.saveModifiers(event); - Runtime.dynCall('vii', GLUT.motionFunc, [GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('vii', GLUT.motionFunc, [lastX, lastY]); } }, @@ -159,7 +152,7 @@ var LibraryGLUT = { if( GLUT.specialFunc ) { event.preventDefault(); GLUT.saveModifiers(event); - Runtime.dynCall('viii', GLUT.specialFunc, [key, GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('viii', GLUT.specialFunc, [key, Browser.mouseX, Browser.mouseY]); } } else @@ -168,7 +161,7 @@ var LibraryGLUT = { if( key !== null && GLUT.keyboardFunc ) { event.preventDefault(); GLUT.saveModifiers(event); - Runtime.dynCall('viii', GLUT.keyboardFunc, [key, GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('viii', GLUT.keyboardFunc, [key, Browser.mouseX, Browser.mouseY]); } } } @@ -181,7 +174,7 @@ var LibraryGLUT = { if(GLUT.specialUpFunc) { event.preventDefault (); GLUT.saveModifiers(event); - Runtime.dynCall('viii', GLUT.specialUpFunc, [key, GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('viii', GLUT.specialUpFunc, [key, Browser.mouseX, Browser.mouseY]); } } else @@ -190,14 +183,15 @@ var LibraryGLUT = { if( key !== null && GLUT.keyboardUpFunc ) { event.preventDefault (); GLUT.saveModifiers(event); - Runtime.dynCall('viii', GLUT.keyboardUpFunc, [key, GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('viii', GLUT.keyboardUpFunc, [key, Browser.mouseX, Browser.mouseY]); } } } }, onMouseButtonDown: function(event){ - GLUT.savePosition(event); + Browser.calculateMouseEvent(event); + GLUT.buttons |= (1 << event['button']); if(event.target == Module["canvas"] && GLUT.mouseFunc){ @@ -206,18 +200,19 @@ var LibraryGLUT = { } catch (e) {} event.preventDefault(); GLUT.saveModifiers(event); - Runtime.dynCall('viiii', GLUT.mouseFunc, [event['button'], 0/*GLUT_DOWN*/, GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('viiii', GLUT.mouseFunc, [event['button'], 0/*GLUT_DOWN*/, Browser.mouseX, Browser.mouseY]); } }, onMouseButtonUp: function(event){ - GLUT.savePosition(event); + Browser.calculateMouseEvent(event); + GLUT.buttons &= ~(1 << event['button']); if(GLUT.mouseFunc) { event.preventDefault(); GLUT.saveModifiers(event); - Runtime.dynCall('viiii', GLUT.mouseFunc, [event['button'], 1/*GLUT_UP*/, GLUT.lastX, GLUT.lastY]); + Runtime.dynCall('viiii', GLUT.mouseFunc, [event['button'], 1/*GLUT_UP*/, Browser.mouseX, Browser.mouseY]); } }, diff --git a/src/library_sdl.js b/src/library_sdl.js index a1fb871f..9c5e9805 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -46,8 +46,6 @@ var LibrarySDL = { textInput: false, startTime: null, - mouseX: 0, - mouseY: 0, buttonState: 0, DOMButtons: [0, 0, 0], @@ -515,54 +513,22 @@ var LibrarySDL = { } // fall through case 'mousemove': { - if (Browser.pointerLock) { - // When the pointer is locked, calculate the coordinates - // based on the movement of the mouse. - // Workaround for Firefox bug 764498 - if (event.type != 'mousemove' && - ('mozMovementX' in event)) { - var movementX = 0, movementY = 0; - } else { - var movementX = Browser.getMovementX(event); - var movementY = Browser.getMovementY(event); - } - var x = SDL.mouseX + movementX; - var y = SDL.mouseY + movementY; - } else { - // 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); - - // the canvas might be CSS-scaled compared to its backbuffer; - // SDL-using content will want mouse coordinates in terms - // of backbuffer units. - var cw = Module["canvas"].width; - var ch = Module["canvas"].height; - x = x * (cw / rect.width); - y = y * (ch / rect.height); - - var movementX = x - SDL.mouseX; - var movementY = y - SDL.mouseY; - } + Browser.calculateMouseEvent(event); if (event.type != 'mousemove') { var down = event.type === 'mousedown'; {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.type', 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.button', 'event.button+1', 'i8') }}}; // DOM buttons are 0-2, SDL 1-3 {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.state', 'down ? 1 : 0', 'i8') }}}; - {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.x', 'x', 'i32') }}}; - {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.y', 'y', 'i32') }}}; + {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.x', 'Browser.mouseX', 'i32') }}}; + {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.y', 'Browser.mouseY', 'i32') }}}; } else { {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.type', 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.state', 'SDL.buttonState', 'i8') }}}; - {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.x', 'x', 'i32') }}}; - {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.y', 'y', 'i32') }}}; - {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.xrel', 'movementX', 'i32') }}}; - {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.yrel', 'movementY', 'i32') }}}; + {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.x', 'Browser.mouseX', 'i32') }}}; + {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.y', 'Browser.mouseY', 'i32') }}}; + {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.xrel', 'Browser.mouseMovementX', 'i32') }}}; + {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.yrel', 'Browser.mouseMovementY', 'i32') }}}; } - SDL.mouseX = x; - SDL.mouseY = y; break; } case 'unload': { @@ -924,8 +890,8 @@ var LibrarySDL = { }, SDL_GetMouseState: function(x, y) { - if (x) {{{ makeSetValue('x', '0', 'SDL.mouseX', 'i32') }}}; - if (y) {{{ makeSetValue('y', '0', 'SDL.mouseY', 'i32') }}}; + if (x) {{{ makeSetValue('x', '0', 'Browser.mouseX', 'i32') }}}; + if (y) {{{ makeSetValue('y', '0', 'Browser.mouseY', 'i32') }}}; return SDL.buttonState; }, @@ -1705,6 +1671,60 @@ var LibrarySDL = { SDL_GL_SwapBuffers: function() {}, + // SDL 2 + + SDL_GL_ExtensionSupported: function(extension) { + return Module.ctx.getExtension(extension) | 0; + }, + + SDL_DestroyWindow: function(window) {}, + + SDL_DestroyRenderer: function(renderer) {}, + + SDL_GetWindowFlags: function(x, y) { + if (Browser.isFullScreen) { + return 1; + } + + return 0; + }, + + SDL_GL_SwapWindow: function(window) {}, + + SDL_GL_MakeCurrent: function(window, context) {}, + + SDL_GL_DeleteContext: function(context) {}, + + SDL_GL_SetSwapInterval: function(state) {}, + + SDL_SetWindowTitle: function(window, title) { + if (title) document.title = Pointer_stringify(title); + }, + + SDL_GetWindowSize: function(window, width, height){ + var w = Module['canvas'].width; + var h = Module['canvas'].height; + if (width) {{{ makeSetValue('width', '0', 'w', 'i32') }}}; + if (height) {{{ makeSetValue('height', '0', 'h', 'i32') }}}; + }, + + SDL_LogSetOutputFunction: function(callback, userdata) {}, + + SDL_SetWindowFullscreen: function(window, fullscreen) { + if (Browser.isFullScreen) { + Module['canvas'].cancelFullScreen(); + return 1; + } else { + return 0; + } + }, + + SDL_GetWindowFlags: function() {}, + + SDL_ClearError: function() {}, + + SDL_getenv: 'getenv', + // TODO SDL_SetGamma: function(r, g, b) { diff --git a/src/modules.js b/src/modules.js index 6b3c5ffb..2775bfbd 100644 --- a/src/modules.js +++ b/src/modules.js @@ -305,7 +305,7 @@ var Functions = { // Resolve multi-level aliases all the way down while (1) { var varData = Variables.globals[table[i]]; - if (!(varData && varData.resolvedAlias)) break; + if (!(varData && varData.resolvedAlias && varData.resolvedAlias.indexOf('FUNCTION_TABLE_OFFSET') < 0)) break; table[i] = table[+varData.resolvedAlias || eval(varData.resolvedAlias)]; // might need to eval to turn (6) into 6 } // Resolve library aliases diff --git a/src/parseTools.js b/src/parseTools.js index db834206..fa0f251e 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -1118,6 +1118,8 @@ var asmPrintCounter = 0; // See makeSetValue function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSafe, forceAsm) { if (UNALIGNED_MEMORY) align = 1; + else if (FORCE_ALIGNED_MEMORY && !isIllegalType(type)) align = 8; + if (isStructType(type)) { var typeData = Types.types[type]; var ret = []; @@ -1220,6 +1222,8 @@ function indexizeFunctions(value, type) { //! @param noNeedFirst Whether to ignore the offset in the pointer itself. function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe, sep, forcedAlign, forceAsm) { if (UNALIGNED_MEMORY && !forcedAlign) align = 1; + else if (FORCE_ALIGNED_MEMORY && !isIllegalType(type)) align = 8; + sep = sep || ';'; if (isStructType(type)) { var typeData = Types.types[type]; @@ -1678,10 +1682,10 @@ function checkBitcast(item) { function showWarning() { if (warned) return; warned = true; - if (VERBOSE || ASM_JS) { + if (VERBOSE) { warnOnce('Casting potentially incompatible function pointer ' + oldType + ' to ' + newType + ', for ' + item.params[0].ident.slice(1)); } else { - warnOnce('Casting a function pointer type to a potentially incompatible one (use VERBOSE=1 to see more)'); + warnOnce('Casting a function pointer type to a potentially incompatible one (use -s VERBOSE=1 to see more)'); } warnOnce('See https://github.com/kripken/emscripten/wiki/CodeGuidlinesAndLimitations#function-pointer-issues for more information on dangerous function pointer casts'); if (ASM_JS) warnOnce('Incompatible function pointer casts are very dangerous with ASM_JS=1, you should investigate and correct these'); diff --git a/src/settings.js b/src/settings.js index d029598a..8766277b 100644 --- a/src/settings.js +++ b/src/settings.js @@ -89,6 +89,12 @@ var UNALIGNED_MEMORY = 0; // If enabled, all memory accesses are assumed to be u // typed arrays mode 2 where alignment is relevant.) In unaligned memory mode, you // can run nonportable code that typically would break in JS (or on ARM for that // matter, which also cannot do unaligned reads/writes), at the cost of slowness +var FORCE_ALIGNED_MEMORY = 0; // If enabled, assumes all reads and writes are fully aligned for the type they + // use. This is true in proper C code (no undefined behavior), but is sadly + // common enough that we can't do it by default. See SAFE_HEAP and CHECK_HEAP_ALIGN + // for ways to help find places in your code where unaligned reads/writes are done - + // you might be able to refactor your codebase to prevent them, which leads to + // smaller and faster code, or even the option to turn this flag on. var PRECISE_I64_MATH = 1; // If enabled, i64 addition etc. is emulated - which is slow but precise. If disabled, // we use the 'double trick' which is fast but incurs rounding at high values. // Note that we do not catch 32-bit multiplication by default (which must be done in diff --git a/tests/box2d/Benchmark.cpp b/tests/box2d/Benchmark.cpp index 6853a3dc..0db1d4be 100644 --- a/tests/box2d/Benchmark.cpp +++ b/tests/box2d/Benchmark.cpp @@ -31,7 +31,7 @@ using namespace std; const int e_count = 40; -result_t measure(clock_t times[FRAMES]) { +result_t measure(clock_t *times) { float values[FRAMES]; result_t r; diff --git a/tests/cases/trace.ll b/tests/cases/trace.ll index 1bada3e9..ec68ef92 100644 --- a/tests/cases/trace.ll +++ b/tests/cases/trace.ll @@ -24,7 +24,7 @@ entry: %retval = alloca i32, align 4 ; [#uses=1 type=i32*] store i32 0, i32* %retval %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32] - %0 = getelementptr inbounds [4 x %struct.TraceKindPair]* @_ZL14traceKindNames, i32 0, i32 1; [#uses=1 type=%struct.TraceKindPair*] [debug line = 1473:17] + %0 = getelementptr inbounds [4 x %struct.TraceKindPair]* @_ZL14traceKindNames, i32 0, i32 1 ; [#uses=1 type=%struct.TraceKindPair*] [debug line = 1473:17] %1 = getelementptr inbounds %struct.TraceKindPair* %0, i32 0, i32 0 ; [#uses=1 type=i8**] [debug line = 1473:17] ret i32 1 } diff --git a/tests/nbody-java/nbody_nbody.c b/tests/nbody-java/nbody_nbody.c index b6fa9695..4d77bb32 100644 --- a/tests/nbody-java/nbody_nbody.c +++ b/tests/nbody-java/nbody_nbody.c @@ -246,6 +246,22 @@ void nbody_nbody_main___java_lang_String_1ARRAY(JAVA_OBJECT n1) int main(int argc, char* argv[]) { + // translate our normalized argument (0-0, 1-0.1secs, 2-0.5secs, 3-1sec, 4-5secs, 5-10secs) to nbody + int arg = argc > 1 ? argv[1][0] - '0' : 3; + char buffer[100]; + argv[1] = buffer; + int n; + switch(arg) { + case 0: return 0; break; + case 1: n = 600000; break; + case 2: n = 3600000; break; + case 3: n = 6550000; break; + case 4: n = 30000000; break; + case 5: n = 60000000; break; + default: printf("error: %d\\n", arg); return -1; + } + snprintf(buffer, 50, "%d", n); + xmlvm_init(); // Initialize the main thread before entering XMLVM_SETJMP diff --git a/tests/runner.py b/tests/runner.py index 27fb84dc..b2b1ff43 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -291,7 +291,7 @@ process(sys.argv[1]) out = open(stdout, 'r').read() err = open(stderr, 'r').read() if engine == SPIDERMONKEY_ENGINE and Settings.ASM_JS: - if 'Successfully compiled asm.js code' in err and 'asm.js link error' not in err: + if 'uccessfully compiled asm.js code' in err and 'asm.js link error' not in err: print >> sys.stderr, "[was asm.js'ified]" elif 'asm.js' in err: # if no asm.js error, then not an odin build raise Exception("did NOT asm.js'ify") @@ -447,6 +447,8 @@ process(sys.argv[1]) sys.argv = map(lambda arg: arg if not arg.startswith('test_') else 'default.' + arg, sys.argv) +test_modes = ['default', 'o1', 'o2', 'asm1', 'asm2', 'asm2g', 'asm2x86', 's_0_0', 's_0_1', 's_1_0', 's_1_1'] + test_index = 0 if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'browser' not in str(sys.argv): @@ -454,10 +456,10 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows print "Running Emscripten tests..." - if len(sys.argv) == 2 and 'ALL.' in sys.argv[1]: + 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], 'default.'+test, 'o1.'+test, 'o2.'+test, 'asm1.'+test, 'asm2.'+test, 'asm2g.'+test, 'asm2x86.'+test, 's_0_0.'+test, 's_0_1.'+test, 's_1_0.'+test, 's_1_1.'+test] + sys.argv = [sys.argv[0]] + map(lambda mode: mode+'.'+test, test_modes) class T(RunnerCore): # Short name, to make it more fun to use manually on the commandline ## Does a complete test - builds, runs, checks output, etc. @@ -5618,7 +5620,7 @@ at function.:blag open(path_from_root('tests', 'printf', 'output_i64_1.txt'), 'r').read()] self.do_run(src, expected) - def test_printf_types(self): + def test_printf_2(self): src = r''' #include <stdio.h> @@ -5631,11 +5633,12 @@ at function.:blag double d = 6.6; printf("%c,%hd,%d,%lld,%.1f,%.1llf\n", c, s, i, l, f, d); + printf("%#x,%#x\n", 1, 0); return 0; } ''' - self.do_run(src, '1,2,3,4,5.5,6.6\n') + self.do_run(src, '1,2,3,4,5.5,6.6\n0x1,0\n') def test_vprintf(self): src = r''' @@ -6039,6 +6042,40 @@ Pass: 0.000012 0.000012''') ''' self.do_run(src, '''0:173,16 1:16,173 2:183,173 3:17,287 4:98,123''') + def test_sscanf_other_whitespace(self): + Settings.SAFE_HEAP = 0 # use i16s in printf + + src = r''' + #include<stdio.h> + + int main() { + short int x; + short int y; + + const char* buffer[] = { + "\t2\t3\t", /* TAB - horizontal tab */ + "\t\t5\t\t7\t\t", + "\n11\n13\n", /* LF - line feed */ + "\n\n17\n\n19\n\n", + "\v23\v29\v", /* VT - vertical tab */ + "\v\v31\v\v37\v\v", + "\f41\f43\f", /* FF - form feed */ + "\f\f47\f\f53\f\f", + "\r59\r61\r", /* CR - carrage return */ + "\r\r67\r\r71\r\r" + }; + + for (int i=0; i<10; ++i) { + x = 0; y = 0; + sscanf(buffer[i], " %d %d ", &x, &y); + printf("%d, %d, ", x, y); + } + + return 0; + } + ''' + self.do_run(src, '''2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, ''') + def test_sscanf_3(self): # i64 if not Settings.USE_TYPED_ARRAYS == 2: return self.skip('64-bit sscanf only supported in ta2') @@ -7832,15 +7869,29 @@ def process(filename): Settings.SAFE_HEAP_LINES = ['btVoronoiSimplexSolver.h:40', 'btVoronoiSimplexSolver.h:41', 'btVoronoiSimplexSolver.h:42', 'btVoronoiSimplexSolver.h:43'] - self.do_run(open(path_from_root('tests', 'bullet', 'Demos', 'HelloWorld', 'HelloWorld.cpp'), 'r').read(), - [open(path_from_root('tests', 'bullet', 'output.txt'), 'r').read(), # different roundings - open(path_from_root('tests', 'bullet', 'output2.txt'), 'r').read(), - open(path_from_root('tests', 'bullet', 'output3.txt'), 'r').read()], - libraries=self.get_library('bullet', [os.path.join('src', '.libs', 'libBulletDynamics.a'), - os.path.join('src', '.libs', 'libBulletCollision.a'), - os.path.join('src', '.libs', 'libLinearMath.a')], - configure_args=['--disable-demos','--disable-dependency-tracking']), - includes=[path_from_root('tests', 'bullet', 'src')]) + def test(): + self.do_run(open(path_from_root('tests', 'bullet', 'Demos', 'HelloWorld', 'HelloWorld.cpp'), 'r').read(), + [open(path_from_root('tests', 'bullet', 'output.txt'), 'r').read(), # different roundings + open(path_from_root('tests', 'bullet', 'output2.txt'), 'r').read(), + open(path_from_root('tests', 'bullet', 'output3.txt'), 'r').read()], + libraries=self.get_library('bullet', [os.path.join('src', '.libs', 'libBulletDynamics.a'), + os.path.join('src', '.libs', 'libBulletCollision.a'), + os.path.join('src', '.libs', 'libLinearMath.a')], + configure_args=['--disable-demos','--disable-dependency-tracking']), + includes=[path_from_root('tests', 'bullet', 'src')]) + test() + + assert 'asm2g' in test_modes + if self.run_name == 'asm2g': + # Test forced alignment + print >> sys.stderr, 'testing FORCE_ALIGNED_MEMORY' + old = open('src.cpp.o.js').read() + Settings.FORCE_ALIGNED_MEMORY = 1 + test() + new = open('src.cpp.o.js').read() + print len(old), len(new), old.count('tempBigInt'), new.count('tempBigInt') + assert len(old) > len(new) + assert old.count('tempBigInt') > new.count('tempBigInt') def test_poppler(self): if self.emcc_args is None: return self.skip('very slow, we only do this in emcc runs') @@ -9269,6 +9320,7 @@ finalizing 3 (global == 0) def make_run(fullname, name=-1, compiler=-1, llvm_opts=0, embetter=0, quantum_size=0, typed_arrays=0, emcc_args=None, env='{}'): exec(''' class %s(T): + run_name = '%s' env = %s def tearDown(self): @@ -9333,7 +9385,7 @@ class %s(T): Building.pick_llvm_opts(3) TT = %s -''' % (fullname, env, fullname, fullname, compiler, str(emcc_args), llvm_opts, embetter, quantum_size, typed_arrays, fullname)) +''' % (fullname, fullname, env, fullname, fullname, compiler, str(emcc_args), llvm_opts, embetter, quantum_size, typed_arrays, fullname)) return TT # Make one run with the defaults @@ -12529,7 +12581,16 @@ elif 'benchmark' in str(sys.argv): print ' JavaScript: mean: %.3f (+-%.3f) secs median: %.3f range: %.3f-%.3f (noise: %3.3f%%) (%d runs)' % (mean, std, median, min(times), max(times), 100*std/mean, reps) print ' Native : mean: %.3f (+-%.3f) secs median: %.3f range: %.3f-%.3f (noise: %3.3f%%) JS is %.2f X slower' % (mean_native, std_native, median_native, min(native_times), max(native_times), 100*std_native/mean_native, final) - def do_benchmark(self, name, src, args=[], expected_output='FAIL', emcc_args=[], native_args=[], shared_args=[], force_c=False, reps=TEST_REPS): + def do_benchmark(self, name, src, expected_output='FAIL', args=[], emcc_args=[], native_args=[], shared_args=[], force_c=False, reps=TEST_REPS): + # standard arguments for timing: + # 0: no runtime, just startup + # 1: very little runtime + # 2: 0.5 seconds + # 3: 1 second + # 4: 5 seconds + # 5: 10 seconds + args = args or ['3'] + dirname = self.get_dir() filename = os.path.join(dirname, name + '.c' + ('' if force_c else 'pp')) f = open(filename, 'w') @@ -12553,7 +12614,8 @@ elif 'benchmark' in str(sys.argv): for i in range(reps): start = time.time() js_output = run_js(final_filename, engine=JS_ENGINE, args=args, stderr=PIPE, full_output=True) - if i == 0 and 'Successfully compiled asm.js code' in js_output: + + if i == 0 and 'uccessfully compiled asm.js code' in js_output: if 'asm.js link error' not in js_output: print "[%s was asm.js'ified]" % name curr = time.time()-start @@ -12618,7 +12680,7 @@ elif 'benchmark' in str(sys.argv): return 0; } ''' - self.do_benchmark('primes', src, [], 'lastprime: 3043739.') + self.do_benchmark('primes', src, 'lastprime: 3043739.') def test_memops(self): src = ''' @@ -12651,7 +12713,7 @@ elif 'benchmark' in str(sys.argv): return 0; } ''' - self.do_benchmark('memops', src, [], 'final: 400.') + self.do_benchmark('memops', src, 'final: 400.') def zzztest_files(self): src = r''' @@ -12694,7 +12756,7 @@ elif 'benchmark' in str(sys.argv): return 0; } ''' - self.do_benchmark(src, [], 'ok') + self.do_benchmark(src, 'ok') def test_copy(self): src = r''' @@ -12748,7 +12810,7 @@ elif 'benchmark' in str(sys.argv): return 0; } ''' - self.do_benchmark('copy', src, [], 'sum:2836\n') + self.do_benchmark('copy', src, 'sum:2836\n') def test_fannkuch(self): src = open(path_from_root('tests', 'fannkuch.cpp'), 'r').read().replace( @@ -12768,7 +12830,7 @@ elif 'benchmark' in str(sys.argv): ''' ) assert 'switch(arg)' in src - self.do_benchmark('fannkuch', src, [], 'Pfannkuchen(11) = 51.') + self.do_benchmark('fannkuch', src, 'Pfannkuchen(11) = 51.') def test_corrections(self): src = r''' @@ -12801,7 +12863,7 @@ elif 'benchmark' in str(sys.argv): return 0; } ''' - self.do_benchmark('corrections', src, [], 'final: 40006013:10225.', emcc_args=['-s', 'CORRECT_SIGNS=1', '-s', 'CORRECT_OVERFLOWS=1', '-s', 'CORRECT_ROUNDINGS=1']) + self.do_benchmark('corrections', src, 'final: 40006013:10225.', emcc_args=['-s', 'CORRECT_SIGNS=1', '-s', 'CORRECT_OVERFLOWS=1', '-s', 'CORRECT_ROUNDINGS=1']) def fasta(self, name, double_rep, emcc_args=[]): src = open(path_from_root('tests', 'fasta.cpp'), 'r').read().replace('double', double_rep) @@ -12819,7 +12881,7 @@ elif 'benchmark' in str(sys.argv): } ''') assert 'switch(arg)' in src - self.do_benchmark('fasta', src, [], '''GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA\nTCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT\nAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG\nGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG\nCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT\nGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA\nGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA\nTTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG\nAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA\nGCCTGGGCGA''') + self.do_benchmark('fasta', src, '''GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA\nTCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT\nAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG\nGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG\nCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT\nGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA\nGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA\nTTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG\nAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA\nGCCTGGGCGA''') def test_fasta_float(self): self.fasta('fasta_float', 'float') @@ -12832,11 +12894,11 @@ elif 'benchmark' in str(sys.argv): def test_skinning(self): src = open(path_from_root('tests', 'skinning_test_no_simd.cpp'), 'r').read() - self.do_benchmark('skinning', src, [], 'blah=0.000000') + self.do_benchmark('skinning', src, 'blah=0.000000') def test_life(self): src = open(path_from_root('tests', 'life.c'), 'r').read() - self.do_benchmark('life', src, [], '''-------------------------------- + self.do_benchmark('life', src, '''-------------------------------- [][] [] [] [][] [][] [] [] [][] [] [] @@ -12874,7 +12936,7 @@ elif 'benchmark' in str(sys.argv): def test_nbody_java(self): # tests xmlvm compiled java, including bitcasts of doubles, i64 math, etc. args = [path_from_root('tests', 'nbody-java', x) for x in os.listdir(path_from_root('tests', 'nbody-java')) if x.endswith('.c')] + \ ['-I' + path_from_root('tests', 'nbody-java')] - self.do_benchmark('nbody_java', '', ['11500000'], '''Time(s)''', + self.do_benchmark('nbody_java', '', '''Time(s)''', force_c=True, emcc_args=args + ['-s', 'PRECISE_I64_MATH=1', '--llvm-lto', '0'], native_args=args + ['-lgc', '-std=c99', '-target', 'x86_64-pc-linux-gnu', '-lm']) def test_zlib(self): @@ -12883,7 +12945,7 @@ elif 'benchmark' in str(sys.argv): ['-I' + path_from_root('tests', 'zlib')] native_args = self.get_library('zlib_native', os.path.join('libz.a'), make_args=['libz.a'], native=True) + \ ['-I' + path_from_root('tests', 'zlib')] - self.do_benchmark('zlib', src, [], '''sizes: 100000,25906 + self.do_benchmark('zlib', src, '''sizes: 100000,25906 ok. ''', force_c=True, emcc_args=emcc_args, native_args=native_args) @@ -12897,7 +12959,7 @@ ok. emcc_args = js_lib + ['-I' + path_from_root('tests', 'box2d')] native_args = native_lib + ['-I' + path_from_root('tests', 'box2d')] - self.do_benchmark('box2d', src, [], 'frame averages', emcc_args=emcc_args, native_args=native_args) + self.do_benchmark('box2d', src, 'frame averages', emcc_args=emcc_args, native_args=native_args) def test_zzz_bullet(self): # Called thus so it runs late in the alphabetical cycle... it is long src = open(path_from_root('tests', 'bullet', 'Demos', 'Benchmarks', 'BenchmarkDemo.cpp'), 'r').read() + \ @@ -12919,7 +12981,7 @@ ok. native_args = native_lib + ['-I' + path_from_root('tests', 'bullet', 'src'), '-I' + path_from_root('tests', 'bullet', 'Demos', 'Benchmarks')] - self.do_benchmark('bullet', src, [], '\nok.\n', emcc_args=emcc_args, native_args=native_args) + self.do_benchmark('bullet', src, '\nok.\n', emcc_args=emcc_args, native_args=native_args) elif 'sanity' in str(sys.argv): @@ -13423,8 +13485,17 @@ if __name__ == '__main__': arg = sys.argv[i] if arg.startswith('skip:'): which = arg.split('skip:')[1] - print >> sys.stderr, 'will skip "%s"' % which - exec(which + ' = RunnerCore.skipme') + 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 + exec(test + ' = RunnerCore.skipme') + sys.argv[i] = '' sys.argv = filter(lambda arg: arg, sys.argv) diff --git a/tools/eliminator/asm-eliminator-test-output.js b/tools/eliminator/asm-eliminator-test-output.js index b519cdf9..8da7a5bc 100644 --- a/tools/eliminator/asm-eliminator-test-output.js +++ b/tools/eliminator/asm-eliminator-test-output.js @@ -66,11 +66,9 @@ function __ZN5identC2EiPKcPci($this, $n, $a) { } function _vec2Length($this) { $this = $this | 0; - var $__first_addr_i = 0, $__last_addr_i = 0, __stackBase__ = 0; + var __stackBase__ = 0; __stackBase__ = STACKTOP; STACKTOP = STACKTOP + 8 | 0; - $__first_addr_i = __stackBase__; - $__last_addr_i = __stackBase__ + 4; STACKTOP = __stackBase__; return 0; } @@ -109,18 +107,22 @@ function label() { } } function switchy() { - var no = 0, yes = 0; + var no = 0, yes = 0, a = 0, b = 0; while (1) switch (label | 0) { - case x: + case 1: no = 100; break; - case y: + case 2: yes = 111; yes = yes * 2; print(yes); yes--; print(yes / 2); continue; + case 3: + a = 5; + b = a; + break; } } function confuusion() { @@ -133,4 +135,233 @@ function tempDouble(a) { a = +a; f(a * a); } +function _org_apache_harmony_luni_util_NumberConverter_freeFormat__($me) { + $me = $me | 0; + var $_r2_sroa_0 = 0, $_r3_sroa_0 = 0, $$etemp$1 = 0, $6 = 0, $7 = 0, $10 = 0, $11 = +0, $15 = 0, $_r2_sroa_0_0_cast283 = 0, $_r3_sroa_0_0_cast247 = 0, $_r3_sroa_0_0_load244 = +0, $_r3_sroa_0_0_load244$$SHADOW$0 = 0, $_r2_sroa_0_0_load = +0, $_r2_sroa_0_0_load$$SHADOW$0 = 0, $trunc297 = 0, $25 = 0, $26 = 0, $smax = 0, $28 = 0, $_r3_sroa_0_0_load239 = +0, $_pre_phi301 = 0, $_r3_sroa_0_0_cast264_pre_phi = 0, $_r2_sroa_0_0_load265 = +0, $33 = 0, $34 = 0, $_r3_sroa_0_0_cast253 = 0, $36 = 0, $37 = 0, $_r3_sroa_0_0_load243 = +0, $_r2_sroa_0_0_cast = 0, $45 = 0, $_sink_in = +0, $_r3_sroa_0_0_load241 = +0, $_r2_sroa_0_0_load266287 = 0, $_r1_sroa_0_0 = +0, $47 = 0, $48$0 = 0, $48$1 = 0, $_r1_sroa_0_0_extract_trunc185 = 0, $_r1_sroa_0_1_in$0 = 0, $_r1_sroa_0_1_in$1 = 0, $_r1_sroa_0_0_extract_trunc169 = 0, $_r1_sroa_0_2 = +0, $64 = 0, $65 = 0, $69 = 0, $76 = 0, $82 = 0, $_r1_sroa_0_0_extract_trunc = 0, $$etemp$15 = 0, $105 = 0, $106 = 0, $107 = 0, $108 = 0, $109 = 0, $110 = 0, $112 = 0, $113 = 0, $118 = 0, $_r3_sroa_0_0_load242 = +0, label = 0, __stackBase__ = 0; + __stackBase__ = STACKTOP; + STACKTOP = STACKTOP + 16 | 0; + $_r2_sroa_0 = __stackBase__ | 0; + $_r3_sroa_0 = __stackBase__ + 8 | 0; + if ((HEAP32[(114668 | 0) >> 2] | 0 | 0) == 0) { + HEAP32[(114664 | 0) >> 2] = 1; + HEAP32[(114668 | 0) >> 2] = 1; + $$etemp$1 = 114672 | 0; + HEAP32[($$etemp$1 | 0) >> 2] = -1; + HEAP32[($$etemp$1 + 4 | 0) >> 2] = -1; + HEAP32[(114684 | 0) >> 2] = 25296 | 0; + HEAP32[(114704 | 0) >> 2] = 110728; + HEAP32[(114712 | 0) >> 2] = 8; + HEAP32[(114784 | 0 | 0) >> 2] = HEAP32[(107856 | 0 | 0) >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 4 >> 2] = HEAP32[(107856 | 0 | 0) + 4 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 8 >> 2] = HEAP32[(107856 | 0 | 0) + 8 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 12 >> 2] = HEAP32[(107856 | 0 | 0) + 12 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 16 >> 2] = HEAP32[(107856 | 0 | 0) + 16 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 20 >> 2] = HEAP32[(107856 | 0 | 0) + 20 >> 2] | 0; + } + $6 = _org_xmlvm_runtime_XMLVMArray_createSingleDimension___java_lang_Class_int(HEAP32[138960 >> 2] | 0, 25) | 0; + $7 = $me + 8 | 0; + $10 = HEAP32[($me + 20 | 0) >> 2] | 0; + $11 = (HEAP32[tempDoublePtr >> 2] = $10, HEAP32[tempDoublePtr + 4 >> 2] = 0, +HEAPF64[tempDoublePtr >> 3]); + if (($10 | 0) > -1) { + HEAP32[$_r2_sroa_0 >> 2] = 0; + $_r2_sroa_0_0_load265 = +HEAPF64[$_r2_sroa_0 >> 3]; + $_r3_sroa_0_0_cast264_pre_phi = $_r3_sroa_0; + $_pre_phi301 = $6 + 16 | 0; + } else { + $15 = $6 + 16 | 0; + HEAP16[(HEAP32[$15 >> 2] | 0) >> 1] = 48; + $_r2_sroa_0_0_cast283 = $_r2_sroa_0; + HEAP16[((HEAP32[$15 >> 2] | 0) + 2 | 0) >> 1] = 46; + HEAP32[$_r2_sroa_0_0_cast283 >> 2] = 2; + $_r3_sroa_0_0_cast247 = $_r3_sroa_0; + HEAP32[$_r3_sroa_0_0_cast247 >> 2] = $10 + 1 | 0; + $_r3_sroa_0_0_load244 = +HEAPF64[$_r3_sroa_0 >> 3]; + $_r3_sroa_0_0_load244$$SHADOW$0 = HEAP32[($_r3_sroa_0 | 0) >> 2] | 0; + $_r2_sroa_0_0_load = +HEAPF64[$_r2_sroa_0 >> 3]; + $_r2_sroa_0_0_load$$SHADOW$0 = HEAP32[($_r2_sroa_0 | 0) >> 2] | 0; + HEAPF64[$_r3_sroa_0 >> 3] = $_r2_sroa_0_0_load; + HEAPF64[$_r2_sroa_0 >> 3] = $_r3_sroa_0_0_load244; + $trunc297 = $_r3_sroa_0_0_load244$$SHADOW$0; + $25 = $_r2_sroa_0_0_load$$SHADOW$0; + if (($trunc297 | 0) < 0) { + $26 = $trunc297 + 1 | 0; + $smax = ($26 | 0) > 0 ? $26 : 0; + $28 = $25 + $smax | 0; + $113 = $25; + $112 = $trunc297; + while (1) { + HEAP16[((HEAP32[$15 >> 2] | 0) + ($113 << 1) | 0) >> 1] = 48; + $118 = $112 + 1 | 0; + if (($118 | 0) < 0) { + $113 = $113 + 1 | 0; + $112 = $118; + } else { + break; + } + } + HEAP32[$_r3_sroa_0_0_cast247 >> 2] = $28 - $trunc297 | 0; + HEAP32[$_r2_sroa_0_0_cast283 >> 2] = $smax; + $_r3_sroa_0_0_load239 = +HEAPF64[$_r3_sroa_0 >> 3]; + } else { + $_r3_sroa_0_0_load239 = $_r2_sroa_0_0_load; + } + HEAPF64[$_r2_sroa_0 >> 3] = $_r3_sroa_0_0_load239; + $_r2_sroa_0_0_load265 = $_r3_sroa_0_0_load239; + $_r3_sroa_0_0_cast264_pre_phi = $_r3_sroa_0_0_cast247; + $_pre_phi301 = $15; + } + $33 = $me + 16 | 0; + $34 = HEAP32[$33 >> 2] | 0; + $_r3_sroa_0_0_cast253 = $_r3_sroa_0; + HEAP32[$_r3_sroa_0_0_cast253 >> 2] = $34; + $36 = $me + 12 | 0; + $37 = HEAP32[$36 >> 2] | 0; + HEAP32[$36 >> 2] = $37 + 1 | 0; + HEAP32[$_r3_sroa_0_0_cast264_pre_phi >> 2] = HEAP32[((HEAP32[($34 + 16 | 0) >> 2] | 0) + ($37 << 2) | 0) >> 2] | 0; + $_r3_sroa_0_0_load243 = +HEAPF64[$_r3_sroa_0 >> 3]; + HEAPF64[$_r3_sroa_0 >> 3] = $_r2_sroa_0_0_load265; + HEAPF64[$_r2_sroa_0 >> 3] = $11; + $_r2_sroa_0_0_cast = $_r2_sroa_0; + $45 = $7; + $_r1_sroa_0_0 = $_r3_sroa_0_0_load243; + $_r2_sroa_0_0_load266287 = $10; + $_r3_sroa_0_0_load241 = $_r2_sroa_0_0_load265; + $_sink_in = $_r2_sroa_0_0_load265; + while (1) { + HEAPF64[tempDoublePtr >> 3] = $_sink_in; + $47 = HEAP32[tempDoublePtr >> 2] | 0; + HEAPF64[tempDoublePtr >> 3] = $_r1_sroa_0_0; + $48$0 = HEAP32[tempDoublePtr >> 2] | 0; + $48$1 = HEAP32[tempDoublePtr + 4 >> 2] | 0; + $_r1_sroa_0_0_extract_trunc185 = $48$0; + do { + if (($_r1_sroa_0_0_extract_trunc185 | 0) == -1) { + if (($_r2_sroa_0_0_load266287 | 0) < -1) { + $_r1_sroa_0_2 = $_r3_sroa_0_0_load241; + break; + } + HEAP16[((HEAP32[$_pre_phi301 >> 2] | 0) + ($47 << 1) | 0) >> 1] = 48; + $_r1_sroa_0_1_in$1 = 0 | $48$1 & -1; + $_r1_sroa_0_1_in$0 = $47 + 1 | 0 | $48$0 & 0; + label = 785; + break; + } else { + HEAP16[((HEAP32[$_pre_phi301 >> 2] | 0) + ($47 << 1) | 0) >> 1] = ($_r1_sroa_0_0_extract_trunc185 + 48 | 0) & 65535; + $_r1_sroa_0_1_in$1 = 0; + $_r1_sroa_0_1_in$0 = $47 + 1 | 0; + label = 785; + break; + } + } while (0); + do { + if ((label | 0) == 785) { + label = 0; + if (!(($_r2_sroa_0_0_load266287 | 0) == 0)) { + $_r1_sroa_0_2 = (HEAP32[tempDoublePtr >> 2] = $_r1_sroa_0_1_in$0, HEAP32[tempDoublePtr + 4 >> 2] = $_r1_sroa_0_1_in$1, +HEAPF64[tempDoublePtr >> 3]); + break; + } + $_r1_sroa_0_0_extract_trunc169 = $_r1_sroa_0_1_in$0; + HEAP32[$_r3_sroa_0_0_cast264_pre_phi >> 2] = $_r1_sroa_0_0_extract_trunc169 + 1 | 0; + HEAP16[((HEAP32[$_pre_phi301 >> 2] | 0) + ($_r1_sroa_0_0_extract_trunc169 << 1) | 0) >> 1] = 46; + $_r1_sroa_0_2 = +HEAPF64[$_r3_sroa_0 >> 3]; + } + } while (0); + $64 = $_r2_sroa_0_0_load266287 - 1 | 0; + $65 = HEAP32[$36 >> 2] | 0; + HEAP32[$_r3_sroa_0_0_cast264_pre_phi >> 2] = $65; + if (($65 | 0) < (HEAP32[$45 >> 2] | 0 | 0)) { + $69 = HEAP32[$33 >> 2] | 0; + HEAP32[$_r3_sroa_0_0_cast253 >> 2] = $69; + HEAP32[$36 >> 2] = $65 + 1 | 0; + $76 = HEAP32[((HEAP32[($69 + 16 | 0) >> 2] | 0) + ($65 << 2) | 0) >> 2] | 0; + HEAP32[$_r3_sroa_0_0_cast264_pre_phi >> 2] = $76; + if (!(($76 | 0) != -1 | ($64 | 0) > -2)) { + break; + } + } else { + HEAP32[$_r3_sroa_0_0_cast264_pre_phi >> 2] = -1; + if (!(($64 | 0) > -2)) { + break; + } + } + $_r3_sroa_0_0_load242 = +HEAPF64[$_r3_sroa_0 >> 3]; + HEAPF64[$_r3_sroa_0 >> 3] = $_r1_sroa_0_2; + $_r1_sroa_0_0 = $_r3_sroa_0_0_load242; + $_r2_sroa_0_0_load266287 = $64; + $_r3_sroa_0_0_load241 = $_r1_sroa_0_2; + $_sink_in = $_r1_sroa_0_2; + } + HEAP32[$_r2_sroa_0_0_cast >> 2] = $64; + if ((HEAP32[(106148 | 0) >> 2] | 0 | 0) == 0) { + ___INIT_java_lang_String(); + } + $82 = _GC_MALLOC(36 | 0) | 0; + HEAP32[$82 >> 2] = 106144; + _memset($82 + 4 | 0 | 0 | 0, 0 | 0 | 0, 32 | 0 | 0); + HEAP32[$_r2_sroa_0 >> 2] = $82; + HEAPF64[tempDoublePtr >> 3] = $_r1_sroa_0_2; + $_r1_sroa_0_0_extract_trunc = HEAP32[tempDoublePtr >> 2] | 0; + HEAP32[($82 + 8 | 0) >> 2] = 0; + HEAP32[($82 + 12 | 0) >> 2] = 0; + HEAP32[($82 + 16 | 0) >> 2] = 0; + if (($_r1_sroa_0_0_extract_trunc | 0) < 0) { + _XMLVM_ERROR(16136 | 0, 13208 | 0, 132112 | 0, 830); + return 0 | 0; + } + if ((HEAP32[($6 + 12 | 0) >> 2] | 0 | 0) < ($_r1_sroa_0_0_extract_trunc | 0)) { + _XMLVM_ERROR(16136 | 0, 13208 | 0, 132112 | 0, 830); + return 0 | 0; + } + HEAP32[($82 + 24 | 0) >> 2] = 0; + if (!((HEAP32[(114668 | 0) >> 2] | 0 | 0) == 0)) { + $105 = HEAP32[138960 >> 2] | 0; + $106 = _org_xmlvm_runtime_XMLVMArray_createSingleDimension___java_lang_Class_int($105, $_r1_sroa_0_0_extract_trunc) | 0; + $107 = $82 + 20 | 0; + $108 = $107; + HEAP32[$108 >> 2] = $106; + $109 = $82 + 28 | 0; + $110 = $109; + HEAP32[$110 >> 2] = $_r1_sroa_0_0_extract_trunc; + _java_lang_System_arraycopy___java_lang_Object_int_java_lang_Object_int_int($6, 0, $106, 0, $_r1_sroa_0_0_extract_trunc); + STACKTOP = __stackBase__; + return $82 | 0; + } + HEAP32[(114664 | 0) >> 2] = 1; + HEAP32[(114668 | 0) >> 2] = 1; + $$etemp$15 = 114672 | 0; + HEAP32[($$etemp$15 | 0) >> 2] = -1; + HEAP32[($$etemp$15 + 4 | 0) >> 2] = -1; + HEAP32[(114684 | 0) >> 2] = 25296 | 0; + HEAP32[(114704 | 0) >> 2] = 110728; + HEAP32[(114712 | 0) >> 2] = 8; + HEAP32[(114784 | 0 | 0) >> 2] = HEAP32[(107856 | 0 | 0) >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 4 >> 2] = HEAP32[(107856 | 0 | 0) + 4 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 8 >> 2] = HEAP32[(107856 | 0 | 0) + 8 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 12 >> 2] = HEAP32[(107856 | 0 | 0) + 12 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 16 >> 2] = HEAP32[(107856 | 0 | 0) + 16 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 20 >> 2] = HEAP32[(107856 | 0 | 0) + 20 >> 2] | 0; + $105 = HEAP32[138960 >> 2] | 0; + $106 = _org_xmlvm_runtime_XMLVMArray_createSingleDimension___java_lang_Class_int($105, $_r1_sroa_0_0_extract_trunc) | 0; + $107 = $82 + 20 | 0; + $108 = $107; + HEAP32[$108 >> 2] = $106; + $109 = $82 + 28 | 0; + $110 = $109; + HEAP32[$110 >> 2] = $_r1_sroa_0_0_extract_trunc; + _java_lang_System_arraycopy___java_lang_Object_int_java_lang_Object_int_int($6, 0, $106, 0, $_r1_sroa_0_0_extract_trunc); + STACKTOP = __stackBase__; + return $82 | 0; +} +function __ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_($this, $manifold, $xfA, $xfB) { + $this = $this | 0; + $manifold = $manifold | 0; + $xfA = $xfA | 0; + $xfB = $xfB | 0; + var __stackBase__ = 0; + __stackBase__ = STACKTOP; + STACKTOP = STACKTOP + 256 | 0; + __ZN12b2EPCollider7CollideEP10b2ManifoldPK11b2EdgeShapeRK11b2TransformPK14b2PolygonShapeS7_(__stackBase__ | 0, $manifold, HEAP32[((HEAP32[($this + 48 | 0) >> 2] | 0) + 12 | 0) >> 2] | 0, $xfA, HEAP32[((HEAP32[($this + 52 | 0) >> 2] | 0) + 12 | 0) >> 2] | 0, $xfB); + STACKTOP = __stackBase__; + return; +} diff --git a/tools/eliminator/asm-eliminator-test.js b/tools/eliminator/asm-eliminator-test.js index ff67af47..5f75e9c1 100644 --- a/tools/eliminator/asm-eliminator-test.js +++ b/tools/eliminator/asm-eliminator-test.js @@ -143,17 +143,22 @@ function label() { } function switchy() { var no = 0, yes = 0; + var a = 0, b = 0; while (1) switch (label | 0) { - case x: + case 1: no = 100; // eliminatable in theory, but eliminator does not look into switch. must leave def above as well. break; - case y: + case 2: yes = 111; yes = yes*2; print(yes); yes--; print(yes/2); continue; + case 3: + a = 5; + b = a; + break; } } function confuusion() { @@ -170,5 +175,423 @@ function tempDouble(a) { y = a*a; f(y); } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "__Z11printResultPiS_j", "_segment_holding", "__ZN5identC2EiPKcPci", "_vec2Length", "exc", "label", "confuusion", "tempDouble"] +function _org_apache_harmony_luni_util_NumberConverter_freeFormat__($me) { + $me = $me | 0; + var $_r2_sroa_0 = 0, $_r3_sroa_0 = 0, $1 = 0, $2 = 0, $$etemp$1 = 0, $$etemp$0$0 = 0, $$etemp$0$1 = 0, $st$2$0 = 0; + var $st$3$1 = 0, $5 = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0, $10 = 0, $_r1_sroa_0_0_insert_ext191$0 = 0; + var $_r1_sroa_0_0_insert_ext191$1 = 0, $11 = +0, $12 = 0, $14 = 0, $15 = 0, $16 = 0, $17 = 0, $_r2_sroa_0_0_cast283 = 0; + var $18 = 0, $19 = 0, $20 = 0, $21 = 0, $_r3_sroa_0_0_cast247 = 0, $_r3_sroa_0_0_load244 = +0, $ld$4$0 = 0, $_r3_sroa_0_0_load244$$SHADOW$0 = 0; + var $ld$5$1 = 0, $_r3_sroa_0_0_load244$$SHADOW$1 = 0, $_r2_sroa_0_0_load = +0, $ld$6$0 = 0, $_r2_sroa_0_0_load$$SHADOW$0 = 0, $ld$7$1 = 0, $_r2_sroa_0_0_load$$SHADOW$1 = 0, $22$0 = 0; + var $22$1 = 0, $trunc297$0 = 0, $trunc297 = 0, $23 = 0, $24$0 = 0, $24$1 = 0, $25$0 = 0, $25 = 0; + var $26 = 0, $27 = 0, $smax = 0, $28 = 0, $29 = 0, $_r3_sroa_0_0_load239_pre = +0, $ld$8$0 = 0, $_r3_sroa_0_0_load239_pre$$SHADOW$0 = 0; + var $ld$9$1 = 0, $_r3_sroa_0_0_load239_pre$$SHADOW$1 = 0, $_r3_sroa_0_0_load239 = +0, $_pre_phi301 = 0, $_r3_sroa_0_0_cast264_pre_phi = 0, $_r2_sroa_0_0_load265 = +0, $32 = 0, $33 = 0; + var $34 = 0, $_r3_sroa_0_0_cast253 = 0, $35 = 0, $36 = 0, $37 = 0, $38 = 0, $39 = 0, $40 = 0; + var $41 = 0, $42 = 0, $43 = 0, $44 = 0, $_r3_sroa_0_0_load243 = +0, $ld$10$0 = 0, $_r3_sroa_0_0_load243$$SHADOW$0 = 0, $ld$11$1 = 0; + var $_r3_sroa_0_0_load243$$SHADOW$1 = 0, $_r2_sroa_0_0_cast = 0, $45 = 0, $_sink_in = +0, $_r3_sroa_0_0_load241 = +0, $_r2_sroa_0_0_load266287 = 0, $_r1_sroa_0_0 = +0, $_sink$0 = 0, $_sink$1 = 0; + var $47$0 = 0, $47 = 0, $48$0 = 0, $48$1 = 0, $_r1_sroa_0_0_extract_trunc185$0 = 0, $_r1_sroa_0_0_extract_trunc185 = 0, $49 = 0, $51 = 0, $52 = 0; + var $53 = 0, $54 = 0, $55 = 0, $56 = 0, $_r1_sroa_0_0_insert_ext195$0 = 0, $_r1_sroa_0_0_insert_ext195$1 = 0, $_r1_sroa_0_1_in$0 = 0, $_r1_sroa_0_1_in$1 = 0; + var $_r1_sroa_0_1 = +0, $58 = 0, $_r1_sroa_0_0_extract_trunc169$0 = 0, $_r1_sroa_0_0_extract_trunc169 = 0, $60 = 0, $61 = 0, $62 = 0, $63 = 0; + var $_r3_sroa_0_0_load240 = +0, $ld$12$0 = 0, $_r3_sroa_0_0_load240$$SHADOW$0 = 0, $ld$13$1 = 0, $_r3_sroa_0_0_load240$$SHADOW$1 = 0, $_r1_sroa_0_2 = +0, $64 = 0, $65 = 0; + var $66 = 0, $67 = 0, $69 = 0, $70 = 0, $71 = 0, $72 = 0, $73 = 0, $74 = 0; + var $75 = 0, $76 = 0, $phitmp = 0, $77 = 0, $or_cond = 0, $79 = 0, $80 = 0, $82 = 0; + var $83 = 0, $84 = 0, $_r2_sroa_0_0_cast269 = 0, $85$0 = 0, $85$1 = 0, $_r1_sroa_0_0_extract_trunc$0 = 0, $_r1_sroa_0_0_extract_trunc = 0, $86 = 0, $87 = 0; + var $88 = 0, $89 = 0, $90 = 0, $91 = 0, $92 = 0, $94 = 0, $95 = 0, $96 = 0; + var $97 = 0, $99 = 0, $100 = 0, $101 = 0, $102 = 0, $$etemp$15 = 0, $$etemp$14$0 = 0, $$etemp$14$1 = 0; + var $st$16$0 = 0, $st$17$1 = 0, $105 = 0, $106 = 0, $107 = 0, $108 = 0, $109 = 0, $110 = 0; + var $112 = 0, $113 = 0, $114 = 0, $115 = 0, $116 = 0, $117 = 0, $118 = 0, $119 = 0; + var $121 = 0, $123 = 0, $_r1_sroa_0_0_insert_ext$0 = 0, $_r1_sroa_0_0_insert_ext$1 = 0, $$etemp$18$0 = 0, $$etemp$18$1 = 0, $_r1_sroa_0_0_insert_mask$0 = 0, $_r1_sroa_0_0_insert_mask$1 = 0; + var $_r1_sroa_0_0_insert_insert$0 = 0, $_r1_sroa_0_0_insert_insert$1 = 0, $124 = 0, $125 = 0, $126 = 0, $_old = 0, $_r3_sroa_0_0_load242 = +0, $ld$19$0 = 0; + var $_r3_sroa_0_0_load242$$SHADOW$0 = 0, $ld$20$1 = 0, $_r3_sroa_0_0_load242$$SHADOW$1 = 0, $_r2_sroa_0_0_cast284 = 0, $_r2_sroa_0_0_load265_pre = +0, $ld$21$0 = 0, $_r2_sroa_0_0_load265_pre$$SHADOW$0 = 0, $ld$22$1 = 0; + var $_r2_sroa_0_0_load265_pre$$SHADOW$1 = 0, $_r3_sroa_0_0_cast264_pre = 0, $_pre = 0, $_pre300 = 0; + var label = 0; + var __stackBase__ = 0; + __stackBase__ = STACKTOP; + STACKTOP = STACKTOP + 16 | 0; + $_r2_sroa_0 = __stackBase__ | 0; + $_r3_sroa_0 = __stackBase__ + 8 | 0; + $1 = HEAP32[(114668 | 0) >> 2] | 0; + $2 = ($1 | 0) == 0; + if ($2) { + HEAP32[(114664 | 0) >> 2] = 1; + HEAP32[(114668 | 0) >> 2] = 1; + $$etemp$1 = 114672 | 0; + $$etemp$0$0 = -1; + $$etemp$0$1 = -1; + $st$2$0 = $$etemp$1 | 0; + HEAP32[$st$2$0 >> 2] = $$etemp$0$0; + $st$3$1 = $$etemp$1 + 4 | 0; + HEAP32[$st$3$1 >> 2] = $$etemp$0$1; + HEAP32[(114684 | 0) >> 2] = 25296 | 0; + HEAP32[(114704 | 0) >> 2] = 110728; + HEAP32[(114712 | 0) >> 2] = 8; + HEAP32[(114784 | 0 | 0) >> 2] = HEAP32[(107856 | 0 | 0) >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 4 >> 2] = HEAP32[(107856 | 0 | 0) + 4 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 8 >> 2] = HEAP32[(107856 | 0 | 0) + 8 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 12 >> 2] = HEAP32[(107856 | 0 | 0) + 12 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 16 >> 2] = HEAP32[(107856 | 0 | 0) + 16 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 20 >> 2] = HEAP32[(107856 | 0 | 0) + 20 >> 2] | 0; + } + $5 = HEAP32[138960 >> 2] | 0; + $6 = _org_xmlvm_runtime_XMLVMArray_createSingleDimension___java_lang_Class_int($5, 25) | 0; + $7 = $me + 8 | 0; + $8 = $me + 20 | 0; + $9 = $8; + $10 = HEAP32[$9 >> 2] | 0; + $_r1_sroa_0_0_insert_ext191$0 = $10; + $_r1_sroa_0_0_insert_ext191$1 = 0; + $11 = (HEAP32[tempDoublePtr >> 2] = $_r1_sroa_0_0_insert_ext191$0, HEAP32[tempDoublePtr + 4 >> 2] = $_r1_sroa_0_0_insert_ext191$1, +HEAPF64[tempDoublePtr >> 3]); + $12 = ($10 | 0) > -1; + if ($12) { + $_r2_sroa_0_0_cast284 = $_r2_sroa_0; + HEAP32[$_r2_sroa_0_0_cast284 >> 2] = 0; + $_r2_sroa_0_0_load265_pre = +HEAPF64[$_r2_sroa_0 >> 3]; + $ld$21$0 = $_r2_sroa_0 | 0; + $_r2_sroa_0_0_load265_pre$$SHADOW$0 = HEAP32[$ld$21$0 >> 2] | 0; + $ld$22$1 = $_r2_sroa_0 + 4 | 0; + $_r2_sroa_0_0_load265_pre$$SHADOW$1 = HEAP32[$ld$22$1 >> 2] | 0; + $_r3_sroa_0_0_cast264_pre = $_r3_sroa_0; + $_pre = $6 + 16 | 0; + $_pre300 = $_pre; + var $_r2_sroa_0_0_load265 = $_r2_sroa_0_0_load265_pre; + var $_r3_sroa_0_0_cast264_pre_phi = $_r3_sroa_0_0_cast264_pre; + var $_pre_phi301 = $_pre300; + } else { + $14 = $6 + 16 | 0; + $15 = $14; + $16 = HEAP32[$15 >> 2] | 0; + $17 = $16; + HEAP16[$17 >> 1] = 48; + $_r2_sroa_0_0_cast283 = $_r2_sroa_0; + $18 = HEAP32[$15 >> 2] | 0; + $19 = $18 + 2 | 0; + $20 = $19; + HEAP16[$20 >> 1] = 46; + HEAP32[$_r2_sroa_0_0_cast283 >> 2] = 2; + $21 = $10 + 1 | 0; + $_r3_sroa_0_0_cast247 = $_r3_sroa_0; + HEAP32[$_r3_sroa_0_0_cast247 >> 2] = $21; + $_r3_sroa_0_0_load244 = +HEAPF64[$_r3_sroa_0 >> 3]; + $ld$4$0 = $_r3_sroa_0 | 0; + $_r3_sroa_0_0_load244$$SHADOW$0 = HEAP32[$ld$4$0 >> 2] | 0; + $ld$5$1 = $_r3_sroa_0 + 4 | 0; + $_r3_sroa_0_0_load244$$SHADOW$1 = HEAP32[$ld$5$1 >> 2] | 0; + $_r2_sroa_0_0_load = +HEAPF64[$_r2_sroa_0 >> 3]; + $ld$6$0 = $_r2_sroa_0 | 0; + $_r2_sroa_0_0_load$$SHADOW$0 = HEAP32[$ld$6$0 >> 2] | 0; + $ld$7$1 = $_r2_sroa_0 + 4 | 0; + $_r2_sroa_0_0_load$$SHADOW$1 = HEAP32[$ld$7$1 >> 2] | 0; + HEAPF64[$_r3_sroa_0 >> 3] = $_r2_sroa_0_0_load; + HEAPF64[$_r2_sroa_0 >> 3] = $_r3_sroa_0_0_load244; + $22$0 = $_r3_sroa_0_0_load244$$SHADOW$0; + $22$1 = $_r3_sroa_0_0_load244$$SHADOW$1; + $trunc297$0 = $22$0; + $trunc297 = $trunc297$0; + $23 = ($trunc297 | 0) < 0; + $24$0 = $_r2_sroa_0_0_load$$SHADOW$0; + $24$1 = $_r2_sroa_0_0_load$$SHADOW$1; + $25$0 = $24$0; + $25 = $25$0; + if ($23) { + $26 = $trunc297 + 1 | 0; + $27 = ($26 | 0) > 0; + $smax = $27 ? $26 : 0; + $28 = $25 + $smax | 0; + var $113 = $25; + var $112 = $trunc297; + while (1) { + $114 = $113 + 1 | 0; + $115 = HEAP32[$15 >> 2] | 0; + $116 = $115; + $117 = $116 + ($113 << 1) | 0; + HEAP16[$117 >> 1] = 48; + $118 = $112 + 1 | 0; + $119 = ($118 | 0) < 0; + if ($119) { + var $113 = $114; + var $112 = $118; + } else { + break; + } + } + $29 = $28 - $trunc297 | 0; + HEAP32[$_r3_sroa_0_0_cast247 >> 2] = $29; + HEAP32[$_r2_sroa_0_0_cast283 >> 2] = $smax; + $_r3_sroa_0_0_load239_pre = +HEAPF64[$_r3_sroa_0 >> 3]; + $ld$8$0 = $_r3_sroa_0 | 0; + $_r3_sroa_0_0_load239_pre$$SHADOW$0 = HEAP32[$ld$8$0 >> 2] | 0; + $ld$9$1 = $_r3_sroa_0 + 4 | 0; + $_r3_sroa_0_0_load239_pre$$SHADOW$1 = HEAP32[$ld$9$1 >> 2] | 0; + $_r3_sroa_0_0_load239 = $_r3_sroa_0_0_load239_pre; + } else { + $_r3_sroa_0_0_load239 = $_r2_sroa_0_0_load; + } + HEAPF64[$_r2_sroa_0 >> 3] = $_r3_sroa_0_0_load239; + var $_r2_sroa_0_0_load265 = $_r3_sroa_0_0_load239; + var $_r3_sroa_0_0_cast264_pre_phi = $_r3_sroa_0_0_cast247; + var $_pre_phi301 = $15; + } + $32 = $me + 16 | 0; + $33 = $32; + $34 = HEAP32[$33 >> 2] | 0; + $_r3_sroa_0_0_cast253 = $_r3_sroa_0; + HEAP32[$_r3_sroa_0_0_cast253 >> 2] = $34; + $35 = $me + 12 | 0; + $36 = $35; + $37 = HEAP32[$36 >> 2] | 0; + $38 = $37 + 1 | 0; + HEAP32[$36 >> 2] = $38; + $39 = $34 + 16 | 0; + $40 = $39; + $41 = HEAP32[$40 >> 2] | 0; + $42 = $41; + $43 = $42 + ($37 << 2) | 0; + $44 = HEAP32[$43 >> 2] | 0; + HEAP32[$_r3_sroa_0_0_cast264_pre_phi >> 2] = $44; + $_r3_sroa_0_0_load243 = +HEAPF64[$_r3_sroa_0 >> 3]; + $ld$10$0 = $_r3_sroa_0 | 0; + $_r3_sroa_0_0_load243$$SHADOW$0 = HEAP32[$ld$10$0 >> 2] | 0; + $ld$11$1 = $_r3_sroa_0 + 4 | 0; + $_r3_sroa_0_0_load243$$SHADOW$1 = HEAP32[$ld$11$1 >> 2] | 0; + HEAPF64[$_r3_sroa_0 >> 3] = $_r2_sroa_0_0_load265; + HEAPF64[$_r2_sroa_0 >> 3] = $11; + $_r2_sroa_0_0_cast = $_r2_sroa_0; + $45 = $7; + var $_r1_sroa_0_0 = $_r3_sroa_0_0_load243; + var $_r2_sroa_0_0_load266287 = $10; + var $_r3_sroa_0_0_load241 = $_r2_sroa_0_0_load265; + var $_sink_in = $_r2_sroa_0_0_load265; + while (1) { + HEAPF64[tempDoublePtr >> 3] = $_sink_in; + var $_sink$0 = HEAP32[tempDoublePtr >> 2] | 0; + var $_sink$1 = HEAP32[tempDoublePtr + 4 >> 2] | 0; + $47$0 = $_sink$0; + $47 = $47$0; + HEAPF64[tempDoublePtr >> 3] = $_r1_sroa_0_0; + var $48$0 = HEAP32[tempDoublePtr >> 2] | 0; + var $48$1 = HEAP32[tempDoublePtr + 4 >> 2] | 0; + $_r1_sroa_0_0_extract_trunc185$0 = $48$0; + $_r1_sroa_0_0_extract_trunc185 = $_r1_sroa_0_0_extract_trunc185$0; + $49 = ($_r1_sroa_0_0_extract_trunc185 | 0) == -1; + do { + if ($49) { + $121 = ($_r2_sroa_0_0_load266287 | 0) < -1; + if ($121) { + $_r1_sroa_0_2 = $_r3_sroa_0_0_load241; + break; + } + $123 = $47 + 1 | 0; + $_r1_sroa_0_0_insert_ext$0 = $123; + $_r1_sroa_0_0_insert_ext$1 = 0; + $$etemp$18$0 = 0; + $$etemp$18$1 = -1; + $_r1_sroa_0_0_insert_mask$0 = $48$0 & $$etemp$18$0; + $_r1_sroa_0_0_insert_mask$1 = $48$1 & $$etemp$18$1; + $_r1_sroa_0_0_insert_insert$0 = $_r1_sroa_0_0_insert_ext$0 | $_r1_sroa_0_0_insert_mask$0; + $_r1_sroa_0_0_insert_insert$1 = $_r1_sroa_0_0_insert_ext$1 | $_r1_sroa_0_0_insert_mask$1; + $124 = HEAP32[$_pre_phi301 >> 2] | 0; + $125 = $124; + $126 = $125 + ($47 << 1) | 0; + HEAP16[$126 >> 1] = 48; + var $_r1_sroa_0_1_in$1 = $_r1_sroa_0_0_insert_insert$1; + var $_r1_sroa_0_1_in$0 = $_r1_sroa_0_0_insert_insert$0; + label = 785; + break; + } else { + $51 = $47 + 1 | 0; + $52 = $_r1_sroa_0_0_extract_trunc185 + 48 | 0; + $53 = $52 & 65535; + $54 = HEAP32[$_pre_phi301 >> 2] | 0; + $55 = $54; + $56 = $55 + ($47 << 1) | 0; + HEAP16[$56 >> 1] = $53; + $_r1_sroa_0_0_insert_ext195$0 = $51; + $_r1_sroa_0_0_insert_ext195$1 = 0; + var $_r1_sroa_0_1_in$1 = $_r1_sroa_0_0_insert_ext195$1; + var $_r1_sroa_0_1_in$0 = $_r1_sroa_0_0_insert_ext195$0; + label = 785; + break; + } + } while (0); + do { + if ((label | 0) == 785) { + label = 0; + $_r1_sroa_0_1 = (HEAP32[tempDoublePtr >> 2] = $_r1_sroa_0_1_in$0, HEAP32[tempDoublePtr + 4 >> 2] = $_r1_sroa_0_1_in$1, +HEAPF64[tempDoublePtr >> 3]); + $58 = ($_r2_sroa_0_0_load266287 | 0) == 0; + if (!$58) { + $_r1_sroa_0_2 = $_r1_sroa_0_1; + break; + } + $_r1_sroa_0_0_extract_trunc169$0 = $_r1_sroa_0_1_in$0; + $_r1_sroa_0_0_extract_trunc169 = $_r1_sroa_0_0_extract_trunc169$0; + $60 = $_r1_sroa_0_0_extract_trunc169 + 1 | 0; + HEAP32[$_r3_sroa_0_0_cast264_pre_phi >> 2] = $60; + $61 = HEAP32[$_pre_phi301 >> 2] | 0; + $62 = $61; + $63 = $62 + ($_r1_sroa_0_0_extract_trunc169 << 1) | 0; + HEAP16[$63 >> 1] = 46; + $_r3_sroa_0_0_load240 = +HEAPF64[$_r3_sroa_0 >> 3]; + $ld$12$0 = $_r3_sroa_0 | 0; + $_r3_sroa_0_0_load240$$SHADOW$0 = HEAP32[$ld$12$0 >> 2] | 0; + $ld$13$1 = $_r3_sroa_0 + 4 | 0; + $_r3_sroa_0_0_load240$$SHADOW$1 = HEAP32[$ld$13$1 >> 2] | 0; + $_r1_sroa_0_2 = $_r3_sroa_0_0_load240; + } + } while (0); + $64 = $_r2_sroa_0_0_load266287 - 1 | 0; + $65 = HEAP32[$36 >> 2] | 0; + HEAP32[$_r3_sroa_0_0_cast264_pre_phi >> 2] = $65; + $66 = HEAP32[$45 >> 2] | 0; + $67 = ($65 | 0) < ($66 | 0); + if ($67) { + $69 = HEAP32[$33 >> 2] | 0; + HEAP32[$_r3_sroa_0_0_cast253 >> 2] = $69; + $70 = $65 + 1 | 0; + HEAP32[$36 >> 2] = $70; + $71 = $69 + 16 | 0; + $72 = $71; + $73 = HEAP32[$72 >> 2] | 0; + $74 = $73; + $75 = $74 + ($65 << 2) | 0; + $76 = HEAP32[$75 >> 2] | 0; + HEAP32[$_r3_sroa_0_0_cast264_pre_phi >> 2] = $76; + $phitmp = ($76 | 0) != -1; + $77 = ($64 | 0) > -2; + $or_cond = $phitmp | $77; + if (!$or_cond) { + break; + } + } else { + HEAP32[$_r3_sroa_0_0_cast264_pre_phi >> 2] = -1; + $_old = ($64 | 0) > -2; + if (!$_old) { + break; + } + } + $_r3_sroa_0_0_load242 = +HEAPF64[$_r3_sroa_0 >> 3]; + $ld$19$0 = $_r3_sroa_0 | 0; + $_r3_sroa_0_0_load242$$SHADOW$0 = HEAP32[$ld$19$0 >> 2] | 0; + $ld$20$1 = $_r3_sroa_0 + 4 | 0; + $_r3_sroa_0_0_load242$$SHADOW$1 = HEAP32[$ld$20$1 >> 2] | 0; + HEAPF64[$_r3_sroa_0 >> 3] = $_r1_sroa_0_2; + var $_r1_sroa_0_0 = $_r3_sroa_0_0_load242; + var $_r2_sroa_0_0_load266287 = $64; + var $_r3_sroa_0_0_load241 = $_r1_sroa_0_2; + var $_sink_in = $_r1_sroa_0_2; + } + HEAP32[$_r2_sroa_0_0_cast >> 2] = $64; + $79 = HEAP32[(106148 | 0) >> 2] | 0; + $80 = ($79 | 0) == 0; + if ($80) { + ___INIT_java_lang_String(); + } + $82 = _GC_MALLOC(36 | 0) | 0; + $83 = $82; + HEAP32[$83 >> 2] = 106144; + $84 = $82 + 4 | 0; + _memset($84 | 0 | 0, 0 | 0 | 0, 32 | 0 | 0); + $_r2_sroa_0_0_cast269 = $_r2_sroa_0; + HEAP32[$_r2_sroa_0_0_cast269 >> 2] = $82; + HEAPF64[tempDoublePtr >> 3] = $_r1_sroa_0_2; + var $85$0 = HEAP32[tempDoublePtr >> 2] | 0; + var $85$1 = HEAP32[tempDoublePtr + 4 >> 2] | 0; + $_r1_sroa_0_0_extract_trunc$0 = $85$0; + $_r1_sroa_0_0_extract_trunc = $_r1_sroa_0_0_extract_trunc$0; + $86 = $82 + 8 | 0; + $87 = $86; + HEAP32[$87 >> 2] = 0; + $88 = $82 + 12 | 0; + $89 = $88; + HEAP32[$89 >> 2] = 0; + $90 = $82 + 16 | 0; + $91 = $90; + HEAP32[$91 >> 2] = 0; + $92 = ($_r1_sroa_0_0_extract_trunc | 0) < 0; + if ($92) { + _XMLVM_ERROR(16136 | 0, 13208 | 0, 132112 | 0, 830); + return 0 | 0; + } + $94 = $6 + 12 | 0; + $95 = $94; + $96 = HEAP32[$95 >> 2] | 0; + $97 = ($96 | 0) < ($_r1_sroa_0_0_extract_trunc | 0); + if ($97) { + _XMLVM_ERROR(16136 | 0, 13208 | 0, 132112 | 0, 830); + return 0 | 0; + } + $99 = $82 + 24 | 0; + $100 = $99; + HEAP32[$100 >> 2] = 0; + $101 = HEAP32[(114668 | 0) >> 2] | 0; + $102 = ($101 | 0) == 0; + if (!$102) { + $105 = HEAP32[138960 >> 2] | 0; + $106 = _org_xmlvm_runtime_XMLVMArray_createSingleDimension___java_lang_Class_int($105, $_r1_sroa_0_0_extract_trunc) | 0; + $107 = $82 + 20 | 0; + $108 = $107; + HEAP32[$108 >> 2] = $106; + $109 = $82 + 28 | 0; + $110 = $109; + HEAP32[$110 >> 2] = $_r1_sroa_0_0_extract_trunc; + _java_lang_System_arraycopy___java_lang_Object_int_java_lang_Object_int_int($6, 0, $106, 0, $_r1_sroa_0_0_extract_trunc); + STACKTOP = __stackBase__; + return $82 | 0; + } + HEAP32[(114664 | 0) >> 2] = 1; + HEAP32[(114668 | 0) >> 2] = 1; + $$etemp$15 = 114672 | 0; + $$etemp$14$0 = -1; + $$etemp$14$1 = -1; + $st$16$0 = $$etemp$15 | 0; + HEAP32[$st$16$0 >> 2] = $$etemp$14$0; + $st$17$1 = $$etemp$15 + 4 | 0; + HEAP32[$st$17$1 >> 2] = $$etemp$14$1; + HEAP32[(114684 | 0) >> 2] = 25296 | 0; + HEAP32[(114704 | 0) >> 2] = 110728; + HEAP32[(114712 | 0) >> 2] = 8; + HEAP32[(114784 | 0 | 0) >> 2] = HEAP32[(107856 | 0 | 0) >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 4 >> 2] = HEAP32[(107856 | 0 | 0) + 4 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 8 >> 2] = HEAP32[(107856 | 0 | 0) + 8 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 12 >> 2] = HEAP32[(107856 | 0 | 0) + 12 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 16 >> 2] = HEAP32[(107856 | 0 | 0) + 16 >> 2] | 0; + HEAP32[(114784 | 0 | 0) + 20 >> 2] = HEAP32[(107856 | 0 | 0) + 20 >> 2] | 0; + $105 = HEAP32[138960 >> 2] | 0; + $106 = _org_xmlvm_runtime_XMLVMArray_createSingleDimension___java_lang_Class_int($105, $_r1_sroa_0_0_extract_trunc) | 0; + $107 = $82 + 20 | 0; + $108 = $107; + HEAP32[$108 >> 2] = $106; + $109 = $82 + 28 | 0; + $110 = $109; + HEAP32[$110 >> 2] = $_r1_sroa_0_0_extract_trunc; + _java_lang_System_arraycopy___java_lang_Object_int_java_lang_Object_int_int($6, 0, $106, 0, $_r1_sroa_0_0_extract_trunc); + STACKTOP = __stackBase__; + return $82 | 0; +} +function __ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_($this, $manifold, $xfA, $xfB) { + $this = $this | 0; + $manifold = $manifold | 0; + $xfA = $xfA | 0; + $xfB = $xfB | 0; + var $collider_i = 0, $1 = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, $7 = 0; + var $8 = 0, $9 = 0, $10 = 0, $11 = 0; + var label = 0; + var __stackBase__ = 0; + __stackBase__ = STACKTOP; + STACKTOP = STACKTOP + 256 | 0; + $collider_i = __stackBase__ | 0; + $1 = $this + 48 | 0; + $2 = HEAP32[$1 >> 2] | 0; + $3 = $2 + 12 | 0; + $4 = HEAP32[$3 >> 2] | 0; + $5 = $4; + $6 = $this + 52 | 0; + $7 = HEAP32[$6 >> 2] | 0; + $8 = $7 + 12 | 0; + $9 = HEAP32[$8 >> 2] | 0; + $10 = $9; + $11 = $collider_i; + __ZN12b2EPCollider7CollideEP10b2ManifoldPK11b2EdgeShapeRK11b2TransformPK14b2PolygonShapeS7_($collider_i, $manifold, $5, $xfA, $10, $xfB); + STACKTOP = __stackBase__; + return; +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "__Z11printResultPiS_j", "_segment_holding", "__ZN5identC2EiPKcPci", "_vec2Length", "exc", "label", "confuusion", "tempDouble", "_org_apache_harmony_luni_util_NumberConverter_freeFormat__", "__ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_"] diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 56ff971c..ce67da89 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1787,6 +1787,7 @@ function eliminate(ast, memSafe) { if (asm) var asmData = normalizeAsm(func); //printErr('eliminate in ' + func[1]); + // First, find the potentially eliminatable functions: that have one definition and one use var definitions = {}; var uses = {}; @@ -1802,6 +1803,7 @@ function eliminate(ast, memSafe) { } } // examine body and note locals + var hasSwitch = false; traverse(func, function(node, type) { if (type === 'var') { var node1 = node[1]; @@ -1833,11 +1835,29 @@ function eliminate(ast, memSafe) { uses[name]--; // because the name node will show up by itself in the previous case } } + } else if (type == 'switch') { + hasSwitch = true; } }); + + // we cannot eliminate variables if there is a switch + if (traverse(func, function(node, type) { + if (type == 'switch') return true; + })) { + if (asm) denormalizeAsm(func, asmData); + return; + } + var potentials = {}; // local variables with 1 definition and 1 use var sideEffectFree = {}; // whether a local variable has no side effects in its definition - for (var name in locals) { + + function unprocessVariable(name) { + if (name in potentials) delete potentials[name]; + if (name in varsToRemove) delete varsToRemove[name]; + if (name in sideEffectFree) delete sideEffectFree[name]; + if (name in varsToTryToRemove) delete varsToTryToRemove[name]; + } + function processVariable(name) { if (definitions[name] == 1 && uses[name] == 1) { potentials[name] = 1; } else if (uses[name] == 0 && (!definitions[name] || definitions[name] <= 1)) { // no uses, no def or 1 def (cannot operate on phis, and the llvm optimizer will remove unneeded phis anyhow) @@ -1862,11 +1882,32 @@ function eliminate(ast, memSafe) { if (!hasSideEffects) { varsToRemove[name] = !definitions[name] ? 2 : 1; // remove it normally sideEffectFree[name] = true; + // Each time we remove a variable with 0 uses, if its value has no + // side effects and vanishes too, then we can remove a use from variables + // appearing in it, and possibly eliminate again + if (value) { + traverse(value, function(node, type) { + if (type == 'name') { + var name = node[1]; + node[1] = ''; // we can remove this - it will never be shown, and should not be left to confuse us as we traverse + if (name in locals) { + uses[name]--; // cannot be infinite recursion since we descend an energy function + assert(uses[name] >= 0); + unprocessVariable(name); + processVariable(name); + } + } + }); + } } else { varsToTryToRemove[name] = 1; // try to remove it later during scanning } } } + for (var name in locals) { + processVariable(name); + } + //printErr('defs: ' + JSON.stringify(definitions)); //printErr('uses: ' + JSON.stringify(uses)); //printErr('values: ' + JSON.stringify(values)); diff --git a/tools/shared.py b/tools/shared.py index 5a9860db..cc056074 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -509,6 +509,9 @@ COMPILER_OPTS = COMPILER_OPTS + ['-m32', '-U__i386__', '-U__i386', '-Ui386', '-D__IEEE_LITTLE_ENDIAN', '-fno-math-errno', '-fno-threadsafe-statics', '-target', LLVM_TARGET] +if LLVM_TARGET == 'le32-unknown-nacl': + COMPILER_OPTS += ['-U__native_client__', '-U__pnacl__', '-U__ELF__'] # The nacl target is originally used for Google Native Client. Emscripten is not NaCl, so remove the platform #define, when using their triple. + USE_EMSDK = not os.environ.get('EMMAKEN_NO_SDK') if USE_EMSDK: @@ -675,6 +678,7 @@ class Settings: Settings.RELOOP = 1 if opt_level >= 3: # Aside from these, -O3 also runs closure compiler and llvm lto + Settings.FORCE_ALIGNED_MEMORY = 1 Settings.DOUBLE_MODE = 0 Settings.PRECISE_I64_MATH = 0 if noisy: logging.warning('Applying some potentially unsafe optimizations! (Use -O2 if this fails.)') |