aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS3
-rw-r--r--ChangeLog28
-rwxr-xr-xemcc16
-rwxr-xr-xemmake2
-rwxr-xr-xemscripten.py488
-rw-r--r--src/compiler.js28
-rw-r--r--src/intertyper.js25
-rw-r--r--src/jsifier.js38
-rw-r--r--src/library.js104
-rw-r--r--src/library_browser.js19
-rw-r--r--src/library_gl.js837
-rw-r--r--src/library_sdl.js29
-rw-r--r--src/library_sockfs.js2
-rw-r--r--src/modules.js6
-rw-r--r--src/parseTools.js34
-rw-r--r--src/preamble.js18
-rw-r--r--src/relooper/Relooper.cpp9
-rw-r--r--src/runtime.js5
-rw-r--r--src/settings.js7
-rw-r--r--src/shell.html2
-rw-r--r--src/shell.js2
-rw-r--r--src/simd.js1031
-rw-r--r--system/include/emscripten/emmintrin.h87
-rw-r--r--system/include/emscripten/vector.h20
-rw-r--r--system/include/emscripten/xmmintrin.h131
-rw-r--r--tests/embind/shell.html2
-rw-r--r--tests/hello_world_worker.cpp10
-rw-r--r--tests/pthread/specific.c8
-rw-r--r--tests/pthread/specific.c.txt2
-rw-r--r--tests/sdl_canvas_size.html2
-rw-r--r--tests/sdl_joystick.c4
-rw-r--r--tests/test_browser.py21
-rw-r--r--tests/test_core.py517
-rw-r--r--tests/test_other.py62
-rw-r--r--tools/cache.py12
-rw-r--r--tools/file_packager.py8
-rw-r--r--tools/jsrun.py2
-rw-r--r--tools/shared.py34
38 files changed, 2755 insertions, 900 deletions
diff --git a/AUTHORS b/AUTHORS
index 6a28c205..b03bfe7b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -108,3 +108,6 @@ a license to everyone to use it as detailed in LICENSE.)
* Ben Noordhuis <info@bnoordhuis.nl>
* Bob Roberts <bobroberts177@gmail.com>
* John Vilk <jvilk@cs.umass.edu>
+* Daniel Baulig <dbaulig@fb.com> (copyright owned by Facebook, Inc.)
+* Lu Wang <coolwanglu@gmail.com>
+* Heidi Pan <heidi.pan@intel.com> (copyright owned by Intel)
diff --git a/ChangeLog b/ChangeLog
index 94a24675..cab1d74a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,8 +9,32 @@ Not all changes are documented here. In particular, new features, user-oriented
Current trunk code
------------------
- - To see a list of commits that in the active development branch 'incoming', which have not yet been packaged in a release, see
- https://github.com/kripken/emscripten/compare/1.7.5...incoming
+ - To see a list of commits in the active development branch 'incoming', which have not yet been packaged in a release, see
+ https://github.com/kripken/emscripten/compare/1.7.8...incoming
+
+v1.7.8: 11/19/2013
+------------------
+ - Fixed an issue with -MMD compilation parameter.
+ - Added EM_ASM_INT() and EM_ASM_DOUBLE() macros. For more information, read https://groups.google.com/forum/#!topic/emscripten-discuss/BFGTJPCgO6Y .
+ - Fixed --split parameter to also work on Windows.
+ - Fixed issues with BSD sockets accept() call.
+ - Full list of changes: https://github.com/kripken/emscripten/compare/1.7.7...1.7.8
+
+v1.7.7: 11/16/2013
+------------------
+ - Improve SDL audio buffer queue timing support.
+ - Improved default precision of clock_gettime even when not using CLOCK_REALTIME.
+ - Optimize and fix issues with LLVM IR processing.
+ - Full list of changes: https://github.com/kripken/emscripten/compare/1.7.6...1.7.7
+
+v1.7.6: 11/15/2013
+------------------
+ - Added regex implementation from musl libc.
+ - The command line parameter -s DEAD_FUNCTIONS=[] can now be used to explicitly kill functions coming from built-in library_xx.js.
+ - Improved EGL support and GLES2 spec conformance.
+ - Reverted -s TOTAL_MEMORY=x to require pow2 values, instead of the relaxed 'multiples of 16MB'. This is because the relaxed rule is released only in Firefox 26 which which is currently in Beta and ships on the week of December 10th (currently in Beta). As of writing, current stable Firefox 25 does not yet support these.
+ - Adjusted the default linker behavior to warn about all missing symbols, instead of silently ignoring them. Use -s WARN_ON_UNDEFINED_SYMBOLS=0 to suppress these warnings if necessary.
+ - Full list of changes: https://github.com/kripken/emscripten/compare/1.7.5...1.7.6
v1.7.5: 11/13/2013
------------------
diff --git a/emcc b/emcc
index 008468a1..029d60a1 100755
--- a/emcc
+++ b/emcc
@@ -53,8 +53,9 @@ from tools import shared, jsrun
from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename, WINDOWS
from tools.response_file import read_response_file
-CXX_SUFFIXES = ('.cpp', '.cxx', '.cc')
-SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc', '.m', '.mm')
+C_SUFFIXES = ('.c', '.C')
+CXX_SUFFIXES = ('.cpp', '.cxx', '.cc', '.CPP', '.CXX', '.CC')
+SOURCE_SUFFIXES = C_SUFFIXES + CXX_SUFFIXES + ('.m', '.mm')
BITCODE_SUFFIXES = ('.bc', '.o', '.obj')
DYNAMICLIB_SUFFIXES = ('.dylib', '.so', '.dll')
STATICLIB_SUFFIXES = ('.a',)
@@ -1274,7 +1275,16 @@ try:
shutil.move(in_temp(unsuffixed(uniquename(input_file)) + '.o'), unsuffixed_basename(input_file) + '.' + final_suffix)
else:
if len(input_files) == 1:
- shutil.move(in_temp(unsuffixed(uniquename(input_files[0])) + '.o'), specified_target)
+ temp_output_base = in_temp(unsuffixed(uniquename(input_files[0])))
+ shutil.move(temp_output_base + '.o', specified_target)
+ if os.path.exists(temp_output_base + '.d'):
+ # There was a .d file generated, from -MD or -MMD and friends, save a copy of it to where the output resides,
+ # adjusting the target name away from the temporary file name to the specified target.
+ # It will be deleted with the rest of the temporary directory.
+ deps = open(temp_output_base + '.d').read()
+ deps = deps.replace(temp_output_base + '.o', specified_target)
+ with open(os.path.join(os.path.dirname(specified_target), os.path.basename(unsuffixed(input_files[0]) + '.d')), "w") as out_dep:
+ out_dep.write(deps)
else:
assert len(original_input_files) == 1 or not has_dash_c, 'fatal error: cannot specify -o with -c with multiple files' + str(sys.argv) + ':' + str(original_input_files)
# We have a specified target (-o <target>), which is not JavaScript or HTML, and
diff --git a/emmake b/emmake
index 18e6afa9..e8f34f41 100755
--- a/emmake
+++ b/emmake
@@ -6,7 +6,7 @@ the environment variables to use emcc and so forth. Usage:
emmake make [FLAGS]
-Not that if you ran configure with emconfigure, then
+Note that if you ran configure with emconfigure, then
the environment variables have already been detected
and set. This script is useful if you have no configure
step, and your Makefile uses the environment vars
diff --git a/emscripten.py b/emscripten.py
index 75e6711a..907e88ce 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -9,7 +9,7 @@ header files (so that the JS compiler can see the constants in those
headers, for the libc implementation in JS).
'''
-import os, sys, json, optparse, subprocess, re, time, multiprocessing, string, logging
+import os, sys, json, optparse, subprocess, re, time, multiprocessing, string, logging, shutil
from tools import shared
from tools import jsrun, cache as cache_module, tempfiles
@@ -706,6 +706,492 @@ Runtime.stackRestore = function(top) { asm['stackRestore'](top) };
outfile.close()
+# emscript_fast: emscript'en code using the 'fast' compilation path, using
+# an LLVM backend
+# FIXME: this is just a copy-paste of normal emscript(), and we trample it
+# if the proper env var is set (see below). we should refactor to
+# share code between the two, once emscript_fast stabilizes (or,
+# leaving it separate like it is will make it trivial to rip out
+# if the experiment fails)
+
+def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
+ jcache=None, temp_files=None, DEBUG=None, DEBUG_CACHE=None):
+ """Runs the emscripten LLVM-to-JS compiler. We parallelize as much as possible
+
+ Args:
+ infile: The path to the input LLVM assembly file.
+ settings: JSON-formatted settings that override the values
+ defined in src/settings.js.
+ outfile: The file where the output is written.
+ """
+
+ assert(settings['ASM_JS']) # TODO: apply ASM_JS even in -O0 for fastcomp
+ assert(settings['RUNNING_JS_OPTS'])
+
+ # Overview:
+ # * Run LLVM backend to emit JS. JS includes function bodies, memory initializer,
+ # and various metadata
+ # * Run compiler.js on the metadata to emit the shell js code, pre/post-ambles,
+ # JS library dependencies, etc.
+
+ if DEBUG: logging.debug('emscript: llvm backend')
+
+ # TODO: proper temp files
+ # TODO: use a single LLVM toolchain instead of normal for source, pnacl for simplification, custom for js backend
+
+ if DEBUG: shutil.copyfile(infile, os.path.join(shared.CANONICAL_TEMP_DIR, 'temp0.ll'))
+
+ if DEBUG: logging.debug(' ..1..')
+ temp1 = temp_files.get('.1.bc').name
+ shared.jsrun.timeout_run(subprocess.Popen([os.path.join(shared.LLVM_ROOT, 'opt'), infile, '-pnacl-abi-simplify-preopt', '-o', temp1]))
+ assert os.path.exists(temp1)
+ if DEBUG:
+ shutil.copyfile(temp1, os.path.join(shared.CANONICAL_TEMP_DIR, 'temp1.bc'))
+ shared.jsrun.timeout_run(subprocess.Popen([os.path.join(shared.LLVM_ROOT, 'llvm-dis'), 'temp1.bc', '-o', 'temp1.ll']))
+
+ #if DEBUG: logging.debug(' ..2..')
+ #temp2 = temp_files.get('.2.bc').name
+ #shared.jsrun.timeout_run(subprocess.Popen([os.path.join(shared.LLVM_ROOT, 'opt'), temp1, '-O3', '-o', temp2]))
+ #assert os.path.exists(temp2)
+ #if DEBUG:
+ # shutil.copyfile(temp2, os.path.join(shared.CANONICAL_TEMP_DIR, 'temp2.bc'))
+ # shared.jsrun.timeout_run(subprocess.Popen([os.path.join(shared.LLVM_ROOT, 'llvm-dis'), 'temp2.bc', '-o', 'temp2.ll']))
+ temp2 = temp1 # XXX if we optimize the bc, we remove some pnacl clutter, but it also makes varargs stores be 8-byte aligned
+
+ if DEBUG: logging.debug(' ..3..')
+ temp3 = temp_files.get('.3.bc').name
+ shared.jsrun.timeout_run(subprocess.Popen([os.path.join(shared.LLVM_ROOT, 'opt'), temp2, '-pnacl-abi-simplify-postopt', '-o', temp3]))
+ assert os.path.exists(temp3)
+ if DEBUG:
+ shutil.copyfile(temp3, os.path.join(shared.CANONICAL_TEMP_DIR, 'temp3.bc'))
+ shared.jsrun.timeout_run(subprocess.Popen([os.path.join(shared.LLVM_ROOT, 'llvm-dis'), 'temp3.bc', '-o', 'temp3.ll']))
+
+ if DEBUG: logging.debug(' ..4..')
+ temp4 = temp_files.get('.4.js').name
+ backend_compiler = os.path.join(shared.LLVM_ROOT, 'llc')
+ shared.jsrun.timeout_run(subprocess.Popen([backend_compiler, temp3, '-march=js', '-filetype=asm', '-o', temp4], stdout=subprocess.PIPE))
+ if DEBUG: shutil.copyfile(temp4, os.path.join(shared.CANONICAL_TEMP_DIR, 'temp4.js'))
+
+ # Split up output
+ backend_output = open(temp4).read()
+ #if DEBUG: print >> sys.stderr, backend_output
+
+ start_funcs_marker = '// EMSCRIPTEN_START_FUNCTIONS'
+ end_funcs_marker = '// EMSCRIPTEN_END_FUNCTIONS'
+ metadata_split_marker = '// EMSCRIPTEN_METADATA'
+
+ start_funcs = backend_output.index(start_funcs_marker)
+ end_funcs = backend_output.rindex(end_funcs_marker)
+ metadata_split = backend_output.rindex(metadata_split_marker)
+
+ funcs = backend_output[start_funcs+len(start_funcs_marker):end_funcs]
+ metadata_raw = backend_output[metadata_split+len(metadata_split_marker):]
+ #if DEBUG: print >> sys.stderr, "METAraw", metadata_raw
+ metadata = json.loads(metadata_raw)
+ mem_init = backend_output[end_funcs+len(end_funcs_marker):metadata_split]
+ #if DEBUG: print >> sys.stderr, "FUNCS", funcs
+ #if DEBUG: print >> sys.stderr, "META", metadata
+ #if DEBUG: print >> sys.stderr, "meminit", mem_init
+
+ # function table masks
+
+ table_sizes = {}
+ for k, v in metadata['tables'].iteritems():
+ table_sizes[k] = str(v.count(',')) # undercounts by one, but that is what we want
+ funcs = re.sub(r"#FM_(\w+)#", lambda m: table_sizes[m.groups(0)[0]], funcs)
+
+ # js compiler
+
+ if DEBUG: logging.debug('emscript: js compiler glue')
+
+ # Integrate info from backend
+ settings['DEFAULT_LIBRARY_FUNCS_TO_INCLUDE'] = list(
+ set(settings['DEFAULT_LIBRARY_FUNCS_TO_INCLUDE'] + map(shared.JS.to_nice_ident, metadata['declares'])).difference(
+ map(lambda x: x[1:], metadata['implementedFunctions'])
+ )
+ ) + map(lambda x: x[1:], metadata['externs'])
+
+ # Settings changes
+ assert settings['TARGET_LE32'] == 1
+ settings['TARGET_LE32'] = 2
+
+ # Save settings to a file to work around v8 issue 1579
+ settings_file = temp_files.get('.txt').name
+ def save_settings():
+ global settings_text
+ settings_text = json.dumps(settings, sort_keys=True)
+ s = open(settings_file, 'w')
+ s.write(settings_text)
+ s.close()
+ save_settings()
+
+ # Call js compiler
+ if DEBUG: t = time.time()
+ out = jsrun.run_js(path_from_root('src', 'compiler.js'), compiler_engine, [settings_file, ';', 'glue'] + libraries, stdout=subprocess.PIPE, stderr=STDERR_FILE,
+ cwd=path_from_root('src'))
+ assert '//FORWARDED_DATA:' in out, 'Did not receive forwarded data in pre output - process failed?'
+ glue, forwarded_data = out.split('//FORWARDED_DATA:')
+
+ #print >> sys.stderr, out
+
+ last_forwarded_json = forwarded_json = json.loads(forwarded_data)
+
+ # merge in information from llvm backend
+
+ last_forwarded_json['Functions']['tables'] = metadata['tables']
+
+ '''indexed_functions = set()
+ for key in forwarded_json['Functions']['indexedFunctions'].iterkeys():
+ indexed_functions.add(key)'''
+
+ pre, post = glue.split('// EMSCRIPTEN_END_FUNCS')
+
+ #print >> sys.stderr, 'glue:', pre, '\n\n||||||||||||||||\n\n', post, '...............'
+
+ # memory and global initializers
+
+ global_initializers = ', '.join(map(lambda i: '{ func: function() { %s() } }' % i, metadata['initializers']))
+
+ pre = pre.replace('STATICTOP = STATIC_BASE + 0;', '''STATICTOP = STATIC_BASE + Runtime.alignMemory(%d);
+/* global initializers */ __ATINIT__.push(%s);
+%s''' % (mem_init.count(',')+1, global_initializers, mem_init)) # XXX wrong size calculation!
+
+ funcs_js = [funcs]
+ if settings.get('ASM_JS'):
+ parts = pre.split('// ASM_LIBRARY FUNCTIONS\n')
+ if len(parts) > 1:
+ pre = parts[0]
+ funcs_js.append(parts[1])
+
+ # calculations on merged forwarded data TODO
+
+ # merge forwarded data
+ assert settings.get('ASM_JS'), 'fastcomp is asm.js only'
+ settings['EXPORTED_FUNCTIONS'] = forwarded_json['EXPORTED_FUNCTIONS']
+ all_exported_functions = set(settings['EXPORTED_FUNCTIONS']) # both asm.js and otherwise
+ for additional_export in settings['DEFAULT_LIBRARY_FUNCS_TO_INCLUDE']: # additional functions to export from asm, if they are implemented
+ all_exported_functions.add('_' + additional_export)
+ exported_implemented_functions = set()
+ export_bindings = settings['EXPORT_BINDINGS']
+ export_all = settings['EXPORT_ALL']
+ for key in metadata['implementedFunctions'] + forwarded_json['Functions']['implementedFunctions'].keys(): # XXX perf
+ if key in all_exported_functions or export_all or (export_bindings and key.startswith('_emscripten_bind')):
+ exported_implemented_functions.add(key)
+
+ #if DEBUG: outfile.write('// pre\n')
+ outfile.write(pre)
+ pre = None
+
+ #if DEBUG: outfile.write('// funcs\n')
+
+ if settings.get('ASM_JS'):
+ #print >> sys.stderr, '<<<<<<', post, '>>>>>>'
+ 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')
+ class Counter:
+ i = 0
+ j = 0
+ if 'pre' in last_forwarded_json['Functions']['tables']:
+ pre_tables = last_forwarded_json['Functions']['tables']['pre']
+ del last_forwarded_json['Functions']['tables']['pre']
+ else:
+ pre_tables = ''
+
+ def make_table(sig, raw):
+ i = Counter.i
+ Counter.i += 1
+ bad = 'b' + str(i)
+ params = ','.join(['p%d' % p for p in range(len(sig)-1)])
+ coercions = ';'.join(['p%d = %s' % (p, shared.JS.make_coercion('p%d' % p, sig[p+1], settings)) for p in range(len(sig)-1)]) + ';'
+ ret = '' if sig[0] == 'v' else ('return %s' % shared.JS.make_initializer(sig[0], settings))
+ start = raw.index('[')
+ end = raw.rindex(']')
+ body = raw[start+1:end].split(',')
+ for j in range(settings['RESERVED_FUNCTION_POINTERS']):
+ body[settings['FUNCTION_POINTER_ALIGNMENT'] * (1 + j)] = 'jsCall_%s_%s' % (sig, j)
+ Counter.j = 0
+ def fix_item(item):
+ Counter.j += 1
+ newline = Counter.j % 30 == 29
+ if item == '0': return bad if not newline else (bad + '\n')
+ return item if not newline else (item + '\n')
+ body = ','.join(map(fix_item, body))
+ return ('function %s(%s) { %s %s(%d); %s }' % (bad, params, coercions, 'abort' if not settings['ASSERTIONS'] else 'nullFunc', i, ret), ''.join([raw[:start+1], body, raw[end:]]))
+
+ infos = [make_table(sig, raw) for sig, raw in last_forwarded_json['Functions']['tables'].iteritems()]
+
+ function_tables_defs = '\n'.join([info[0] for info in infos]) + '\n// EMSCRIPTEN_END_FUNCS\n' + '\n'.join([info[1] for info in infos])
+
+ asm_setup = ''
+ maths = ['Math.' + func for func in ['floor', 'abs', 'sqrt', 'pow', 'cos', 'sin', 'tan', 'acos', 'asin', 'atan', 'atan2', 'exp', 'log', 'ceil', 'imul']]
+ fundamentals = ['Math', 'Int8Array', 'Int16Array', 'Int32Array', 'Uint8Array', 'Uint16Array', 'Uint32Array', 'Float32Array', 'Float64Array']
+ math_envs = ['Math.min'] # TODO: move min to maths
+ asm_setup += '\n'.join(['var %s = %s;' % (f.replace('.', '_'), f) for f in math_envs])
+
+ if settings['PRECISE_F32']: maths += ['Math.fround']
+
+ basic_funcs = ['abort', 'assert', 'asmPrintInt', 'asmPrintFloat'] + [m.replace('.', '_') for m in math_envs]
+ if settings['RESERVED_FUNCTION_POINTERS'] > 0: basic_funcs.append('jsCall')
+ if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE', 'SAFE_HEAP_CLEAR']
+ if settings['CHECK_HEAP_ALIGN']: basic_funcs += ['CHECK_ALIGN_2', 'CHECK_ALIGN_4', 'CHECK_ALIGN_8']
+ if settings['ASSERTIONS']:
+ basic_funcs += ['nullFunc']
+ asm_setup += 'function nullFunc(x) { Module["printErr"]("Invalid function pointer called. Perhaps a miscast function pointer (check compilation warnings) or bad vtable lookup (maybe due to derefing a bad pointer, like NULL)?"); abort(x) }\n'
+
+ basic_vars = ['STACKTOP', 'STACK_MAX', 'tempDoublePtr', 'ABORT']
+ basic_float_vars = ['NaN', 'Infinity']
+
+ if metadata.get('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']
+
+ if settings.get('DLOPEN_SUPPORT'):
+ for sig in last_forwarded_json['Functions']['tables'].iterkeys():
+ basic_vars.append('F_BASE_%s' % sig)
+ asm_setup += ' var F_BASE_%s = %s;\n' % (sig, 'FUNCTION_TABLE_OFFSET' if settings.get('SIDE_MODULE') else '0') + '\n'
+
+ asm_runtime_funcs = ['stackAlloc', 'stackSave', 'stackRestore', 'setThrew'] + ['setTempRet%d' % i for i in range(10)]
+ # function tables
+ function_tables = ['dynCall_' + table for table in last_forwarded_json['Functions']['tables']]
+ function_tables_impls = []
+
+ for sig in last_forwarded_json['Functions']['tables'].iterkeys():
+ args = ','.join(['a' + str(i) for i in range(1, len(sig))])
+ arg_coercions = ' '.join(['a' + str(i) + '=' + shared.JS.make_coercion('a' + str(i), sig[i], settings) + ';' for i in range(1, len(sig))])
+ coerced_args = ','.join([shared.JS.make_coercion('a' + str(i), sig[i], settings) for i in range(1, len(sig))])
+ ret = ('return ' if sig[0] != 'v' else '') + shared.JS.make_coercion('FUNCTION_TABLE_%s[index&{{{ FTM_%s }}}](%s)' % (sig, sig, coerced_args), sig[0], settings)
+ function_tables_impls.append('''
+ function dynCall_%s(index%s%s) {
+ index = index|0;
+ %s
+ %s;
+ }
+''' % (sig, ',' if len(sig) > 1 else '', args, arg_coercions, ret))
+
+ for i in range(settings['RESERVED_FUNCTION_POINTERS']):
+ jsret = ('return ' if sig[0] != 'v' else '') + shared.JS.make_coercion('jsCall(%d%s%s)' % (i, ',' if coerced_args else '', coerced_args), sig[0], settings)
+ function_tables_impls.append('''
+ function jsCall_%s_%s(%s) {
+ %s
+ %s;
+ }
+
+''' % (sig, i, args, arg_coercions, jsret))
+ shared.Settings.copy(settings)
+ asm_setup += '\n' + shared.JS.make_invoke(sig) + '\n'
+ basic_funcs.append('invoke_%s' % sig)
+ if settings.get('DLOPEN_SUPPORT'):
+ asm_setup += '\n' + shared.JS.make_extcall(sig) + '\n'
+ basic_funcs.append('extCall_%s' % sig)
+
+ # calculate exports
+ exported_implemented_functions = list(exported_implemented_functions) + metadata['initializers']
+ exported_implemented_functions.append('runPostSets')
+ exports = []
+ if not simple:
+ for export in exported_implemented_functions + asm_runtime_funcs + function_tables:
+ exports.append("%s: %s" % (export, export))
+ exports = '{ ' + ', '.join(exports) + ' }'
+ else:
+ exports = '_main'
+ # calculate globals
+ try:
+ del forwarded_json['Variables']['globals']['_llvm_global_ctors'] # not a true variable
+ except:
+ pass
+ # If no named globals, only need externals
+ global_vars = metadata['externs'] #+ forwarded_json['Variables']['globals']
+ global_funcs = list(set(['_' + key for key, value in forwarded_json['Functions']['libraryFunctions'].iteritems() if value != 2]).difference(set(global_vars))) # + metadata['externFuncs']/'declares'
+ 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]) + \
+ ''.join([' var ' + g + '=env.' + math_fix(g) + ';\n' for g in basic_funcs + global_funcs])
+ asm_global_vars = ''.join([' var ' + g + '=env.' + g + '|0;\n' for g in basic_vars + global_vars])
+ # In linkable modules, we need to add some explicit globals for global variables that can be linked and used across modules
+ if settings.get('MAIN_MODULE') or settings.get('SIDE_MODULE'):
+ assert settings.get('TARGET_LE32'), 'TODO: support x86 target when linking modules (needs offset of 4 and not 8 here)'
+ for key, value in forwarded_json['Variables']['globals'].iteritems():
+ if value.get('linkable'):
+ init = forwarded_json['Variables']['indexedGlobals'][key] + 8 # 8 is Runtime.GLOBAL_BASE / STATIC_BASE
+ if settings.get('SIDE_MODULE'): init = '(H_BASE+' + str(init) + ')|0'
+ asm_global_vars += ' var %s=%s;\n' % (key, str(init))
+
+ # sent data
+ the_global = '{ ' + ', '.join(['"' + math_fix(s) + '": ' + s for s in fundamentals]) + ' }'
+ sending = '{ ' + ', '.join(['"' + math_fix(s) + '": ' + s for s in basic_funcs + global_funcs + basic_vars + basic_float_vars + global_vars]) + ' }'
+ # received
+ if not simple:
+ receiving = ';\n'.join(['var ' + s + ' = Module["' + s + '"] = asm["' + s + '"]' for s in exported_implemented_functions + function_tables])
+ else:
+ receiving = 'var _main = Module["_main"] = asm;'
+
+ # finalize
+
+ if DEBUG: logging.debug('asm text sizes' + str([map(len, funcs_js), len(asm_setup), len(asm_global_vars), len(asm_global_funcs), len(pre_tables), len('\n'.join(function_tables_impls)), len(function_tables_defs.replace('\n', '\n ')), len(exports), len(the_global), len(sending), len(receiving)]))
+
+ funcs_js = ['''
+%s
+function asmPrintInt(x, y) {
+ Module.print('int ' + x + ',' + y);// + ' ' + new Error().stack);
+}
+function asmPrintFloat(x, y) {
+ Module.print('float ' + x + ',' + y);// + ' ' + new Error().stack);
+}
+// EMSCRIPTEN_START_ASM
+var asm = (function(global, env, buffer) {
+ %s
+ var HEAP8 = new global.Int8Array(buffer);
+ var HEAP16 = new global.Int16Array(buffer);
+ var HEAP32 = new global.Int32Array(buffer);
+ var HEAPU8 = new global.Uint8Array(buffer);
+ var HEAPU16 = new global.Uint16Array(buffer);
+ var HEAPU32 = new global.Uint32Array(buffer);
+ var HEAPF32 = new global.Float32Array(buffer);
+ var HEAPF64 = new global.Float64Array(buffer);
+''' % (asm_setup, "'use asm';" if not metadata.get('hasInlineJS') and not settings['SIDE_MODULE'] and settings['ASM_JS'] == 1 else "'almost asm';") + '\n' + asm_global_vars + '''
+ var __THREW__ = 0;
+ var threwValue = 0;
+ var setjmpId = 0;
+ var undef = 0;
+ var nan = +env.NaN, inf = +env.Infinity;
+ var tempInt = 0, tempBigInt = 0, tempBigIntP = 0, tempBigIntS = 0, tempBigIntR = 0.0, tempBigIntI = 0, tempBigIntD = 0, tempValue = 0, tempDouble = 0.0;
+''' + ''.join(['''
+ var tempRet%d = 0;''' % i for i in range(10)]) + '\n' + asm_global_funcs] + [' var tempFloat = %s;\n' % ('Math_fround(0)' if settings.get('PRECISE_F32') else '0.0')] + ['''
+// EMSCRIPTEN_START_FUNCS
+function stackAlloc(size) {
+ size = size|0;
+ var ret = 0;
+ ret = STACKTOP;
+ STACKTOP = (STACKTOP + size)|0;
+''' + ('STACKTOP = (STACKTOP + 3)&-4;' if settings['TARGET_X86'] else 'STACKTOP = (STACKTOP + 7)&-8;') + '''
+ return ret|0;
+}
+function stackSave() {
+ return STACKTOP|0;
+}
+function stackRestore(top) {
+ top = top|0;
+ STACKTOP = top;
+}
+function setThrew(threw, value) {
+ threw = threw|0;
+ value = value|0;
+ if ((__THREW__|0) == 0) {
+ __THREW__ = threw;
+ threwValue = value;
+ }
+}
+function copyTempFloat(ptr) {
+ ptr = ptr|0;
+ HEAP8[tempDoublePtr] = HEAP8[ptr];
+ HEAP8[tempDoublePtr+1|0] = HEAP8[ptr+1|0];
+ HEAP8[tempDoublePtr+2|0] = HEAP8[ptr+2|0];
+ HEAP8[tempDoublePtr+3|0] = HEAP8[ptr+3|0];
+}
+function copyTempDouble(ptr) {
+ ptr = ptr|0;
+ HEAP8[tempDoublePtr] = HEAP8[ptr];
+ HEAP8[tempDoublePtr+1|0] = HEAP8[ptr+1|0];
+ HEAP8[tempDoublePtr+2|0] = HEAP8[ptr+2|0];
+ HEAP8[tempDoublePtr+3|0] = HEAP8[ptr+3|0];
+ HEAP8[tempDoublePtr+4|0] = HEAP8[ptr+4|0];
+ HEAP8[tempDoublePtr+5|0] = HEAP8[ptr+5|0];
+ HEAP8[tempDoublePtr+6|0] = HEAP8[ptr+6|0];
+ HEAP8[tempDoublePtr+7|0] = HEAP8[ptr+7|0];
+}
+''' + ''.join(['''
+function setTempRet%d(value) {
+ value = value|0;
+ tempRet%d = value;
+}
+''' % (i, i) for i in range(10)])] + funcs_js + ['''
+ %s
+
+ return %s;
+})
+// EMSCRIPTEN_END_ASM
+(%s, %s, buffer);
+%s;
+''' % (pre_tables + '\n'.join(function_tables_impls) + '\n' + function_tables_defs.replace('\n', '\n '), exports, the_global, sending, receiving)]
+
+ if not settings.get('SIDE_MODULE'):
+ funcs_js.append('''
+Runtime.stackAlloc = function(size) { return asm['stackAlloc'](size) };
+Runtime.stackSave = function() { return asm['stackSave']() };
+Runtime.stackRestore = function(top) { asm['stackRestore'](top) };
+''')
+
+ # Set function table masks
+ masks = {}
+ max_mask = 0
+ for sig, table in last_forwarded_json['Functions']['tables'].iteritems():
+ mask = table.count(',')
+ masks[sig] = str(mask)
+ max_mask = max(mask, max_mask)
+ def function_table_maskize(js, masks):
+ def fix(m):
+ sig = m.groups(0)[0]
+ return masks[sig]
+ return re.sub(r'{{{ FTM_([\w\d_$]+) }}}', lambda m: fix(m), js) # masks[m.groups(0)[0]]
+ funcs_js = map(lambda js: function_table_maskize(js, masks), funcs_js)
+
+ if settings.get('DLOPEN_SUPPORT'):
+ funcs_js.append('''
+ asm.maxFunctionIndex = %(max_mask)d;
+ DLFCN.registerFunctions(asm, %(max_mask)d+1, %(sigs)s, Module);
+ Module.SYMBOL_TABLE = SYMBOL_TABLE;
+''' % { 'max_mask': max_mask, 'sigs': str(map(str, last_forwarded_json['Functions']['tables'].keys())) })
+
+ else:
+ function_tables_defs = '\n'.join([table for table in last_forwarded_json['Functions']['tables'].itervalues()])
+ outfile.write(function_tables_defs)
+ funcs_js = ['''
+// EMSCRIPTEN_START_FUNCS
+'''] + funcs_js + ['''
+// EMSCRIPTEN_END_FUNCS
+''']
+
+ # Create symbol table for self-dlopen
+ if settings.get('DLOPEN_SUPPORT'):
+ symbol_table = {}
+ for k, v in forwarded_json['Variables']['indexedGlobals'].iteritems():
+ if forwarded_json['Variables']['globals'][k]['named']:
+ symbol_table[k] = str(v + forwarded_json['Runtime']['GLOBAL_BASE'])
+ for raw in last_forwarded_json['Functions']['tables'].itervalues():
+ if raw == '': continue
+ table = map(string.strip, raw[raw.find('[')+1:raw.find(']')].split(","))
+ for i in range(len(table)):
+ value = table[i]
+ if value != '0':
+ if settings.get('SIDE_MODULE'):
+ symbol_table[value] = 'FUNCTION_TABLE_OFFSET+' + str(i)
+ else:
+ symbol_table[value] = str(i)
+ outfile.write("var SYMBOL_TABLE = %s;" % json.dumps(symbol_table).replace('"', ''))
+
+ for i in range(len(funcs_js)): # do this loop carefully to save memory
+ outfile.write(funcs_js[i])
+ funcs_js = None
+
+ outfile.write(post)
+
+ outfile.close()
+
+if os.environ.get('EMCC_FAST_COMPILER'):
+ emscript = emscript_fast
+
def main(args, compiler_engine, cache, jcache, relooper, temp_files, DEBUG, DEBUG_CACHE):
# Prepare settings for serialization to JSON.
settings = {}
diff --git a/src/compiler.js b/src/compiler.js
index aa3c7b92..7d768c3d 100644
--- a/src/compiler.js
+++ b/src/compiler.js
@@ -206,12 +206,12 @@ if (phase == 'pre') {
if (VERBOSE) printErr('VERBOSE is on, this generates a lot of output and can slow down compilation');
// Load struct and define information.
-try {
+//try {
var temp = JSON.parse(read(STRUCT_INFO));
-} catch(e) {
- printErr('cannot load struct info at ' + STRUCT_INFO + ' : ' + e + ', trying in current dir');
- temp = JSON.parse(read('struct_info.compiled.json'));
-}
+//} catch(e) {
+// printErr('cannot load struct info at ' + STRUCT_INFO + ' : ' + e + ', trying in current dir');
+// temp = JSON.parse(read('struct_info.compiled.json'));
+//}
C_STRUCTS = temp.structs;
C_DEFINES = temp.defines;
@@ -224,12 +224,12 @@ load('analyzer.js');
load('jsifier.js');
if (phase == 'funcs' && RELOOP) { // XXX handle !singlePhase
RelooperModule = { TOTAL_MEMORY: ceilPowerOfTwo(2*RELOOPER_BUFFER_SIZE) };
- try {
+ //try {
load(RELOOPER);
- } catch(e) {
- printErr('cannot load relooper at ' + RELOOPER + ' : ' + e + ', trying in current dir');
- load('relooper.js');
- }
+ //} catch(e) {
+ // printErr('cannot load relooper at ' + RELOOPER + ' : ' + e + ', trying in current dir');
+ // load('relooper.js');
+ //}
assert(typeof Relooper != 'undefined');
}
globalEval(processMacros(preprocess(read('runtime.js'))));
@@ -267,7 +267,7 @@ function compile(raw) {
function runPhase(currPhase) {
//printErr('// JS compiler in action, phase ' + currPhase + typeof lines + (lines === null));
phase = currPhase;
- if (phase != 'pre') {