diff options
Diffstat (limited to 'emscripten.py')
-rwxr-xr-x | emscripten.py | 56 |
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) |