diff options
Diffstat (limited to 'emcc')
-rwxr-xr-x | emcc | 146 |
1 files changed, 119 insertions, 27 deletions
@@ -781,6 +781,14 @@ def filename_type_ending(filename): suffix = filename_type_suffix(filename) return '' if not suffix else ('.' + suffix) +# Log out times for emcc stages +log_time_last = time.time() +def log_time(name): + global log_time_last + now = time.time() + logging.debug('emcc step "%s" took %.2f seconds' % (name, now - log_time_last)) + log_time_last = now + try: call = CXX if use_cxx else CC @@ -1196,7 +1204,6 @@ try: shared.Settings.ASM_JS = 1 assert shared.Settings.ALLOW_MEMORY_GROWTH == 0, 'memory growth not supported in fastcomp yet' assert shared.Settings.UNALIGNED_MEMORY == 0, 'forced unaligned memory not supported in fastcomp' - assert shared.Settings.SAFE_HEAP == 0, 'safe heap not supported in fastcomp yet' assert shared.Settings.CHECK_HEAP_ALIGN == 0, 'check heap align not supported in fastcomp yet' assert shared.Settings.SAFE_DYNCALLS == 0, 'safe dyncalls not supported in fastcomp' assert shared.Settings.RESERVED_FUNCTION_POINTERS == 0, 'reserved function pointers not supported in fastcomp' @@ -1230,6 +1237,9 @@ try: shared.Settings.CORRECT_OVERFLOWS = 1 assert not shared.Settings.PGO, 'cannot run PGO in ASM_JS mode' + if shared.Settings.SAFE_HEAP and not js_opts: + logging.warning('asm.js+SAFE_HEAP requires js opts to be run (-O1 or above by default)') + if shared.Settings.CORRECT_SIGNS >= 2 or shared.Settings.CORRECT_OVERFLOWS >= 2 or shared.Settings.CORRECT_ROUNDINGS >= 2: debug_level = 4 # must keep debug info to do line-by-line operations @@ -1295,6 +1305,8 @@ try: temp_files = [] + log_time('parse arguments and setup') + # First, generate LLVM bitcode. For each input file, we get base.o with bitcode for input_file in input_files: file_ending = filename_type_ending(input_file) @@ -1334,6 +1346,8 @@ try: logging.error(input_file + ': Unknown file suffix when compiling to LLVM bitcode!') sys.exit(1) + log_time('bitcodeize inputs') + if not LEAVE_INPUTS_RAW: assert len(temp_files) == len(input_files) @@ -1380,6 +1394,8 @@ try: shared.Building.link(temp_files, specified_target) exit(0) + log_time('bitcodeize inputs') + ## Continue on to create JavaScript logging.debug('will generate JavaScript') @@ -1440,18 +1456,26 @@ try: libc_files = [ 'dlmalloc.c', os.path.join('libcxx', 'new.cpp'), - os.path.join('libc', 'stdlib', 'getopt_long.c'), - os.path.join('libc', 'gen', 'err.c'), - os.path.join('libc', 'gen', 'errx.c'), - os.path.join('libc', 'gen', 'warn.c'), - os.path.join('libc', 'gen', 'warnx.c'), - os.path.join('libc', 'gen', 'verr.c'), - os.path.join('libc', 'gen', 'verrx.c'), - os.path.join('libc', 'gen', 'vwarn.c'), - os.path.join('libc', 'gen', 'vwarnx.c'), - os.path.join('libc', 'stdlib', 'strtod.c'), ] musl_files = [ + ['internal', [ + 'floatscan.c', + 'shgetc.c', + ]], + ['math', [ + 'scalbn.c', + 'scalbnl.c', + ]], + ['stdio', [ + '__overflow.c', + '__toread.c', + '__towrite.c', + '__uflow.c', + ]], + ['stdlib', [ + 'atof.c', + 'strtod.c', + ]] ] for directory, sources in musl_files: libc_files += [os.path.join('libc', 'musl', 'src', directory, source) for source in sources] @@ -1492,6 +1516,12 @@ try: 'wctrans.c', 'wcwidth.c', ]], + ['internal', [ + 'intscan.c', + ]], + ['legacy', [ + 'err.c', + ]], ['locale', [ 'iconv.c', 'iswalnum_l.c', @@ -1507,7 +1537,9 @@ try: 'iswspace_l.c', 'iswupper_l.c', 'iswxdigit_l.c', + 'strcasecmp_l.c', 'strfmon.c', + 'strncasecmp_l.c', 'strxfrm.c', 'towctrans_l.c', 'towlower_l.c', @@ -1519,6 +1551,35 @@ try: 'wctrans_l.c', 'wctype_l.c', ]], + ['math', [ + '__cos.c', + '__cosdf.c', + '__sin.c', + '__sindf.c', + 'ilogb.c', + 'ilogbf.c', + 'ilogbl.c', + 'ldexp.c', + 'ldexpf.c', + 'ldexpl.c', + 'logb.c', + 'logbf.c', + 'logbl.c', + 'lgamma.c', + 'lgamma_r.c', + 'lgammaf.c', + 'lgammaf_r.c', + 'lgammal.c', + 'scalbnf.c', + 'signgam.c', + 'tgamma.c', + 'tgammaf.c', + 'tgammal.c' + ]], + ['misc', [ + 'getopt.c', + 'getopt_long.c', + ]], ['multibyte', [ 'btowc.c', 'mblen.c', @@ -1537,6 +1598,7 @@ try: 'wctomb.c', ]], ['regex', [ + 'fnmatch.c', 'regcomp.c', 'regerror.c', 'regexec.c', @@ -1549,13 +1611,27 @@ try: 'vswprintf.c', 'vwprintf.c', 'wprintf.c', + 'fputwc.c', + 'fputws.c', ]], ['stdlib', [ 'ecvt.c', 'fcvt.c', 'gcvt.c', + 'wcstod.c', + 'wcstol.c', ]], ['string', [ + 'memccpy.c', + 'memmem.c', + 'mempcpy.c', + 'memrchr.c', + 'strcasestr.c', + 'strchrnul.c', + 'strlcat.c', + 'strlcpy.c', + 'strsep.c', + 'strverscmp.c', 'wcpcpy.c', 'wcpncpy.c', 'wcscasecmp.c', @@ -1693,15 +1769,14 @@ try: libfile = shared.Cache.get(name, create) extra_files_to_link.append(libfile) + log_time('calculate system libraries') + # First, combine the bitcode files if there are several. We must also link if we have a singleton .a if len(input_files) + len(extra_files_to_link) > 1 or \ (not LEAVE_INPUTS_RAW and not (suffix(temp_files[0]) in BITCODE_ENDINGS or suffix(temp_files[0]) in DYNAMICLIB_ENDINGS) and shared.Building.is_ar(temp_files[0])): linker_inputs = temp_files + extra_files_to_link logging.debug('linking: ' + str(linker_inputs)) - t0 = time.time() shared.Building.link(linker_inputs, in_temp(target_basename + '.bc'), force_archive_contents = len(filter(lambda temp: not temp.endswith(STATICLIB_ENDINGS), temp_files)) == 0) - t1 = time.time() - logging.debug(' linking took %.2f seconds' % (t1 - t0)) final = in_temp(target_basename + '.bc') else: if not LEAVE_INPUTS_RAW: @@ -1711,19 +1786,16 @@ try: final = in_temp(input_files[0]) shutil.copyfile(input_files[0], final) + log_time('link') + if DEBUG: logging.debug('saving intermediate processing steps to %s' % shared.EMSCRIPTEN_TEMP_DIR) intermediate_counter = 0 - intermediate_time = None def save_intermediate(name=None, suffix='js'): - global intermediate_counter, intermediate_time + global intermediate_counter shutil.copyfile(final, os.path.join(shared.EMSCRIPTEN_TEMP_DIR, 'emcc-%d%s.%s' % (intermediate_counter, '' if name is None else '-' + name, suffix))) intermediate_counter += 1 - now = time.time() - if intermediate_time: - logging.debug(' step took %.2f seconds' % (now - intermediate_time)) - intermediate_time = now if not LEAVE_INPUTS_RAW: save_intermediate('basebc', 'bc') @@ -1784,6 +1856,8 @@ try: final += '.adsimp.bc' if DEBUG: save_intermediate('adsimp', 'bc') + log_time('post-link') + # Emscripten logging.debug('LLVM => JS') extra_args = [] if not js_libraries else ['--libraries', ','.join(map(os.path.abspath, js_libraries))] @@ -1791,6 +1865,8 @@ try: final = shared.Building.emscripten(final, append_ext=False, extra_args=extra_args) if DEBUG: save_intermediate('original') + log_time('emscript (llvm=>js)') + # Embed and preload files if len(preload_files) + len(embed_files) > 0: logging.debug('setting up files') @@ -1851,9 +1927,7 @@ try: shared.try_delete(memfile) def repl(m): # handle chunking of the memory initializer - s = re.sub('[\[\]\n\(\)\. ]', '', m.groups(0)[0]) - s = s.replace('concat', ',') - if s[-1] == ',': s = s[:-1] + s = m.groups(0)[0] open(memfile, 'wb').write(''.join(map(lambda x: chr(int(x or '0')), s.split(',')))) if DEBUG: # Copy into temp dir as well, so can be run there too @@ -1864,6 +1938,7 @@ try: src = re.sub(shared.JS.memory_initializer_pattern, repl, open(final).read(), count=1) open(final + '.mem.js', 'w').write(src) final += '.mem.js' + src = None js_transform_tempfiles[-1] = final # simple text substitution preserves comment line number mappings if DEBUG: if os.path.exists(memfile): @@ -1871,6 +1946,17 @@ try: logging.debug('wrote memory initialization to %s' % memfile) else: logging.debug('did not see memory initialization') + elif shared.Settings.USE_TYPED_ARRAYS == 2 and not shared.Settings.MAIN_MODULE and not shared.Settings.SIDE_MODULE: + # not writing a binary init, but we can at least optimize them by splitting them up + src = open(final).read() + src = shared.JS.optimize_initializer(src) + if src is not None: + logging.debug('optimizing memory initialization') + open(final + '.mem.js', 'w').write(src) + final += '.mem.js' + src = None + + log_time('source transforms') # It is useful to run several js optimizer passes together, to save on unneeded unparsing/reparsing js_optimizer_queue = [] @@ -1932,6 +2018,8 @@ try: if DEBUG: save_intermediate('closure') if js_opts: + if shared.Settings.ASM_JS and shared.Settings.SAFE_HEAP: js_optimizer_queue += ['safeHeap'] + if shared.Settings.OUTLINING_LIMIT > 0 and shared.Settings.ASM_JS: js_optimizer_queue += ['outline'] js_optimizer_extra_info['sizeToOutline'] = shared.Settings.OUTLINING_LIMIT @@ -1940,7 +2028,7 @@ try: js_optimizer_queue += ['registerize'] if opt_level > 0: - if debug_level < 2 and shared.Settings.ASM_JS: js_optimizer_queue = map(lambda p: p if p != 'registerize' else 'registerizeAndMinify', js_optimizer_queue) + if debug_level < 2 and shared.Settings.ASM_JS: js_optimizer_queue += ['minifyNames'] if debug_level == 0: js_optimizer_queue += ['minifyWhitespace'] if closure and shared.Settings.ASM_JS: @@ -1950,10 +2038,12 @@ try: flush_js_optimizer_queue() + log_time('js opts') + # Remove some trivial whitespace # TODO: do not run when compress has already been done on all parts of the code - src = open(final).read() - src = re.sub(r'\n+[ \n]*\n+', '\n', src) - open(final, 'w').write(src) + #src = open(final).read() + #src = re.sub(r'\n+[ \n]*\n+', '\n', src) + #open(final, 'w').write(src) def generate_source_map(map_file_base_name, offset=0): jsrun.run_js(shared.path_from_root('tools', 'source-maps', 'sourcemapper.js'), @@ -2056,6 +2146,8 @@ try: # copy final JS to output shutil.move(final, target) + log_time('final emitting') + if DEBUG: logging.debug('total time: %.2f seconds' % (time.time() - start_time)) finally: |