aboutsummaryrefslogtreecommitdiff
path: root/emscripten.py
diff options
context:
space:
mode:
Diffstat (limited to 'emscripten.py')
-rwxr-xr-xemscripten.py56
1 files changed, 42 insertions, 14 deletions
diff --git a/emscripten.py b/emscripten.py
index 59a0666c..c8122cb9 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, shutil
+import os, sys, json, optparse, subprocess, re, time, multiprocessing, string, logging
from tools import shared
from tools import jsrun, cache as cache_module, tempfiles
@@ -538,7 +538,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
''.join([' var ' + g + '=+env.' + g + ';\n' for g in basic_float_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)'
+ assert settings.get('TARGET_ASMJS_UNKNOWN_EMSCRIPTEN'), '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
@@ -746,6 +746,9 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
backend_args += ['-emscripten-warn-unaligned']
if settings['RESERVED_FUNCTION_POINTERS'] > 0:
backend_args += ['-emscripten-reserved-function-pointers=%d' % settings['RESERVED_FUNCTION_POINTERS']]
+ if settings['ASSERTIONS'] > 0:
+ backend_args += ['-emscripten-assertions=%d' % settings['ASSERTIONS']]
+ backend_args += ['-O' + str(settings['OPT_LEVEL'])]
if DEBUG:
logging.debug('emscript: llvm backend: ' + ' '.join(backend_args))
t = time.time()
@@ -780,6 +783,8 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
table_sizes = {}
for k, v in metadata['tables'].iteritems():
table_sizes[k] = str(v.count(',')) # undercounts by one, but that is what we want
+ #if settings['ASSERTIONS'] >= 2 and table_sizes[k] == 0:
+ # print >> sys.stderr, 'warning: no function pointers with signature ' + k + ', but there is a call, which will abort if it occurs (this can result from undefined behavior, check for compiler warnings on your source files and consider -Werror)'
funcs = re.sub(r"#FM_(\w+)#", lambda m: table_sizes[m.groups(0)[0]], funcs)
# fix +float into float.0, if not running js opts
@@ -801,8 +806,8 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
if DEBUG: logging.debug('emscript: js compiler glue')
# Settings changes
- assert settings['TARGET_LE32'] == 1
- settings['TARGET_LE32'] = 2
+ assert settings['TARGET_ASMJS_UNKNOWN_EMSCRIPTEN'] == 1
+ settings['TARGET_ASMJS_UNKNOWN_EMSCRIPTEN'] = 2
i64_funcs = ['i64Add', 'i64Subtract', '__muldi3', '__divdi3', '__udivdi3', '__remdi3', '__uremdi3']
for i64_func in i64_funcs:
if i64_func in metadata['declares']:
@@ -819,6 +824,8 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
) + map(lambda x: x[1:], metadata['externs'])
if metadata['simd']:
settings['SIMD'] = 1
+ if not metadata['canValidate'] and settings['ASM_JS'] != 2:
+ logging.warning('disabling asm.js validation due to use of non-supported features')
settings['ASM_JS'] = 2
# Save settings to a file to work around v8 issue 1579
@@ -922,7 +929,6 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
debug_tables = {}
def make_table(sig, raw):
- Counter.pre = ''
params = ','.join(['p%d' % p for p in range(len(sig)-1)])
coerced_params = ','.join([shared.JS.make_coercion('p%d', unfloat(sig[p+1]), settings) % 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)]) + ';'
@@ -941,7 +947,10 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
code += 'return %s' % shared.JS.make_initializer(sig[0], settings) + ';'
return name, make_func(name, code)
bad, bad_func = make_bad() # the default bad func
- Counter.pre = [bad_func]
+ if settings['ASSERTIONS'] <= 1:
+ Counter.pre = [bad_func]
+ else:
+ Counter.pre = []
start = raw.index('[')
end = raw.rindex(']')
body = raw[start+1:end].split(',')
@@ -957,7 +966,7 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
if settings['ASSERTIONS'] <= 1:
return bad if not newline else (bad + '\n')
else:
- specific_bad, specific_bad_func = make_bad(Counter.j)
+ specific_bad, specific_bad_func = make_bad(Counter.j-1)
Counter.pre.append(specific_bad_func)
return specific_bad if not newline else (specific_bad + '\n')
if item not in implemented_functions:
@@ -997,6 +1006,7 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE']
if settings['CHECK_HEAP_ALIGN']: basic_funcs += ['CHECK_ALIGN_2', 'CHECK_ALIGN_4', 'CHECK_ALIGN_8']
if settings['ASSERTIONS']:
+ if settings['ASSERTIONS'] >= 2: import difflib
for sig in last_forwarded_json['Functions']['tables'].iterkeys():
basic_funcs += ['nullFunc_' + sig]
if settings['ASSERTIONS'] <= 1:
@@ -1006,11 +1016,29 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
pointer = ' \'" + x + "\' '
asm_setup += '\nvar debug_table_' + sig + ' = ' + json.dumps(debug_tables[sig]) + ';'
extra = ' Module["printErr"]("This pointer might make sense in another type signature: '
- for other in last_forwarded_json['Functions']['tables'].iterkeys():
+ # sort signatures, attempting to show most likely related ones first
+ sigs = last_forwarded_json['Functions']['tables'].keys()
+ def keyfunc(other):
+ ret = 0
+ minlen = min(len(other), len(sig))
+ maxlen = min(len(other), len(sig))
+ if other.startswith(sig) or sig.startswith(other): ret -= 1000 # prioritize prefixes, could be dropped params
+ ret -= 133*difflib.SequenceMatcher(a=other, b=sig).ratio() # prioritize on diff similarity
+ ret += 15*abs(len(other) - len(sig))/float(maxlen) # deprioritize the bigger the length difference is
+ for i in range(minlen):
+ if other[i] == sig[i]: ret -= 5/float(maxlen) # prioritize on identically-placed params
+ ret += 20*len(other) # deprioritize on length
+ return ret
+ sigs.sort(key=keyfunc)
+ for other in sigs:
if other != sig:
extra += other + ': " + debug_table_' + other + '[x] + " '
extra += '"); '
- asm_setup += '\nfunction nullFunc_' + sig + '(x) { Module["printErr"]("Invalid function pointer' + pointer + 'called with signature \'' + sig + '\'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an different type, which will fail?"); ' + extra + ' abort(x) }\n'
+ asm_setup += '\nfunction nullFunc_' + sig + '(x) { Module["printErr"]("Invalid function pointer' + pointer + 'called with signature \'' + sig + '\'. ' + \
+ 'Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? ' + \
+ 'Or calling a function with an incorrect type, which will fail? ' + \
+ '(it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)' + \
+ '"); ' + extra + ' abort(x) }\n'
basic_vars = ['STACKTOP', 'STACK_MAX', 'tempDoublePtr', 'ABORT']
basic_float_vars = ['NaN', 'Infinity']
@@ -1087,7 +1115,7 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
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)'
+ assert settings.get('TARGET_ASMJS_UNKNOWN_EMSCRIPTEN'), '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
@@ -1257,7 +1285,7 @@ Runtime.stackRestore = function(top) { asm['stackRestore'](top) };
if DEBUG: logging.debug(' emscript: final python processing took %s seconds' % (time.time() - t))
-if os.environ.get('EMCC_FAST_COMPILER') == '1':
+if os.environ.get('EMCC_FAST_COMPILER') != '0':
emscript = emscript_fast
def main(args, compiler_engine, cache, jcache, relooper, temp_files, DEBUG, DEBUG_CACHE):
@@ -1277,13 +1305,13 @@ def main(args, compiler_engine, cache, jcache, relooper, temp_files, DEBUG, DEBU
settings.setdefault('RELOOPER', relooper)
if not os.path.exists(relooper):
shared.Building.ensure_relooper(relooper)
-
+
settings.setdefault('STRUCT_INFO', cache.get_path('struct_info.compiled.json'))
struct_info = settings.get('STRUCT_INFO')
-
+
if not os.path.exists(struct_info):
shared.Building.ensure_struct_info(struct_info)
-
+
emscript(args.infile, settings, args.outfile, libraries, compiler_engine=compiler_engine,
jcache=jcache, temp_files=temp_files, DEBUG=DEBUG, DEBUG_CACHE=DEBUG_CACHE)