aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS13
-rwxr-xr-xemcc29
-rwxr-xr-xemscripten.py50
-rw-r--r--src/analyzer.js21
-rwxr-xr-x[-rw-r--r--]src/embind/embind.js1816
-rwxr-xr-x[-rw-r--r--]src/embind/emval.js195
-rw-r--r--src/fastLong.js298
-rw-r--r--src/jsifier.js84
-rw-r--r--src/library.js129
-rw-r--r--src/library_browser.js6
-rw-r--r--src/library_gl.js8
-rw-r--r--src/long.js56
-rw-r--r--src/modules.js2
-rw-r--r--src/parseTools.js17
-rw-r--r--src/preamble.js2
-rw-r--r--src/settings.js1
-rwxr-xr-x[-rw-r--r--]system/include/emscripten/bind.h1311
-rw-r--r--system/include/emscripten/val.h259
-rwxr-xr-x[-rw-r--r--]system/include/emscripten/wire.h297
-rw-r--r--system/lib/compiler-rt/LICENSE.TXT97
-rw-r--r--system/lib/compiler-rt/divdi3.c47
-rw-r--r--system/lib/compiler-rt/int_endianness.h116
-rw-r--r--system/lib/compiler-rt/int_lib.h46
-rw-r--r--system/lib/compiler-rt/int_math.h67
-rw-r--r--system/lib/compiler-rt/int_types.h140
-rw-r--r--system/lib/compiler-rt/int_util.h29
-rw-r--r--system/lib/compiler-rt/muldi3.c56
-rw-r--r--system/lib/compiler-rt/readme.txt20
-rw-r--r--system/lib/compiler-rt/udivdi3.c36
-rw-r--r--system/lib/compiler-rt/udivmoddi4.c251
-rwxr-xr-xsystem/lib/embind/bind.cpp100
-rw-r--r--tests/cases/call_i64_noret.ll17
-rw-r--r--tests/cases/legalizer_ta2.ll1
-rw-r--r--tests/cases/longjmp_tiny.ll (renamed from tests/cases/longjmp_tiny_noasm.ll)0
-rw-r--r--tests/cases/longjmp_tiny.txt (renamed from tests/cases/longjmp_tiny_noasm.txt)0
-rw-r--r--tests/cases/longjmp_tiny_invoke.ll (renamed from tests/cases/longjmp_tiny_noasm_invoke.ll)0
-rw-r--r--tests/cases/longjmp_tiny_invoke.txt (renamed from tests/cases/longjmp_tiny_noasm_invoke.txt)0
-rw-r--r--tests/cases/longjmp_tiny_phi.ll (renamed from tests/cases/longjmp_tiny_phi_noasm.ll)0
-rw-r--r--tests/cases/longjmp_tiny_phi.txt (renamed from tests/cases/longjmp_tiny_phi_noasm.txt)0
-rw-r--r--tests/cases/longjmp_tiny_phi2.ll (renamed from tests/cases/longjmp_tiny_phi2_noasm.ll)0
-rw-r--r--tests/cases/longjmp_tiny_phi2.txt (renamed from tests/cases/longjmp_tiny_phi2_noasm.txt)0
-rw-r--r--tests/cases/uadd_overflow_64_ta2.ll30
-rw-r--r--tests/cases/uadd_overflow_64_ta2.txt2
-rw-r--r--tests/embind/embind.benchmark.js201
-rwxr-xr-xtests/embind/embind.test.js1691
-rw-r--r--tests/embind/embind_benchmark.cpp344
-rw-r--r--tests/embind/embind_test.cpp1926
-rw-r--r--tests/embind/embind_test.js393
-rwxr-xr-xtests/embind/imvu_test_adapter.js616
-rw-r--r--tests/embind/shell.html94
-rwxr-xr-xtests/embind/underscore-1.4.2.js1200
-rw-r--r--tests/gl_stride.c152
-rw-r--r--tests/gl_stride.pngbin0 -> 345620 bytes
-rwxr-xr-xtests/runner.py169
-rw-r--r--tests/unistd/misc.out2
-rw-r--r--tests/websockets_gethostbyname.c4
-rw-r--r--tools/eliminator/asm-eliminator-test-output.js15
-rw-r--r--tools/eliminator/asm-eliminator-test.js15
-rw-r--r--tools/file_packager.py52
-rw-r--r--tools/js-optimizer.js13
-rw-r--r--tools/response_file.py28
-rw-r--r--tools/shared.py36
62 files changed, 10856 insertions, 1744 deletions
diff --git a/AUTHORS b/AUTHORS
index 87a656d6..1c6cf0ec 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -24,7 +24,7 @@ a license to everyone to use it as detailed in LICENSE.)
* Pierre Renaux <pierre@talansoft.com>
* Brian Anderson <banderson@mozilla.com>
* Jon Bardin <diclophis@gmail.com>
-* Jukka Jylänki <jujjyl@gmail.com>
+* Jukka Jylänki <jujjyl@gmail.com>
* Aleksander Guryanov <caiiiycuk@gmail.com>
* Chad Austin <chad@chadaustin.me> (copyright owned by IMVU)
* nandhp <nandhp@gmail.com>
@@ -46,7 +46,7 @@ a license to everyone to use it as detailed in LICENSE.)
* Anthony Liot <wolfviking0@yahoo.com>
* Michael Riss <Michael.Riss@gmx.de>
* Jasper St. Pierre <jstpierre@mecheye.net>
-* Manuel Schölling <manuel.schoelling@gmx.de>
+* Manuel Schölling <manuel.schoelling@gmx.de>
* Bruce Mitchener, Jr. <bruce.mitchener@gmail.com>
* Michael Bishop <mbtyke@gmail.com>
* Roger Braun <roger@rogerbraun.net>
@@ -57,9 +57,14 @@ a license to everyone to use it as detailed in LICENSE.)
* Ting-Yuan Huang <thuang@mozilla.com>
* Joshua Granick <jgranick@blackberry.com>
* Felix H. Dahlke <fhd@ubercode.de>
-* Éloi Rivard <azmeuk@gmail.com>
+* Éloi Rivard <azmeuk@gmail.com>
* Alexander Gladysh <ag@logiceditor.com>
* Arlo Breault <arlolra@gmail.com>
* Jacob Lee <artdent@gmail.com> (copyright owned by Google, Inc.)
* Joe Lee <jlee@imvu.com> (copyright owned by IMVU)
-
+* Andy Friesen <andy@imvu.com> (copyright owned by IMVU)
+* Bill Welden <bwelden@imvu.com> (copyright owned by IMVU)
+* Michael Ey <mey@imvu.com> (copyright owned by IMVU)
+* Llorens Marti Garcia <lgarcia@imvu.com> (copyright owned by IMVU)
+* Jinsuck Kim <jkim@imvu.com> (copyright owned by IMVU)
+* Todd Lee <tlee@imvu.com> (copyright owned by IMVU)
diff --git a/emcc b/emcc
index 03d92fd3..5d22129a 100755
--- a/emcc
+++ b/emcc
@@ -79,6 +79,7 @@ import os, sys, shutil, tempfile, subprocess, shlex, time, re
from subprocess import PIPE, STDOUT
from tools import shared
from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename
+from tools.response_file import read_response_file
# Mapping of emcc opt levels to llvm opt levels. We use llvm opt level 3 in emcc opt
# levels 2 and 3 (emcc 3 is unsafe opts, so unsuitable for the only level to get
@@ -129,19 +130,10 @@ while response_file:
for index in range(1, len(sys.argv)):
if sys.argv[index][0] == '@':
# found one, loop again next time
- response_file = sys.argv[index][1:]
- print >>sys.stderr, 'emcc: using response file: %s' % response_file
- if not os.path.exists(response_file):
- print >>sys.stderr, 'emcc: error: Response file not found: %s' % response_file
- exit(1)
-
- response_fd = open(response_file, 'r')
- extra_args = shlex.split(response_fd.read())
- response_fd.close()
-
+ response_file = True
+ extra_args = read_response_file(sys.argv[index])
# slice in extra_args in place of the response file arg
sys.argv[index:index+1] = extra_args
- #if DEBUG: print >>sys.stderr, "Expanded response file: " + " | ".join(sys.argv)
break
if sys.argv[1] == '--version':
@@ -171,7 +163,7 @@ Most normal gcc/g++ options will work, for example:
Options that are modified or new in %s include:
-O0 No optimizations (default)
- -O1 Simple optimizations, including LLVM -O1
+ -O1 Simple optimizations, including asm.js, LLVM -O1
optimizations, and no runtime assertions
or C++ exception catching (to re-enable
C++ exception catching, use
@@ -473,7 +465,7 @@ Options that are modified or new in %s include:
--memory-init-file <on> If on, we generate a separate memory initialization
file. This is more efficient than storing the
memory initialization data embedded inside
- JavaScript as text. (default is on)
+ JavaScript as text. (default is off)
The target file, if specified (-o <target>), defines what will
be generated:
@@ -483,8 +475,8 @@ be generated:
<name>.bc LLVM bitcode (default)
<name>.o LLVM bitcode (same as .bc)
-Note that if --memory-init-file is used, then in addition to a
-.js or .html file that is generated, a .mem file will also appear.
+(Note that if --memory-init-file is used, then in addition to a
+.js or .html file that is generated, a .mem file will also appear.)
The -c option (which tells gcc not to run the linker) will
cause LLVM bitcode to be generated, as %s only generates
@@ -727,7 +719,7 @@ try:
bind = False
jcache = False
save_bc = False
- memory_init_file = True
+ memory_init_file = False
if use_cxx:
default_cxx_std = '-std=c++03' # Enforce a consistent C++ standard when compiling .cpp files, if user does not specify one on the cmdline.
@@ -1010,8 +1002,11 @@ try:
# Apply effects from settings
if shared.Settings.ASM_JS:
- assert opt_level == 2, 'asm.js requires -O2'
+ assert opt_level >= 1, 'asm.js requires -O1 or above'
+ if bind:
+ shared.Settings.ASM_JS = 0
+ print >> sys.stderr, 'emcc: warning: disabling asm.js because it is not compatible with embind yet'
if closure:
print >> sys.stderr, 'emcc: warning: disabling closure because it is not compatible with asm.js code generation'
closure = False
diff --git a/emscripten.py b/emscripten.py
index 996e5cc3..6d384a96 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -12,6 +12,7 @@ headers, for the libc implementation in JS).
import os, sys, json, optparse, subprocess, re, time, multiprocessing, functools
from tools import jsrun, cache as cache_module, tempfiles
+from tools.response_file import read_response_file
__rootpath__ = os.path.abspath(os.path.dirname(__file__))
def path_from_root(*pathelems):
@@ -347,6 +348,14 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
if settings.get('ASM_JS'):
post_funcs, post_rest = post.split('// EMSCRIPTEN_END_FUNCS\n')
post = post_rest
+
+ # Move preAsms to their right place
+ def move_preasm(m):
+ contents = m.groups(0)[0]
+ outfile.write(contents + '\n')
+ return ''
+ post_funcs = re.sub(r'/\* PRE_ASM \*/(.*)\n', lambda m: move_preasm(m), post_funcs)
+
funcs_js += ['\n' + post_funcs + '// EMSCRIPTEN_END_FUNCS\n']
simple = os.environ.get('EMCC_SIMPLE_ASM')
@@ -384,15 +393,12 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
if settings['CHECK_HEAP_ALIGN']: basic_funcs += ['CHECK_ALIGN_2', 'CHECK_ALIGN_4', 'CHECK_ALIGN_8']
basic_vars = ['STACKTOP', 'STACK_MAX', 'tempDoublePtr', 'ABORT']
basic_float_vars = ['NaN', 'Infinity']
- if forwarded_json['Types']['preciseI64MathUsed']:
- basic_funcs += ['i64Math_' + op for op in ['add', 'subtract', 'multiply', 'divide', 'modulo']]
- asm_setup += '''
-var i64Math_add = function(a, b, c, d) { i64Math.add(a, b, c, d) };
-var i64Math_subtract = function(a, b, c, d) { i64Math.subtract(a, b, c, d) };
-var i64Math_multiply = function(a, b, c, d) { i64Math.multiply(a, b, c, d) };
-var i64Math_divide = function(a, b, c, d, e) { i64Math.divide(a, b, c, d, e) };
-var i64Math_modulo = function(a, b, c, d, e) { i64Math.modulo(a, b, c, d, e) };
-'''
+
+ if forwarded_json['Types']['preciseI64MathUsed'] or \
+ forwarded_json['Functions']['libraryFunctions'].get('llvm_cttz_i32') or \
+ forwarded_json['Functions']['libraryFunctions'].get('llvm_ctlz_i32'):
+ basic_vars += ['cttz_i8', 'ctlz_i8']
+
asm_runtime_funcs = ['stackAlloc', 'stackSave', 'stackRestore', 'setThrew'] + ['setTempRet%d' % i for i in range(10)]
# function tables
def asm_coerce(value, sig):
@@ -420,7 +426,7 @@ function invoke_%s(%s) {
try {
%sModule.dynCall_%s(%s);
} catch(e) {
- asm.setThrew(1);
+ asm.setThrew(1, 0);
}
}
''' % (sig, args, 'return ' if sig[0] != 'v' else '', sig, args)
@@ -442,7 +448,7 @@ function invoke_%s(%s) {
pass
# If no named globals, only need externals
global_vars = map(lambda g: g['name'], filter(lambda g: settings['NAMED_GLOBALS'] or g.get('external') or g.get('unIndexable'), forwarded_json['Variables']['globals'].values()))
- global_funcs = ['_' + x for x in forwarded_json['Functions']['libraryFunctions'].keys()]
+ global_funcs = ['_' + key for key, value in forwarded_json['Functions']['libraryFunctions'].iteritems() if value != 2]
def math_fix(g):
return g if not g.startswith('Math_') else g.split('_')[1];
asm_global_funcs = ''.join([' var ' + g.replace('.', '_') + '=global.' + g + ';\n' for g in maths]) + \
@@ -483,6 +489,8 @@ var asm = (function(global, env, buffer) {
var HEAPF64 = new global.Float64Array(buffer);
''' % (asm_setup,) + '\n' + asm_global_vars + '''
var __THREW__ = 0;
+ var threwValue = 0;
+ var setjmpId = 0;
var undef = 0;
var tempInt = 0, tempBigInt = 0, tempBigIntP = 0, tempBigIntS = 0, tempBigIntR = 0.0, tempBigIntI = 0, tempBigIntD = 0, tempValue = 0, tempDouble = 0.0;
''' + ''.join(['''
@@ -503,9 +511,13 @@ var asm = (function(global, env, buffer) {
top = top|0;
STACKTOP = top;
}
- function setThrew(threw) {
+ function setThrew(threw, value) {
threw = threw|0;
- __THREW__ = threw;
+ value = value|0;
+ if ((__THREW__|0) == 0) {
+ __THREW__ = threw;
+ threwValue = value;
+ }
}
''' + ''.join(['''
function setTempRet%d(value) {
@@ -643,6 +655,18 @@ def main(args, compiler_engine, cache, jcache, relooper, temp_files, DEBUG, DEBU
jcache=jcache, temp_files=temp_files, DEBUG=DEBUG, DEBUG_CACHE=DEBUG_CACHE)
def _main(environ):
+ response_file = True
+ while response_file:
+ response_file = None
+ for index in range(1, len(sys.argv)):
+ if sys.argv[index][0] == '@':
+ # found one, loop again next time
+ response_file = True
+ response_file_args = read_response_file(sys.argv[index])
+ # slice in extra_args in place of the response file arg
+ sys.argv[index:index+1] = response_file_args
+ break
+
parser = optparse.OptionParser(
usage='usage: %prog [-h] [-H HEADERS] [-o OUTFILE] [-c COMPILER_ENGINE] [-s FOO=BAR]* infile',
description=('You should normally never use this! Use emcc instead. '
diff --git a/src/analyzer.js b/src/analyzer.js
index 3921cab8..3278139b 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -324,12 +324,13 @@ function analyzer(data, sidePass) {
}
// call, return: Return the first 32 bits, the rest are in temp
case 'call': {
- bits = getBits(value.type);
- var elements = getLegalVars(item.assignTo, bits);
var toAdd = [value];
// legalize parameters
legalizeFunctionParameters(value.params);
+ // legalize return value, if any
if (value.assignTo && isIllegalType(item.type)) {
+ bits = getBits(value.type);
+ var elements = getLegalVars(item.assignTo, bits);
// legalize return value
value.assignTo = elements[0].ident;
for (var j = 1; j < elements.length; j++) {
@@ -1388,21 +1389,21 @@ function analyzer(data, sidePass) {
var line = label.lines[j];
if ((line.intertype == 'call' || line.intertype == 'invoke') && line.ident == setjmp) {
// Add a new label
- var oldIdent = label.ident;
- var newIdent = func.labelIdCounter++;
+ var oldLabel = label.ident;
+ var newLabel = func.labelIdCounter++;
if (!func.setjmpTable) func.setjmpTable = [];
- func.setjmpTable.push([oldIdent, newIdent, line.assignTo]);
+ func.setjmpTable.push({ oldLabel: oldLabel, newLabel: newLabel, assignTo: line.assignTo });
func.labels.splice(i+1, 0, {
intertype: 'label',
- ident: newIdent,
+ ident: newLabel,
lineNum: label.lineNum + 0.5,
lines: label.lines.slice(j+1)
});
- func.labelsDict[newIdent] = func.labels[i+1];
+ func.labelsDict[newLabel] = func.labels[i+1];
label.lines = label.lines.slice(0, j+1);
label.lines.push({
intertype: 'branch',
- label: toNiceIdent(newIdent),
+ label: toNiceIdent(newLabel),
lineNum: line.lineNum + 0.01, // XXX legalizing might confuse this
});
// Correct phis
@@ -1411,8 +1412,8 @@ function analyzer(data, sidePass) {
if (phi.intertype == 'phi') {
for (var i = 0; i < phi.params.length; i++) {
var sourceLabelId = getActualLabelId(phi.params[i].label);
- if (sourceLabelId == oldIdent) {
- phi.params[i].label = newIdent;
+ if (sourceLabelId == oldLabel) {
+ phi.params[i].label = newLabel;
}
}
}
diff --git a/src/embind/embind.js b/src/embind/embind.js
index d40d6ca2..988526b4 100644..100755
--- a/src/embind/embind.js
+++ b/src/embind/embind.js
@@ -1,14 +1,141 @@
/*global Module*/
/*global _malloc, _free, _memcpy*/
-/*global FUNCTION_TABLE, HEAP32*/
-/*global Pointer_stringify, writeStringToMemory*/
+/*global FUNCTION_TABLE, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32*/
+/*global readLatin1String*/
/*global __emval_register, _emval_handle_array, __emval_decref*/
+/*global ___getTypeName*/
+/*jslint sub:true*/ /* The symbols 'fromWireType' and 'toWireType' must be accessed via array notation to be closure-safe since craftInvokerFunction crafts functions as strings that can't be closured. */
+var InternalError = Module.InternalError = extendError(Error, 'InternalError');
+var BindingError = Module.BindingError = extendError(Error, 'BindingError');
+var UnboundTypeError = Module.UnboundTypeError = extendError(BindingError, 'UnboundTypeError');
+function throwInternalError(message) {
+ throw new InternalError(message);
+}
+
+function throwBindingError(message) {
+ throw new BindingError(message);
+}
+
+function throwUnboundTypeError(message, types) {
+ var unboundTypes = [];
+ var seen = {};
+ function visit(type) {
+ if (seen[type]) {
+ return;
+ }
+ if (registeredTypes[type]) {
+ return;
+ }
+ if (typeDependencies[type]) {
+ typeDependencies[type].forEach(visit);
+ return;
+ }
+ unboundTypes.push(type);
+ seen[type] = true;
+ }
+ types.forEach(visit);
+
+ throw new UnboundTypeError(message + ': ' + unboundTypes.map(getTypeName).join([', ']));
+}
+
+// Creates a function overload resolution table to the given method 'methodName' in the given prototype,
+// if the overload table doesn't yet exist.
+function ensureOverloadTable(proto, methodName, humanName) {
+ if (undefined === proto[methodName].overloadTable) {
+ var prevFunc = proto[methodName];
+ // Inject an overload resolver function that routes to the appropriate overload based on the number of arguments.
+ proto[methodName] = function() {
+ // TODO This check can be removed in -O3 level "unsafe" optimizations.
+ if (!proto[methodName].overloadTable.hasOwnProperty(arguments.length)) {
+ throwBindingError("Function '" + humanName + "' called with an invalid number of arguments (" + arguments.length + ") - expects one of (" + proto[methodName].overloadTable + ")!");
+ }
+ return proto[methodName].overloadTable[arguments.length].apply(this, arguments);
+ };
+ // Move the previous function into the overload table.
+ proto[methodName].overloadTable = [];
+ proto[methodName].overloadTable[prevFunc.argCount] = prevFunc;
+ }
+}
+
+/* Registers a symbol (function, class, enum, ...) as part of the Module JS object so that
+ hand-written code is able to access that symbol via 'Module.name'.
+ name: The name of the symbol that's being exposed.
+ value: The object itself to expose (function, class, ...)
+ numArguments: For functions, specifies the number of arguments the function takes in. For other types, unused and undefined.
+
+ To implement support for multiple overloads of a function, an 'overload selector' function is used. That selector function chooses
+ the appropriate overload to call from an function overload table. This selector function is only used if multiple overloads are
+ actually registered, since it carries a slight performance penalty. */
+function exposePublicSymbol(name, value, numArguments) {
+ if (Module.hasOwnProperty(name)) {
+ if (undefined === numArguments || (undefined !== Module[name].overloadTable && undefined !== Module[name].overloadTable[numArguments])) {
+ throwBindingError("Cannot register public name '" + name + "' twice");
+ }
+
+ // We are exposing a function with the same name as an existing function. Create an overload table and a function selector
+ // that routes between the two.
+ ensureOverloadTable(Module, name, name);
+ if (Module.hasOwnProperty(numArguments)) {
+ throwBindingError("Cannot register multiple overloads of a function with the same number of arguments (" + numArguments + ")!");
+ }
+ // Add the new function into the overload table.
+ Module[name].overloadTable[numArguments] = value;
+ }
+ else {
+ Module[name] = value;
+ if (undefined !== numArguments) {
+ Module[name].numArguments = numArguments;
+ }
+ }
+}
+
+function replacePublicSymbol(name, value, numArguments) {
+ if (!Module.hasOwnProperty(name)) {
+ throwInternalError('Replacing nonexistant public symbol');
+ }
+ // If there's an overload table for this symbol, replace the symbol in the overload table instead.
+ if (undefined !== Module[name].overloadTable && undefined !== numArguments) {
+ Module[name].overloadTable[numArguments] = value;
+ }
+ else {
+ Module[name] = value;
+ }
+}
+
+// from https://github.com/imvu/imvujs/blob/master/src/error.js
+function extendError(baseErrorType, errorName) {
+ var errorClass = createNamedFunction(errorName, function(message) {
+ this.name = errorName;
+ this.message = message;
+
+ var stack = (new Error(message)).stack;
+ if (stack !== undefined) {
+ this.stack = this.toString() + '\n' +
+ stack.replace(/^Error(:[^\n]*)?\n/, '');
+ }
+ });
+ errorClass.prototype = Object.create(baseErrorType.prototype);
+ errorClass.prototype.constructor = errorClass;
+ errorClass.prototype.toString = function() {
+ if (this.message === undefined) {
+ return this.name;
+ } else {
+ return this.name + ': ' + this.message;
+ }
+ };
+
+ return errorClass;
+}
+
+
+// from https://github.com/imvu/imvujs/blob/master/src/function.js
function createNamedFunction(name, body)