diff options
Diffstat (limited to 'emcc')
-rwxr-xr-x | emcc | 120 |
1 files changed, 75 insertions, 45 deletions
@@ -146,7 +146,7 @@ Options that are modified or new in %s include: This is the recommended setting when you want a reasonably optimized build that is generated as - quickly as possible (it is much faster than -O2). + quickly as possible (it builds much faster than -O2). (Note: for details on the affects of different opt levels, see apply_opt_level() in @@ -158,20 +158,11 @@ Options that are modified or new in %s include: time in return for the smallest and fastest output. - -O3 As -O2, plus dangerous optimizations that may - break the generated code! This adds + -O3 As -O2, plus additional optimizations that can + take a significant amount of compilation time. - -s FORCE_ALIGNED_MEMORY=1 - -s DOUBLE_MODE=0 - -s PRECISE_I64_MATH=0 - --closure 1 - --llvm-lto 3 - - This is not recommended at all. A better idea - is to try each of these separately on top of - -O2 to see what works. See the wiki and - src/settings.js (for the -s options) for more - information. + For tips on optimizing your code, see + https://github.com/kripken/emscripten/wiki/Optimizing-Code -s OPTION=VALUE JavaScript code generation option passed into the emscripten compiler. For the @@ -267,8 +258,7 @@ Options that are modified or new in %s include: code size and may in some cases increase runtime speed (although the opposite can also occur). Note that it takes time to run, and - may require some changes to the code. This - is run by default in -O3. + may require some changes to the code. In asm.js mode, closure will only be used on the 'shell' code around the compiled code (the @@ -781,6 +771,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 @@ -1029,9 +1027,7 @@ try: if js_opts is None: js_opts = opt_level >= 2 if llvm_opts is None: llvm_opts = LLVM_OPT_LEVEL[opt_level] - if llvm_lto is None and opt_level >= 3: llvm_lto = 3 if opt_level == 0: debug_level = 4 - if closure is None and opt_level == 3: closure = True if llvm_lto is None and bind: logging.debug('running lto for embind') # XXX this is a workaround for a pointer issue @@ -1196,7 +1192,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 +1225,13 @@ 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.ALLOW_MEMORY_GROWTH: + logging.error('Cannot enable ALLOW_MEMORY_GROWTH with asm.js, build with -s ASM_JS=0 if you need a growable heap'); + sys.exit(1); + 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 +1297,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 +1338,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 +1386,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,15 +1448,6 @@ 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'), ] musl_files = [ ['internal', [ @@ -1462,6 +1461,7 @@ try: ['stdio', [ '__overflow.c', '__toread.c', + '__towrite.c', '__uflow.c', ]], ['stdlib', [ @@ -1511,6 +1511,9 @@ try: ['internal', [ 'intscan.c', ]], + ['legacy', [ + 'err.c', + ]], ['locale', [ 'iconv.c', 'iswalnum_l.c', @@ -1541,7 +1544,9 @@ try: 'wctype_l.c', ]], ['math', [ + '__cos.c', '__cosdf.c', + '__sin.c', '__sindf.c', 'ilogb.c', 'ilogbf.c', @@ -1563,6 +1568,10 @@ try: 'tgammaf.c', 'tgammal.c' ]], + ['misc', [ + 'getopt.c', + 'getopt_long.c', + ]], ['multibyte', [ 'btowc.c', 'mblen.c', @@ -1581,6 +1590,7 @@ try: 'wctomb.c', ]], ['regex', [ + 'fnmatch.c', 'regcomp.c', 'regerror.c', 'regexec.c', @@ -1594,6 +1604,7 @@ try: 'vwprintf.c', 'wprintf.c', 'fputwc.c', + 'fputws.c', ]], ['stdlib', [ 'ecvt.c', @@ -1750,15 +1761,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: @@ -1768,19 +1778,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') @@ -1841,6 +1848,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))] @@ -1848,6 +1857,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') @@ -1908,9 +1919,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 @@ -1921,6 +1930,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): @@ -1928,6 +1938,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 = [] @@ -1989,15 +2010,20 @@ 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 if (not closure or shared.Settings.ASM_JS) and shared.Settings.RELOOP and debug_level < 3: - js_optimizer_queue += ['registerize'] + if shared.Settings.ASM_JS and opt_level >= 3 and shared.Settings.OUTLINING_LIMIT == 0: + js_optimizer_queue += ['registerizeHarder'] + else: + 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: @@ -2007,10 +2033,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'), @@ -2113,6 +2141,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: |