aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rwxr-xr-xemcc40
-rwxr-xr-xemscripten.py135
-rw-r--r--src/analyzer.js2
-rw-r--r--src/intertyper.js6
-rw-r--r--src/jsifier.js70
-rw-r--r--src/library.js188
-rw-r--r--src/library_gc.js13
-rw-r--r--src/library_gl.js3
-rw-r--r--src/modules.js33
-rw-r--r--src/parseTools.js27
-rw-r--r--src/preamble.js29
-rw-r--r--src/settings.js5
-rw-r--r--src/utility.js2
-rw-r--r--system/include/dlfcn.h9
-rw-r--r--system/include/emscripten/emscripten.h1
-rw-r--r--system/include/gc.h10
-rw-r--r--system/include/libc/limits.h9
-rw-r--r--system/include/libc/sys/_default_fcntl.h2
-rw-r--r--system/include/libc/sys/features.h4
-rw-r--r--system/include/libc/sys/resource.h1
-rw-r--r--system/include/libc/sys/signal.h1
-rw-r--r--system/include/net/netinet/in.h20
-rw-r--r--system/include/netdb.h3
-rw-r--r--system/include/sys/ioctl.h1
-rw-r--r--system/include/sys/poll.h1
-rw-r--r--system/include/sys/socket.h18
-rw-r--r--system/include/sys/statvfs.h2
-rw-r--r--system/include/sys/un.h65
-rw-r--r--tests/cases/gepoverflow.txt2
-rw-r--r--tests/gl_subdata.cpp141
-rw-r--r--tests/hello_libcxx_mod1.cpp9
-rwxr-xr-xtests/runner.py295
-rw-r--r--third_party/closure-compiler/README12
-rw-r--r--third_party/closure-compiler/compiler.jarbin5427247 -> 5856710 bytes
-rw-r--r--tools/eliminator/eliminator-test-output.js1
-rw-r--r--tools/eliminator/safe-eliminator-test-output.js1
-rw-r--r--tools/js-optimizer.js3
-rw-r--r--tools/js_optimizer.py176
-rw-r--r--tools/shared.py162
-rw-r--r--tools/test-js-optimizer-output.js1
-rw-r--r--tools/test-js-optimizer-regs-output.js1
-rw-r--r--tools/test-js-optimizer-t2-output.js1
-rw-r--r--tools/test-js-optimizer-t2c-output.js1
-rw-r--r--tools/test-js-optimizer-t3-output.js49
45 files changed, 1307 insertions, 249 deletions
diff --git a/AUTHORS b/AUTHORS
index 554d7bfd..a1e995c5 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -40,4 +40,5 @@ a license to everyone to use it as detailed in LICENSE.)
* Lars Schneider <lars.schneider@autodesk.com> (copyright owned by Autodesk, Inc.)
* Joel Martin <github@martintribe.org>
* Manuel Wellmann <manuel.wellmann@autodesk.com> (copyright owned by Autodesk, Inc.)
+* Xuejie Xiao <xxuejie@gmail.com>
diff --git a/emcc b/emcc
index 36bd5534..dc8bd630 100755
--- a/emcc
+++ b/emcc
@@ -116,7 +116,7 @@ shared.check_sanity(force=DEBUG)
if len(sys.argv) == 1:
print 'emcc: no input files'
- exit(0)
+ exit(1)
if sys.argv[1] == '--version':
print '''emcc (Emscripten GCC-like replacement) 2.0
@@ -327,6 +327,20 @@ Options that are modified or new in %s include:
llvm-link's behavior is not as permissive
as ld is.
+ --jcache Use a JavaScript cache. This is disabled by
+ default. When enabled, emcc will store the
+ results of compilation in a cache and check
+ the cache when compiling later, something
+ like what ccache does. This allows incremental
+ builds - where you are compiling a large
+ program but only modified a small part of it -
+ to be much faster (at the cost of more disk
+ IO for cache accesses). Note that you need
+ to enable --jcache for both loading and saving
+ of data, so you must enable it on a full build
+ for a later incremental build (where you also
+ enable it) to be sped up.
+
--clear-cache Manually clears the cache of compiled
emscripten system libraries (libc++,
libc++abi, dlmalloc). This is normally
@@ -336,7 +350,10 @@ Options that are modified or new in %s include:
mechanism can get confused. Clearing the
cache can fix weird problems related to
cache incompatibilities, like clang failing
- to link with library files.
+ to link with library files. This also clears
+ other cached data like the jcache and
+ the bootstrapped relooper. After the cache
+ is cleared, this process will exit.
The target file, if specified (-o <target>), defines what will
be generated:
@@ -571,6 +588,7 @@ try:
remove_duplicates = False
keep_debug = False
bind = False
+ jcache = False
def check_bad_eq(arg):
assert '=' not in arg, 'Invalid parameter (do not use "=" with "--" options)'
@@ -678,10 +696,14 @@ try:
elif newargs[i] == '--remove-duplicates':
remove_duplicates = True
newargs[i] = ''
+ elif newargs[i] == '--jcache':
+ jcache = True
+ newargs[i] = ''
elif newargs[i] == '--clear-cache':
newargs[i] = ''
print >> sys.stderr, 'emcc: clearing cache'
shared.Cache.erase()
+ sys.exit(0)
elif newargs[i].startswith(('-I/', '-L/')):
if not absolute_warning_shown:
print >> sys.stderr, 'emcc: warning: -I or -L of an absolute path encountered. If this is to a local system header/library, it may cause problems (local system files make sense for compiling natively on your system, but not necessarily to JavaScript)' # Of course an absolute path to a non-system-specific library or header is fine, and you can ignore this warning. The danger are system headers that are e.g. x86 specific and nonportable. The emscripten bundled headers are modified to be portable, local system ones are generally not
@@ -695,6 +717,8 @@ try:
minify_whitespace = closure # if closure is run, minify whitespace
if opt_level <= 0: keep_debug = True # always keep debug in -O0
+ if DEBUG: start_time = time.time() # done after parsing arguments, which might affect debug state
+
if closure:
assert os.path.exists(shared.CLOSURE_COMPILER), 'emcc: fatal: Closure compiler (%s) does not exist' % shared.CLOSURE_COMPILER
@@ -752,7 +776,8 @@ try:
else:
print >> sys.stderr, 'emcc: %s: warning: Not valid LLVM bitcode' % arg
else:
- print >> sys.stderr, 'emcc: %s: warning: No such file or directory' % arg
+ print >> sys.stderr, 'emcc: %s: error: No such file or directory' % arg
+ exit(1)
elif arg.startswith('-L'):
lib_dirs.append(arg[2:])
newargs[i] = ''
@@ -1044,6 +1069,7 @@ try:
# Emscripten
if DEBUG: print >> sys.stderr, 'emcc: LLVM => JS'
extra_args = [] if not js_libraries else ['--libraries', ','.join(map(os.path.abspath, js_libraries))]
+ if jcache: extra_args.append('--jcache')
final = shared.Building.emscripten(final, append_ext=False, extra_args=extra_args)
if DEBUG: save_intermediate('original')
@@ -1100,12 +1126,12 @@ try:
if len(js_optimizer_queue) > 0:
if DEBUG < 2:
if DEBUG: print >> sys.stderr, 'emcc: applying js optimization passes:', js_optimizer_queue
- final = shared.Building.js_optimizer(final, js_optimizer_queue)
+ final = shared.Building.js_optimizer(final, js_optimizer_queue, jcache)
if DEBUG: save_intermediate('js_opts')
else:
for name in js_optimizer_queue:
print >> sys.stderr, 'emcc: applying js optimization pass:', name
- final = shared.Building.js_optimizer(final, [name])
+ final = shared.Building.js_optimizer(final, [name], jcache)
save_intermediate(name)
js_optimizer_queue = []
@@ -1114,7 +1140,7 @@ try:
if DEBUG >= 2:
# Clean up the syntax a bit
- final = shared.Building.js_optimizer(final, [])
+ final = shared.Building.js_optimizer(final, [], jcache)
if DEBUG: save_intermediate('pretty')
def get_eliminate():
@@ -1221,6 +1247,8 @@ try:
# copy final JS to output
shutil.move(final, target)
+ if DEBUG: print >> sys.stderr, 'emcc: total time: %.2f seconds' % (time.time() - start_time)
+
finally:
if not TEMP_DIR:
try:
diff --git a/emscripten.py b/emscripten.py
index 91b1de5a..15beb4ee 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -32,6 +32,7 @@ def path_from_root(*pathelems):
temp_files = shared.TempFiles()
compiler_engine = None
+jcache = False
def scan(ll, settings):
# blockaddress(@main, %23)
@@ -47,12 +48,13 @@ MIN_CHUNK_SIZE = 1024*1024
MAX_CHUNK_SIZE = float(os.environ.get('EMSCRIPT_MAX_CHUNK_SIZE') or 'inf') # configuring this is just for debugging purposes
def process_funcs(args):
- i, ll, settings_file, compiler, forwarded_file, libraries = args
+ i, funcs, meta, settings_file, compiler, forwarded_file, libraries = args
+ ll = ''.join(funcs) + '\n' + meta
funcs_file = temp_files.get('.func_%d.ll' % i).name
open(funcs_file, 'w').write(ll)
out = shared.run_js(compiler, compiler_engine, [settings_file, funcs_file, 'funcs', forwarded_file] + libraries, stdout=subprocess.PIPE, cwd=path_from_root('src'))
shared.try_delete(funcs_file)
- return out.split('//FORWARDED_DATA:')
+ return out
def emscript(infile, settings, outfile, libraries=[]):
"""Runs the emscripten LLVM-to-JS compiler. We parallelize as much as possible
@@ -73,6 +75,8 @@ def emscript(infile, settings, outfile, libraries=[]):
if DEBUG: print >> sys.stderr, 'emscript: ll=>js'
+ if jcache: shared.JCache.ensure()
+
# Pre-scan ll and alter settings as necessary
if DEBUG: t = time.time()
ll = open(infile).read()
@@ -84,31 +88,31 @@ def emscript(infile, settings, outfile, libraries=[]):
# Split input into the relevant parts for each phase
pre = []
funcs = [] # split up functions here, for parallelism later
+ func_idents = []
meta = [] # needed by each function XXX
- post = []
if DEBUG: t = time.time()
in_func = False
ll_lines = open(infile).readlines()
for line in ll_lines:
if in_func:
- funcs[-1].append(line)
+ funcs[-1][1].append(line)
if line.startswith('}'):
in_func = False
- funcs[-1] = ''.join(funcs[-1])
+ funcs[-1] = (funcs[-1][0], ''.join(funcs[-1][1]))
pre.append(line) # pre needs it to, so we know about all implemented functions
else:
+ if line.startswith(';'): continue
if line.startswith('define '):
in_func = True
- funcs.append([line])
+ funcs.append((line, [line])) # use the entire line as the identifier
pre.append(line) # pre needs it to, so we know about all implemented functions
elif line.find(' = type { ') > 0:
pre.append(line) # type
elif line.startswith('!'):
meta.append(line) # metadata
else:
- post.append(line) # global
- pre.append(line) # pre needs it to, so we know about globals in pre and funcs
+ pre.append(line) # pre needs it so we know about globals in pre and funcs. So emit globals there
ll_lines = None
meta = ''.join(meta)
if DEBUG and len(meta) > 1024*1024: print >> sys.stderr, 'emscript warning: large amounts of metadata, will slow things down'
@@ -120,24 +124,32 @@ def emscript(infile, settings, outfile, libraries=[]):
# print >> sys.stderr, '========== funcs ===============\n'
# for func in funcs:
# print >> sys.stderr, '\n// ===\n\n', ''.join(func)
- # print >> sys.stderr, '========== post ==============\n'
- # print >> sys.stderr, ''.join(post)
# print >> sys.stderr, '=========================\n'
# Save settings to a file to work around v8 issue 1579
settings_file = temp_files.get('.txt').name
+ settings_text = json.dumps(settings)
s = open(settings_file, 'w')
- s.write(json.dumps(settings))
+ s.write(settings_text)
s.close()
# Phase 1 - pre
if DEBUG: t = time.time()
pre_file = temp_files.get('.pre.ll').name
- open(pre_file, 'w').write(''.join(pre) + '\n' + meta)
- out = shared.run_js(compiler, shared.COMPILER_ENGINE, [settings_file, pre_file, 'pre'] + libraries, stdout=subprocess.PIPE, cwd=path_from_root('src'))
- js, forwarded_data = out.split('//FORWARDED_DATA:')
- outfile.write(js)
- js = None
+ pre_input = ''.join(pre) + '\n' + meta
+ out = None
+ if jcache:
+ keys = [pre_input, settings_text, ','.join(libraries)]
+ shortkey = shared.JCache.get_shortkey(keys)
+ out = shared.JCache.get(shortkey, keys)
+ if out and DEBUG: print >> sys.stderr, ' loading pre from jcache'
+ if not out:
+ open(pre_file, 'w').write(pre_input)
+ out = shared.run_js(compiler, shared.COMPILER_ENGINE, [settings_file, pre_file, 'pre'] + libraries, stdout=subprocess.PIPE, cwd=path_from_root('src'))
+ if jcache:
+ if DEBUG: print >> sys.stderr, ' saving pre to jcache'
+ shared.JCache.set(shortkey, keys, out)
+ pre, forwarded_data = out.split('//FORWARDED_DATA:')
forwarded_file = temp_files.get('.json').name
open(forwarded_file, 'w').write(forwarded_data)
if DEBUG: print >> sys.stderr, ' emscript: phase 1 took %s seconds' % (time.time() - t)
@@ -157,28 +169,58 @@ def emscript(infile, settings, outfile, libraries=[]):
if DEBUG: t = time.time()
forwarded_json = json.loads(forwarded_data)
indexed_functions = set()
- chunks = [] # bundles of functions
- curr = ''
- for i in range(len(funcs)):
- func = funcs[i]
- if len(curr) + len(func) < chunk_size:
- curr += func
+
+ chunks = shared.JCache.chunkify(funcs, chunk_size, 'emscript_files' if jcache else None)
+
+ if jcache:
+ # load chunks from cache where we can # TODO: ignore small chunks
+ cached_outputs = []
+ def load_from_cache(chunk):
+ keys = [settings_text, forwarded_data, chunk]
+ shortkey = shared.JCache.get_shortkey(keys) # TODO: share shortkeys with later code
+ out = shared.JCache.get(shortkey, keys) # this is relatively expensive (pickling?)
+ if out:
+ cached_outputs.append(out)
+ return False
+ return True
+ chunks = filter(load_from_cache, chunks)
+ if len(cached_outputs) > 0:
+ if out and DEBUG: print >> sys.stderr, ' loading %d funcchunks from jcache' % len(cached_outputs)
else:
- chunks.append(curr)
- curr = func
- if curr:
- chunks.append(curr)
- curr = ''
+ cached_outputs = []
+
+ # TODO: minimize size of forwarded data from funcs to what we actually need
+
if cores == 1 and total_ll_size < MAX_CHUNK_SIZE: assert len(chunks) == 1, 'no point in splitting up without multiple cores'
- if DEBUG: print >> sys.stderr, ' emscript: phase 2 working on %d chunks %s (intended chunk size: %.2f MB, meta: %.2f MB, forwarded: %.2f MB, total: %.2f MB)' % (len(chunks), ('using %d cores' % cores) if len(chunks) > 1 else '', chunk_size/(1024*1024.), len(meta)/(1024*1024.), len(forwarded_data)/(1024*1024.), total_ll_size/(1024*1024.))
- commands = [(i, chunks[i] + '\n' + meta, settings_file, compiler, forwarded_file, libraries) for i in range(len(chunks))]
+ if len(chunks) > 0:
+ if DEBUG: print >> sys.stderr, ' emscript: phase 2 working on %d chunks %s (intended chunk size: %.2f MB, meta: %.2f MB, forwarded: %.2f MB, total: %.2f MB)' % (len(chunks), ('using %d cores' % cores) if len(chunks) > 1 else '', chunk_size/(1024*1024.), len(meta)/(1024*1024.), len(forwarded_data)/(1024*1024.), total_ll_size/(1024*1024.))
+
+ commands = [(i, chunks[i], meta, settings_file, compiler, forwarded_file, libraries) for i in range(len(chunks))]
- if len(chunks) > 1:
- pool = multiprocessing.Pool(processes=cores)
- outputs = pool.map(process_funcs, commands, chunksize=1)
+ if len(chunks) > 1:
+ pool = multiprocessing.Pool(processes=cores)
+ outputs = pool.map(process_funcs, commands, chunksize=1)
+ elif len(chunks) == 1:
+ outputs = [process_funcs(commands[0])]
else:
- outputs = [process_funcs(commands[0])]
+ outputs = []
+
+ if jcache:
+ # save chunks to cache
+ for i in range(len(chunks)):
+ chunk = chunks[i]
+ keys = [settings_text, forwarded_data, chunk]
+ shortkey = shared.JCache.get_shortkey(keys)
+ shared.JCache.set(shortkey, keys, outputs[i])
+ if out and DEBUG and len(chunks) > 0: print >> sys.stderr, ' saving %d funcchunks to jcache' % len(chunks)
+
+ if jcache: outputs += cached_outputs # TODO: preserve order
+
+ outputs = [output.split('//FORWARDED_DATA:') for output in outputs]
+
+ if DEBUG: print >> sys.stderr, ' emscript: phase 2 took %s seconds' % (time.time() - t)
+ if DEBUG: t = time.time()
funcs_js = ''.join([output[0] for output in outputs])
@@ -191,7 +233,7 @@ def emscript(infile, settings, outfile, libraries=[]):
for key in curr_forwarded_json['Functions']['indexedFunctions'].iterkeys():
indexed_functions.add(key)
outputs = None
- if DEBUG: print >> sys.stderr, ' emscript: phase 2 took %s seconds' % (time.time() - t)
+ if DEBUG: print >> sys.stderr, ' emscript: phase 2b took %s seconds' % (time.time() - t)
if DEBUG: t = time.time()
# calculations on merged forwarded data
@@ -201,23 +243,35 @@ def emscript(infile, settings, outfile, libraries=[]):
forwarded_json['Functions']['indexedFunctions'][indexed] = i # make sure not to modify this python object later - we use it in indexize
i += 2
forwarded_json['Functions']['nextIndex'] = i
+
indexing = forwarded_json['Functions']['indexedFunctions']
def indexize(js):
return re.sub(r'{{{ FI_([\w\d_$]+) }}}', lambda m: str(indexing[m.groups(0)[0]]), js)
- outfile.write(indexize(funcs_js))
+
+ blockaddrs = forwarded_json['Functions']['blockAddresses']
+ def blockaddrsize(js):
+ return re.sub(r'{{{ BA_([\w\d_$]+)\|([\w\d_$]+) }}}', lambda m: str(blockaddrs[m.groups(0)[0]][m.groups(0)[1]]), js)
+
+ #if DEBUG: outfile.write('// pre\n')
+ outfile.write(blockaddrsize(indexize(pre)))
+ pre = None
+
+ #if DEBUG: outfile.write('// funcs\n')
+ outfile.write(blockaddrsize(indexize(funcs_js)))
funcs_js = None
# forward
forwarded_data = json.dumps(forwarded_json)
forwarded_file = temp_files.get('.2.json').name
- open(forwarded_file, 'w').write(forwarded_data)
- if DEBUG: print >> sys.stderr, ' emscript: phase 2b took %s seconds' % (time.time() - t)
+ open(forwarded_file, 'w').write(indexize(forwarded_data))
+ if DEBUG: print >> sys.stderr, ' emscript: phase 2c took %s seconds' % (time.time() - t)
# Phase 3 - post
if DEBUG: t = time.time()
post_file = temp_files.get('.post.ll').name
- open(post_file, 'w').write(''.join(post) + '\n' + meta)
+ open(post_file, 'w').write('\n') # no input, just processing of forwarded data
out = shared.run_js(compiler, shared.COMPILER_ENGINE, [settings_file, post_file, 'post', forwarded_file] + libraries, stdout=subprocess.PIPE, cwd=path_from_root('src'))
+ #if DEBUG: outfile.write('// post\n')
outfile.write(indexize(out))
if DEBUG: print >> sys.stderr, ' emscript: phase 3 took %s seconds' % (time.time() - t)
@@ -329,6 +383,10 @@ if __name__ == '__main__':
metavar='FOO=BAR',
help=('Overrides for settings defined in settings.js. '
'May occur multiple times.'))
+ parser.add_option('-j', '--jcache',
+ action='store_true',
+ default=False,
+ help=('Enable jcache (ccache-like caching of compilation results, for faster incremental builds).'))
# Convert to the same format that argparse would have produced.
keywords, positional = parser.parse_args()
@@ -338,6 +396,7 @@ if __name__ == '__main__':
if isinstance(keywords.outfile, basestring):
keywords.outfile = open(keywords.outfile, 'w')
compiler_engine = keywords.compiler
+ jcache = keywords.jcache
temp_files.run_and_clean(lambda: main(keywords))
diff --git a/src/analyzer.js b/src/analyzer.js
index c09739e9..014579f4 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -690,6 +690,8 @@ function analyzer(data, sidePass) {
var subType = check[2];
addTypeInternal(subType, data); // needed for anonymous structure definitions (see below)
+ // Huge structural types are represented very inefficiently, both here and in generated JS. Best to avoid them - for example static char x[10*1024*1024]; is bad, while static char *x = malloc(10*1024*1024) is fine.
+ if (num >= 10*1024*1024) warnOnce('warning: very large fixed-size structural type: ' + type + ' - can you reduce it? (compilation may be slow)');
Types.types[nonPointing] = {
name_: nonPointing,
fields: range(num).map(function() { return subType }),
diff --git a/src/intertyper.js b/src/intertyper.js
index fbad353a..8e7bb418 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -165,7 +165,7 @@ function intertyper(data, sidePass, baseLineNums) {
function makeToken(text) {
if (text.length == 0) return;
// merge certain tokens
- if (lastToken && ( (lastToken.text == '%' && text[0] == '"') || /^\**$/.exec(text) ) ) {
+ if (lastToken && ( (lastToken.text == '%' && text[0] == '"') || /^\**$/.test(text) ) ) {
lastToken.text += text;
return;
}
@@ -182,7 +182,7 @@ function intertyper(data, sidePass, baseLineNums) {
// merge certain tokens
if (lastToken && isType(lastToken.text) && isFunctionDef(token)) {
lastToken.text += ' ' + text;
- } else if (lastToken && /^}\**$/.exec(text)) { // }, }*, etc.
+ } else if (lastToken && text[0] == '}') { // }, }*, etc.
var openBrace = tokens.length-1;
while (tokens[openBrace].text.substr(-1) != '{') openBrace --;
token = combineTokens(tokens.slice(openBrace+1));
@@ -674,7 +674,7 @@ function intertyper(data, sidePass, baseLineNums) {
// Inline assembly is just JavaScript that we paste into the code
item.intertype = 'value';
if (tokensLeft[0].text == 'sideeffect') tokensLeft.splice(0, 1);
- item.ident = tokensLeft[0].text.substr(1, tokensLeft[0].text.length-2);
+ item.ident = tokensLeft[0].text.substr(1, tokensLeft[0].text.length-2) || ';'; // use ; for empty inline assembly
return { forward: null, ret: [item], item: item };
}
if (item.ident.substr(-2) == '()') {
diff --git a/src/jsifier.js b/src/jsifier.js
index fae92f70..595e057c 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -65,24 +65,27 @@ function JSify(data, functionsOnly, givenFunctions) {
// Add additional necessary items for the main pass. We can now do this since types are parsed (types can be used through
// generateStructInfo in library.js)
LibraryManager.load();
- var libFuncsToInclude;
- if (INCLUDE_FULL_LIBRARY) {
- assert(!BUILD_AS_SHARED_LIB, 'Cannot have both INCLUDE_FULL_LIBRARY and BUILD_AS_SHARED_LIB set.')
- libFuncsToInclude = [];
- for (var key in LibraryManager.library) {
- if (!key.match(/__(deps|postset|inline)$/)) {
- libFuncsToInclude.push(key);
+
+ if (phase == 'pre') {
+ var libFuncsToInclude;
+ if (INCLUDE_FULL_LIBRARY) {
+ assert(!BUILD_AS_SHARED_LIB, 'Cannot have both INCLUDE_FULL_LIBRARY and BUILD_AS_SHARED_LIB set.')
+ libFuncsToInclude = [];
+ for (var key in LibraryManager.library) {
+ if (!key.match(/__(deps|postset|inline)$/)) {
+ libFuncsToInclude.push(key);
+ }
}
+ } else {
+ libFuncsToInclude = DEFAULT_LIBRARY_FUNCS_TO_INCLUDE;
}
- } else {
- libFuncsToInclude = DEFAULT_LIBRARY_FUNCS_TO_INCLUDE;
- }
- libFuncsToInclude.forEach(function(ident) {
- data.functionStubs.push({
- intertype: 'functionStub',
- ident: '_' + ident
+ libFuncsToInclude.forEach(function(ident) {
+ data.functionStubs.push({
+ intertype: 'functionStub',
+ ident: '_' + ident
+ });
});
- });
+ }
}
// Functions
@@ -329,7 +332,7 @@ function JSify(data, functionsOnly, givenFunctions) {
if (item.ident.substr(0, 5) == '__ZTV') {
js += '\n' + makePointer('[0]', null, BUILD_AS_SHARED_LIB ? 'ALLOC_NORMAL' : 'ALLOC_STATIC', ['void*']) + ';';
}
- if (item.ident in EXPORTED_GLOBALS) {
+ if (EXPORT_ALL || (item.ident in EXPORTED_GLOBALS)) {
js += '\nModule["' + item.ident + '"] = ' + item.ident + ';';
}
if (BUILD_AS_SHARED_LIB == 2 && !item.private_) {
@@ -439,7 +442,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
var text = (deps ? '\n' + deps.map(addFromLibrary).filter(function(x) { return x != '' }).join('\n') : '');
text += isFunction ? snippet : 'var ' + ident + '=' + snippet + ';';
- if (ident in EXPORTED_FUNCTIONS) {
+ if (EXPORT_ALL || (ident in EXPORTED_FUNCTIONS)) {
text += '\nModule["' + ident + '"] = ' + ident + ';';
}
return text;
@@ -616,6 +619,7 @@ function JSify(data, functionsOnly, givenFunctions) {
} // otherwise, should have been set before!
if (func.setjmpTable) {
var setjmpTable = {};
+ ret += indent + 'var setjmped = false;'; // set to true if we setjmp in this invocation
ret += indent + 'var setjmpTable = {';
func.setjmpTable.forEach(function(triple) { // original label, label we created for right after the setjmp, variable setjmp result goes into
ret += '"' + getLabelId(triple[0]) + '": ' + 'function(value) { label = ' + getLabelId(triple[1]) + '; ' + triple[2] + ' = value },';
@@ -634,7 +638,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}).join('\n');
ret += '\n' + indent + ' default: assert(0, "bad label: " + label);\n' + indent + '}';
if (func.setjmpTable) {
- ret += ' } catch(e) { if (!e.longjmp) throw(e); setjmpTable[e.label](e.value) }';
+ ret += ' } catch(e) { if (!setjmped) throw(e); if (!e.longjmp) throw(e); setjmpTable[e.label](e.value) }';
}
} else {
ret += (SHOW_LABELS ? indent + '/* ' + block.entries[0] + ' */' : '') + '\n' + getLabelLines(block.labels[0], indent);
@@ -699,7 +703,7 @@ function JSify(data, functionsOnly, givenFunctions) {
func.JS += '\n//FUNCTION_END_MARKER_OF_SOURCE_FILE_' + associatedSourceFile + '\n';
}
- if (func.ident in EXPORTED_FUNCTIONS) {
+ if (EXPORT_ALL || (func.ident in EXPORTED_FUNCTIONS)) {
func.JS += 'Module["' + func.ident + '"] = ' + func.ident + ';';
}
@@ -1066,12 +1070,12 @@ function JSify(data, functionsOnly, givenFunctions) {
var param1 = finalizeLLVMParameter(item.params[0]);
var param2 = finalizeLLVMParameter(item.params[1]);
switch (item.op) {
- case 'add': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue+' + param2, type) + ',tempValue)';
- case 'sub': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue-' + param2, type) + ',tempValue)';
- case 'xchg': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, param2, type) + ',tempValue)';
+ case 'add': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue+' + param2, type, null, null, null, null, ',') + ',tempValue)';
+ case 'sub': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue-' + param2, type, null, null, null, null, ',') + ',tempValue)';
+ case 'xchg': return '(t