aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS4
-rwxr-xr-xemcc12
-rw-r--r--src/determinstic.js8
-rw-r--r--src/intertyper.js15
-rw-r--r--src/jsifier.js14
-rw-r--r--src/library.js664
-rw-r--r--src/library_browser.js36
-rw-r--r--src/library_gl.js1492
-rw-r--r--src/library_sdl.js5
-rw-r--r--src/parseTools.js10
-rw-r--r--src/preamble.js1
-rw-r--r--src/relooper/Relooper.cpp127
-rw-r--r--src/relooper/Relooper.h7
-rw-r--r--src/relooper/fuzzer.py4
-rw-r--r--src/relooper/test.cpp41
-rw-r--r--src/relooper/test.txt27
-rw-r--r--src/relooper/test4.txt1
-rw-r--r--src/relooper/test_debug.txt76
-rw-r--r--src/relooper/test_fuzz1.txt11
-rw-r--r--src/relooper/test_fuzz5.txt24
-rw-r--r--src/relooper/test_fuzz6.txt1
-rwxr-xr-xsrc/relooper/testit.sh2
-rwxr-xr-xsrc/relooper/updateit.sh2
-rw-r--r--src/settings.js7
-rw-r--r--src/shell.js1
-rw-r--r--src/socket.io.js3870
-rw-r--r--src/wrtcp.js821
-rw-r--r--system/include/emscripten/emscripten.h13
-rw-r--r--system/include/libcxx/exception4
-rw-r--r--system/lib/libcxx/symbols1
-rw-r--r--tests/aniso.c16
-rw-r--r--tests/cases/emptystruct.ll2
-rw-r--r--tests/cases/fp80_ta2.ll (renamed from tests/cases/fp80.ll)0
-rw-r--r--tests/cases/muli33_ta2.ll114
-rw-r--r--tests/cases/muli33_ta2.txt1
-rw-r--r--tests/cases/philoop_ta2.ll305
-rw-r--r--tests/cases/philoop_ta2.txt1
-rw-r--r--tests/files.cpp3
-rw-r--r--tests/full_es2_sdlproc.c727
-rw-r--r--tests/gl_ps.c40
-rw-r--r--tests/gl_ps_workaround.c230
-rw-r--r--tests/gl_ps_workaround2.c230
-rw-r--r--tests/glbegin_points.c44
-rw-r--r--tests/linpack.c1153
-rwxr-xr-xtests/runner.py553
-rw-r--r--tests/s3tc.c16
-rw-r--r--tests/s3tc_crunch.c16
-rw-r--r--tests/sdl_fog_density.c48
-rw-r--r--tests/sdl_fog_exp2.c48
-rw-r--r--tests/sdl_fog_linear.c48
-rw-r--r--tests/sdl_fog_negative.c48
-rw-r--r--tests/sdl_fog_simple.c51
-rw-r--r--tests/sdl_ogl.c48
-rw-r--r--tests/sdl_ogl_defaultMatrixMode.c46
-rw-r--r--tests/sdl_ogl_p.c44
-rw-r--r--third_party/lzma.js/lzip/Makefile18
-rw-r--r--tools/eliminator/asm-eliminator-test-output.js4605
-rw-r--r--tools/eliminator/asm-eliminator-test.js6087
-rw-r--r--tools/file_packager.py91
-rw-r--r--tools/js-optimizer.js120
-rw-r--r--tools/shared.py10
-rw-r--r--tools/test-js-optimizer-asm-pre-output.js20
-rw-r--r--tools/test-js-optimizer-asm-pre.js14
-rw-r--r--tools/test-js-optimizer-asm-regs-output.js81
-rw-r--r--tools/test-js-optimizer-asm-regs.js84
65 files changed, 20912 insertions, 1351 deletions
diff --git a/AUTHORS b/AUTHORS
index 4cacefeb..f7a2225a 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -76,4 +76,8 @@ a license to everyone to use it as detailed in LICENSE.)
* John Allwine <jallwine86@gmail.com>
* Martin Gerhardy <martin.gerhardy@gmail.com>
* James Gregory <jgregory@zynga.com> (copyright owned by Zynga, Inc)
+* Dan Gohman <sunfish@google.com> (copyright owned by Google, Inc.)
+* Jeff Gilbert <jgilbert@mozilla.com> (copyright owned by Mozilla Foundation)
+* Frits Talbot <frits@metapathy.com>
+
diff --git a/emcc b/emcc
index acb59143..9feba1b1 100755
--- a/emcc
+++ b/emcc
@@ -110,7 +110,7 @@ while response_file:
sys.argv[index:index+1] = extra_args
break
-if len(sys.argv) == 1 or sys.argv[1] == '--help':
+if len(sys.argv) == 1 or '--help' in sys.argv:
this = os.path.basename('em++' if os.environ.get('EMMAKEN_CXX') else 'emcc')
print '''%s [options] file...
@@ -601,7 +601,7 @@ if EMMAKEN_CFLAGS: CC_ADDITIONAL_ARGS += shlex.split(EMMAKEN_CFLAGS)
# ---------------- Utilities ---------------
-SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc')
+SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc', '.m', '.mm')
BITCODE_SUFFIXES = ('.bc', '.o', '.obj')
DYNAMICLIB_SUFFIXES = ('.dylib', '.so', '.dll')
STATICLIB_SUFFIXES = ('.a',)
@@ -629,7 +629,7 @@ header = False # pre-compiled headers. We fake that by just copying the file
for i in range(1, len(sys.argv)):
arg = sys.argv[i]
if not arg.startswith('-'):
- if arg.endswith('.c'):
+ if arg.endswith(('.c','.m')):
use_cxx = False
if arg.endswith('.h') and sys.argv[i-1] != '-include':
header = True
@@ -994,7 +994,8 @@ try:
for change in settings_changes:
key, value = change.split('=')
if value[0] == '@':
- value = '"' + value + '"'
+ value = '"@' + os.path.abspath(value[1:]) + '"'
+ value = value.replace('\\\\', '/').replace('\\', '/') # Convert backslash paths to forward slashes on Windows as well, since the JS compiler otherwise needs the backslashes escaped (alternative is to escape all input paths passing to JS, which feels clumsier to read)
exec('shared.Settings.' + key + ' = ' + value)
# Apply effects from settings
@@ -1002,8 +1003,7 @@ try:
assert opt_level >= 1, 'asm.js requires -O1 or above'
if bind:
- shared.Settings.ASM_JS = 0
- logging.warning('disabling asm.js because it is not compatible with embind yet')
+ shared.Settings.RESERVED_FUNCTION_POINTERS = max(shared.Settings.RESERVED_FUNCTION_POINTERS, 10)
if shared.Settings.CORRECT_SIGNS != 1:
logging.warning('setting CORRECT_SIGNS to 1 for asm.js code generation')
shared.Settings.CORRECT_SIGNS = 1
diff --git a/src/determinstic.js b/src/determinstic.js
index 91f98ed9..1ec0bbfe 100644
--- a/src/determinstic.js
+++ b/src/determinstic.js
@@ -10,3 +10,11 @@ Date.now = function() {
};
performance.now = Date.now;
+function hashMemory(id) {
+ var ret = 0;
+ for (var i = 0; i < HEAPU8.length; i++) {
+ ret = (ret*17 + HEAPU8[i])|0;
+ }
+ print(id + ':' + ret);
+}
+
diff --git a/src/intertyper.js b/src/intertyper.js
index 445c37f4..6da30ae8 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -537,12 +537,17 @@ function intertyper(data, sidePass, baseLineNums) {
});
}
} else if (!external) {
- if (item.tokens[3].text == 'c')
- item.tokens.splice(3, 1);
- if (item.tokens[3].text in PARSABLE_LLVM_FUNCTIONS) {
- ret.value = parseLLVMFunctionCall(item.tokens.slice(2));
+ if (item.tokens[3] && item.tokens[3].text != ';') {
+ if (item.tokens[3].text == 'c') {
+ item.tokens.splice(3, 1);
+ }
+ if (item.tokens[3].text in PARSABLE_LLVM_FUNCTIONS) {
+ ret.value = parseLLVMFunctionCall(item.tokens.slice(2));
+ } else {
+ ret.value = scanConst(item.tokens[3], ret.type);
+ }
} else {
- ret.value = scanConst(item.tokens[3], ret.type);
+ ret.value = { intertype: 'value', ident: '0', value: '0', type: ret.type };
}
}
return [ret];
diff --git a/src/jsifier.js b/src/jsifier.js
index 2c83d036..156fd65d 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -12,6 +12,8 @@ var RELOOP_IGNORED_LASTS = set('return', 'unreachable', 'resume');
var addedLibraryItems = {};
var asmLibraryFunctions = [];
+var SETJMP_LABEL = -1;
+
// JSifier
function JSify(data, functionsOnly, givenFunctions) {
var mainPass = !functionsOnly;
@@ -458,6 +460,7 @@ function JSify(data, functionsOnly, givenFunctions) {
} else {
ident = '_' + ident;
}
+ if (VERBOSE) printErr('adding ' + ident + ' and deps ' + deps);
var depsText = (deps ? '\n' + deps.map(addFromLibrary).filter(function(x) { return x != '' }).join('\n') : '');
var contentText = isFunction ? snippet : ('var ' + ident + '=' + snippet + ';');
if (ASM_JS) {
@@ -730,7 +733,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}).join('\n') + '\n';
if (func.setjmpTable && ASM_JS) {
// emit a label in which we write to the proper local variable, before jumping to the actual label
- ret += ' case -1111: ';
+ ret += ' case ' + SETJMP_LABEL + ': ';
ret += func.setjmpTable.map(function(triple) { // original label, label we created for right after the setjmp, variable setjmp result goes into
return 'if ((setjmpLabel|0) == ' + getLabelId(triple.oldLabel) + ') { ' + triple.assignTo + ' = threwValue; label = ' + triple.newLabel + ' }\n';
}).join(' else ');
@@ -1030,13 +1033,13 @@ function JSify(data, functionsOnly, givenFunctions) {
}
for (var i = 0; i < idents.length; i++) {
if (keys(deps[idents[i]]).length == 0) {
- pre = 'var ' + idents[i] + ' = ' + valueJSes[idents[i]] + ';' + pre;
+ post = 'var ' + idents[i] + ' = ' + valueJSes[idents[i]] + ';' + post;
remove(idents[i]);
continue mainLoop;
}
}
// If we got here, we have circular dependencies, and must break at least one.
- pre = 'var ' + idents[0] + '$phi = ' + valueJSes[idents[0]] + ';' + pre;
+ pre += 'var ' + idents[0] + '$phi = ' + valueJSes[idents[0]] + ';';
post += 'var ' + idents[0] + ' = ' + idents[0] + '$phi;';
remove(idents[0]);
}
@@ -1160,6 +1163,7 @@ function JSify(data, functionsOnly, givenFunctions) {
return ret + ';';
});
makeFuncLineActor('resume', function(item) {
+ if (DISABLE_EXCEPTION_CATCHING) return 'abort()';
if (item.ident == 0) {
// No exception to resume, so we can just bail.
// This is related to issue #917 and http://llvm.org/PR15518
@@ -1488,9 +1492,9 @@ function JSify(data, functionsOnly, givenFunctions) {
}
if (ASM_JS && funcData.setjmpTable) {
- // check if a longjmp was done. If a setjmp happened, check if ours. If ours, go to -111 to handle it.
+ // check if a longjmp was done. If a setjmp happened, check if ours. If ours, go to a special label to handle it.
// otherwise, just return - the call to us must also have been an invoke, so the setjmp propagates that way
- ret += '; if (((__THREW__|0) != 0) & ((threwValue|0) != 0)) { setjmpLabel = ' + asmCoercion('_testSetjmp(' + makeGetValue('__THREW__', 0, 'i32') + ', setjmpTable)', 'i32') + '; if ((setjmpLabel|0) > 0) { label = -1111; break } else return ' + (funcData.returnType != 'void' ? asmCoercion('0', funcData.returnType) : '') + ' } __THREW__ = threwValue = 0;\n';
+ ret += '; if (((__THREW__|0) != 0) & ((threwValue|0) != 0)) { setjmpLabel = ' + asmCoercion('_testSetjmp(' + makeGetValue('__THREW__', 0, 'i32') + ', setjmpTable)', 'i32') + '; if ((setjmpLabel|0) > 0) { label = ' + SETJMP_LABEL + '; break } else return ' + (funcData.returnType != 'void' ? asmCoercion('0', funcData.returnType) : '') + ' } __THREW__ = threwValue = 0;\n';
}
return ret;
diff --git a/src/library.js b/src/library.js
index 27b79b32..08cb3baf 100644
--- a/src/library.js
+++ b/src/library.js
@@ -326,24 +326,25 @@ LibraryManager.library = {
#else
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');
}
-
+
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) {
@@ -368,7 +369,7 @@ LibraryManager.library = {
this._chunkSize = chunkSize;
this.lengthKnown = true;
}
-
+
var lazyArray = new LazyUint8Array();
Object.defineProperty(lazyArray, "length", {
get: function() {
@@ -560,6 +561,7 @@ LibraryManager.library = {
var stdout = FS.createDevice(devFolder, 'stdout', null, output);
var stderr = FS.createDevice(devFolder, 'stderr', null, error);
FS.createDevice(devFolder, 'tty', input, output);
+ FS.createDevice(devFolder, 'null', function(){}, function(){});
// Create default streams.
FS.streams[1] = {
@@ -2572,7 +2574,7 @@ LibraryManager.library = {
if (format[formatIndex] == 'l') {
long_ = true;
formatIndex++;
- if(format[formatIndex] == 'l') {
+ if (format[formatIndex] == 'l') {
longLong = true;
formatIndex++;
}
@@ -2631,7 +2633,7 @@ LibraryManager.library = {
case 'd': case 'u': case 'i':
if (half) {
{{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i16') }}};
- } else if(longLong) {
+ } else if (longLong) {
{{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i64') }}};
} else {
{{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i32') }}};
@@ -3797,14 +3799,14 @@ LibraryManager.library = {
* implementation (replaced by dlmalloc normally) so
* not an issue.
*/
-#if ASSERTIONS
+#if ASSERTIONS == 2
Runtime.warnOnce('using stub malloc (reference it from C to have the real one included)');
#endif
var ptr = Runtime.dynamicAlloc(bytes + 8);
return (ptr+8) & 0xFFFFFFF8;
},
free: function() {
-#if ASSERTIONS
+#if ASSERTIONS == 2
Runtime.warnOnce('using stub free (reference it from C to have the real one included)');
#endif
},
@@ -3918,7 +3920,14 @@ LibraryManager.library = {
str++;
}
}
- }
+ } else if (finalBase==16) {
+ if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('0') }}}) {
+ if ({{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('x') }}} ||
+ {{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('X') }}}) {
+ str += 2;
+ }
+ }
+ }
if (!finalBase) finalBase = 10;
// Get digits.
@@ -3969,13 +3978,14 @@ LibraryManager.library = {
#if USE_TYPED_ARRAYS == 2
_parseInt64__deps: ['isspace', '__setErrNo', '$ERRNO_CODES', function() { Types.preciseI64MathUsed = 1 }],
_parseInt64: function(str, endptr, base, min, max, unsign) {
- var start = str;
+ var isNegative = false;
// Skip space.
while (_isspace({{{ makeGetValue('str', 0, 'i8') }}})) str++;
-
+
// Check for a plus/minus sign.
if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('-') }}}) {
str++;
+ isNegative = true;
} else if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('+') }}}) {
str++;
}
@@ -3991,12 +4001,19 @@ LibraryManager.library = {
str += 2;
} else {
finalBase = 8;
- str++;
ok = true; // we saw an initial zero, perhaps the entire thing is just "0"
}
}
- }
+ } else if (finalBase==16) {
+ if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('0') }}}) {
+ if ({{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('x') }}} ||
+ {{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('X') }}}) {
+ str += 2;
+ }
+ }
+ }
if (!finalBase) finalBase = 10;
+ start = str;
// Get digits.
var chr;
@@ -4009,6 +4026,7 @@ LibraryManager.library = {
ok = true;
}
}
+
if (!ok) {
___setErrNo(ERRNO_CODES.EINVAL);
{{{ makeStructuralReturn(['0', '0']) }}};
@@ -4020,7 +4038,8 @@ LibraryManager.library = {
}
try {
- i64Math.fromString(Pointer_stringify(start, str - start), finalBase, min, max, unsign);
+ var numberString = isNegative ? '-'+Pointer_stringify(start, str - start) : Pointer_stringify(start, str - start);
+ i64Math.fromString(numberString, finalBase, min, max, unsign);
} catch(e) {
___setErrNo(ERRNO_CODES.ERANGE); // not quite correct
}
@@ -4467,24 +4486,24 @@ LibraryManager.library = {
}
return pdest|0;
},
-
+
strlwr__deps:['tolower'],
strlwr: function(pstr){
var i = 0;
while(1) {
var x = {{{ makeGetValue('pstr', 'i', 'i8') }}};
- if(x == 0) break;
+ if (x == 0) break;
{{{ makeSetValue('pstr', 'i', '_tolower(x)', 'i8') }}};
i++;
}
},
-
+
strupr__deps:['toupper'],
strupr: function(pstr){
var i = 0;
while(1) {
var x = {{{ makeGetValue('pstr', 'i', 'i8') }}};
- if(x == 0) break;
+ if (x == 0) break;
{{{ makeSetValue('pstr', 'i', '_toupper(x)', 'i8') }}};
i++;
}
@@ -4660,7 +4679,7 @@ LibraryManager.library = {
if (size < 0) {
size = 0;
}
-
+
var newStr = _malloc(size + 1);
{{{ makeCopyValues('newStr', 'ptr', 'size', 'null', null, 1) }}};
{{{ makeSetValue('newStr', 'size', '0', 'i8') }}};
@@ -5088,7 +5107,13 @@ LibraryManager.library = {
return _malloc(size);
},
__cxa_free_exception: function(ptr) {
- return _free(ptr);
+ try {
+ return _free(ptr);
+ } catch(e) { // XXX FIXME
+#if ASSERTIONS
+ Module.printErr('exception during cxa_free_exception: ' + e);
+#endif
+ }
},
__cxa_throw__sig: 'viii',
__cxa_throw__deps: ['llvm_eh_exception', '_ZSt18uncaught_exceptionv', '__cxa_find_matching_catch'],
@@ -5576,10 +5601,15 @@ LibraryManager.library = {
frexp: function(x, exp_addr) {
var sig = 0, exp_ = 0;
if (x !== 0) {
+ var sign = 1;
+ if (x < 0) {
+ x = -x;
+ sign = -1;
+ }
var raw_exp = Math.log(x)/Math.log(2);
exp_ = Math.ceil(raw_exp);
if (exp_ === raw_exp) exp_ += 1;
- sig = x/Math.pow(2, exp_);
+ sig = sign*x/Math.pow(2, exp_);
}
{{{ makeSetValue('exp_addr', 0, 'exp_', 'i32') }}}
return sig;
@@ -6907,7 +6937,7 @@ LibraryManager.library = {
},
__errno_state: 0,
__setErrNo__deps: ['__errno_state'],
- __setErrNo__postset: '___errno_state = Runtime.staticAlloc(4);',
+ __setErrNo__postset: '___errno_state = Runtime.staticAlloc(4); {{{ makeSetValue("___errno_state", 0, 0, "i32") }}};',
__setErrNo: function(value) {
// For convenient setting and returning of errno.
{{{ makeSetValue('___errno_state', '0', 'value', 'i32') }}}
@@ -7164,6 +7194,7 @@ LibraryManager.library = {
['i32', 'h_length'],
['i8**', 'h_addr_list'],
]),
+
gethostbyname__deps: ['__hostent_struct_layout'],
gethostbyname: function(name) {
name = Pointer_stringify(name);
@@ -7206,17 +7237,28 @@ LibraryManager.library = {
// sockets. Note that the implementation assumes all sockets are always
// nonblocking
// ==========================================================================
-
+#if SOCKET_WEBRTC
+ $Sockets__deps: ['__setErrNo', '$ERRNO_CODES',
+ function() { return 'var SocketIO = ' + read('socket.io.js') + ';\n' },
+ function() { return 'var Peer = ' + read('wrtcp.js') + ';\n' }],
+#else
$Sockets__deps: ['__setErrNo', '$ERRNO_CODES'],
+#endif
$Sockets: {
- BACKEND_WEBSOCKETS: 0,
- BACKEND_WEBRTC: 1,
BUFFER_SIZE: 10*1024, // initial size
MAX_BUFFER_SIZE: 10*1024*1024, // maximum size we will grow the buffer
- backend: 0, // default to websockets
nextFd: 1,
fds: {},
+ nextport: 1,
+ maxport: 65535,
+ peer: null,
+ connections: {},
+ portmap: {},
+ localAddr: 0xfe00000a, // Local address is always 10.0.0.254
+ addrPool: [ 0x0200000a, 0x0300000a, 0x0400000a, 0x0500000a,
+ 0x0600000a, 0x0700000a, 0x0800000a, 0x0900000a, 0x0a00000a,
+ 0x0b00000a, 0x0c00000a, 0x0d00000a, 0x0e00000a], /* 0x0100000a is reserved */
sockaddr_in_layout: Runtime.generateStructInfo([
['i32', 'sin_family'],
['i16', 'sin_port'],
@@ -7233,114 +7275,386 @@ LibraryManager.library = {
['i32', 'msg_controllen'],
['i32', 'msg_flags'],
]),
+ },
- backends: {
- 0: { // websockets
- connect: function(info) {
- console.log('opening ws://' + info.host + ':' + info.port);
- info.socket = new WebSocket('ws://' + info.host + ':' + info.port, ['binary']);
- info.socket.binaryType = 'arraybuffer';
+#if SOCKET_WEBRTC