def finalize_wasm(infile, outfile, memfile, DEBUG): building.save_intermediate(infile, 'base.wasm') # tell binaryen to look at the features section, and if there isn't one, to use MVP # (which matches what llvm+lld has given us) args = ['--minimize-wasm-changes'] # if we don't need to modify the wasm, don't tell finalize to emit a wasm file modify_wasm = False if settings.WASM2JS: # wasm2js requires full legalization (and will do extra wasm binary # later processing later anyhow) modify_wasm = True if settings.GENERATE_SOURCE_MAP: building.emit_wasm_source_map(infile, infile + '.map', outfile) building.save_intermediate(infile + '.map', 'base_wasm.map') args += [ '--output-source-map-url=' + settings.SOURCE_MAP_BASE + os.path.basename(outfile) + '.map' ] modify_wasm = True if settings.DEBUG_LEVEL >= 2 or settings.ASYNCIFY_ADD or settings.ASYNCIFY_ADVISE or settings.ASYNCIFY_ONLY or settings.ASYNCIFY_REMOVE or settings.EMIT_SYMBOL_MAP or settings.EMIT_NAME_SECTION: args.append('-g') if settings.WASM_BIGINT: args.append('--bigint') if settings.DYNCALLS: # we need to add all dyncalls to the wasm modify_wasm = True else: if settings.WASM_BIGINT: args.append('--no-dyncalls') else: args.append('--dyncalls-i64') # we need to add some dyncalls to the wasm modify_wasm = True if settings.LEGALIZE_JS_FFI: # When we dynamically link our JS loader adds functions from wasm modules to # the table. It must add the original versions of them, not legalized ones, # so that indirect calls have the right type, so export those. if settings.RELOCATABLE: args.append('--pass-arg=legalize-js-interface-export-originals') modify_wasm = True else: args.append('--no-legalize-javascript-ffi') if memfile: args.append(f'--separate-data-segments={memfile}') args.append(f'--global-base={settings.GLOBAL_BASE}') modify_wasm = True if settings.SIDE_MODULE: args.append('--side-module') if settings.STACK_OVERFLOW_CHECK >= 2: args.append('--check-stack-overflow') modify_wasm = True if settings.STANDALONE_WASM: args.append('--standalone-wasm') if settings.DEBUG_LEVEL >= 3: args.append('--dwarf') stdout = building.run_binaryen_command( 'wasm-emscripten-finalize', infile=infile, outfile=outfile if modify_wasm else None, args=args, stdout=subprocess.PIPE) if modify_wasm: building.save_intermediate(infile, 'post_finalize.wasm') elif infile != outfile: shutil.copy(infile, outfile) if settings.GENERATE_SOURCE_MAP: building.save_intermediate(infile + '.map', 'post_finalize.map') if memfile: # we have a separate .mem file. binaryen did not strip any trailing zeros, # because it's an ABI question as to whether it is valid to do so or not. # we can do so here, since we make sure to zero out that memory (even in # the dynamic linking case, our loader zeros it out) remove_trailing_zeros(memfile) return load_metadata_wasm(stdout, DEBUG)
def finalize_wasm(infile, outfile, memfile): building.save_intermediate(infile, 'base.wasm') args = [] # if we don't need to modify the wasm, don't tell finalize to emit a wasm file modify_wasm = False if settings.WASM2JS: # wasm2js requires full legalization (and will do extra wasm binary # later processing later anyhow) modify_wasm = True if settings.USE_PTHREADS and settings.RELOCATABLE: # HACK: When settings.USE_PTHREADS and settings.RELOCATABLE are set finalize needs to scan # more than just the start function for memory.init instructions. This means it can't run # with setSkipFunctionBodies() enabled. Currently the only way to force this is to set an # output file. # TODO(sbc): Find a better way to do this. modify_wasm = True if settings.GENERATE_SOURCE_MAP: building.emit_wasm_source_map(infile, infile + '.map', outfile) building.save_intermediate(infile + '.map', 'base_wasm.map') args += [ '--output-source-map-url=' + settings.SOURCE_MAP_BASE + os.path.basename(outfile) + '.map' ] modify_wasm = True if settings.DEBUG_LEVEL >= 2 or settings.ASYNCIFY_ADD or settings.ASYNCIFY_ADVISE or settings.ASYNCIFY_ONLY or settings.ASYNCIFY_REMOVE or settings.EMIT_SYMBOL_MAP or settings.EMIT_NAME_SECTION: args.append('-g') if settings.WASM_BIGINT: args.append('--bigint') if settings.DYNCALLS: # we need to add all dyncalls to the wasm modify_wasm = True else: if settings.WASM_BIGINT: args.append('--no-dyncalls') else: args.append('--dyncalls-i64') # we need to add some dyncalls to the wasm modify_wasm = True if settings.LEGALIZE_JS_FFI: # When we dynamically link our JS loader adds functions from wasm modules to # the table. It must add the original versions of them, not legalized ones, # so that indirect calls have the right type, so export those. if settings.RELOCATABLE: args.append('--pass-arg=legalize-js-interface-export-originals') modify_wasm = True else: args.append('--no-legalize-javascript-ffi') if memfile: args.append(f'--separate-data-segments={memfile}') args.append(f'--global-base={settings.GLOBAL_BASE}') modify_wasm = True if settings.SIDE_MODULE: args.append('--side-module') if settings.STACK_OVERFLOW_CHECK >= 2: args.append('--check-stack-overflow') modify_wasm = True if settings.STANDALONE_WASM: args.append('--standalone-wasm') if settings.DEBUG_LEVEL >= 3: args.append('--dwarf') # Currently we have two different ways to extract the metadata from the # wasm binary: # 1. via wasm-emscripten-finalize (binaryen) # 2. via local python code # We also have a 'compare' mode that runs both extraction methods and # checks that they produce identical results. read_metadata = os.environ.get('EMCC_READ_METADATA', 'binaryen') if read_metadata == 'binaryen': metadata = get_metadata_binaryen(infile, outfile, modify_wasm, args) elif read_metadata == 'python': metadata = get_metadata_python(infile, outfile, modify_wasm, args) elif read_metadata == 'compare': shutil.copy2(infile, infile + '.bak') if settings.GENERATE_SOURCE_MAP: shutil.copy2(infile + '.map', infile + '.map.bak') pymetadata = get_metadata_python(infile, outfile, modify_wasm, args) shutil.move(infile + '.bak', infile) if settings.GENERATE_SOURCE_MAP: shutil.move(infile + '.map.bak', infile + '.map') metadata = get_metadata_binaryen(infile, outfile, modify_wasm, args) compare_metadata(metadata, pymetadata) else: assert False if modify_wasm: building.save_intermediate(infile, 'post_finalize.wasm') elif infile != outfile: shutil.copy(infile, outfile) if settings.GENERATE_SOURCE_MAP: building.save_intermediate(infile + '.map', 'post_finalize.map') if memfile: # we have a separate .mem file. binaryen did not strip any trailing zeros, # because it's an ABI question as to whether it is valid to do so or not. # we can do so here, since we make sure to zero out that memory (even in # the dynamic linking case, our loader zeros it out) remove_trailing_zeros(memfile) return metadata
def finalize_wasm(temp_files, infile, outfile, memfile, DEBUG): basename = shared.unsuffixed(outfile.name) wasm = basename + '.wasm' base_wasm = infile building.save_intermediate(infile, 'base.wasm') args = ['--detect-features', '--minimize-wasm-changes'] write_source_map = shared.Settings.DEBUG_LEVEL >= 4 if write_source_map: building.emit_wasm_source_map(base_wasm, base_wasm + '.map') building.save_intermediate(base_wasm + '.map', 'base_wasm.map') args += [ '--output-source-map-url=' + shared.Settings.SOURCE_MAP_BASE + os.path.basename(shared.Settings.WASM_BINARY_FILE) + '.map' ] # tell binaryen to look at the features section, and if there isn't one, to use MVP # (which matches what llvm+lld has given us) if shared.Settings.DEBUG_LEVEL >= 2 or shared.Settings.PROFILING_FUNCS or shared.Settings.EMIT_SYMBOL_MAP or shared.Settings.ASYNCIFY_ONLY or shared.Settings.ASYNCIFY_REMOVE or shared.Settings.ASYNCIFY_ADD: args.append('-g') if shared.Settings.WASM_BIGINT: args.append('--bigint') if not shared.Settings.USE_LEGACY_DYNCALLS: if shared.Settings.WASM_BIGINT: args.append('--no-dyncalls') else: args.append('--dyncalls-i64') if shared.Settings.LEGALIZE_JS_FFI != 1: args.append('--no-legalize-javascript-ffi') if not shared.Settings.MEM_INIT_IN_WASM: args.append('--separate-data-segments=' + memfile) if shared.Settings.SIDE_MODULE: args.append('--side-module') else: # --global-base is used by wasm-emscripten-finalize to calculate the size # of the static data used. The argument we supply here needs to match the # global based used by lld (see building.link_lld). For relocatable this is # zero for the global base although at runtime __memory_base is used. # For non-relocatable output we used shared.Settings.GLOBAL_BASE. # TODO(sbc): Can we remove this argument infer this from the segment # initializer? if shared.Settings.RELOCATABLE: args.append('--global-base=0') else: args.append('--global-base=%s' % shared.Settings.GLOBAL_BASE) if shared.Settings.STACK_OVERFLOW_CHECK >= 2: args.append('--check-stack-overflow') if shared.Settings.STANDALONE_WASM: args.append('--standalone-wasm') # When we dynamically link our JS loader adds functions from wasm modules to # the table. It must add the original versions of them, not legalized ones, # so that indirect calls have the right type, so export those. if shared.Settings.RELOCATABLE: args.append('--pass-arg=legalize-js-interface-export-originals') if shared.Settings.DEBUG_LEVEL >= 3: args.append('--dwarf') stdout = building.run_binaryen_command('wasm-emscripten-finalize', infile=base_wasm, outfile=wasm, args=args, stdout=subprocess.PIPE) if write_source_map: building.save_intermediate(wasm + '.map', 'post_finalize.map') building.save_intermediate(wasm, 'post_finalize.wasm') if not shared.Settings.MEM_INIT_IN_WASM: # we have a separate .mem file. binaryen did not strip any trailing zeros, # because it's an ABI question as to whether it is valid to do so or not. # we can do so here, since we make sure to zero out that memory (even in # the dynamic linking case, our loader zeros it out) remove_trailing_zeros(memfile) return load_metadata_wasm(stdout, DEBUG)
def finalize_wasm(infile, memfile, DEBUG): building.save_intermediate(infile, 'base.wasm') args = ['--mutable-sp', '--detect-features', '--minimize-wasm-changes'] # if we don't need to modify the wasm, don't tell finalize to emit a wasm file modify_wasm = False if shared.Settings.RELOCATABLE: # In relocatable mode we transform the PIC ABI from what llvm outputs # to emscripten's PIC ABI that uses `fp$` and `g$` accessor functions. modify_wasm = True if shared.Settings.WASM2JS: # wasm2js requires full legalization (and will do extra wasm binary # later processing later anyhow) modify_wasm = True if shared.Settings.GENERATE_SOURCE_MAP: building.emit_wasm_source_map(infile, infile + '.map') building.save_intermediate(infile + '.map', 'base_wasm.map') args += [ '--output-source-map-url=' + shared.Settings.SOURCE_MAP_BASE + os.path.basename(shared.Settings.WASM_BINARY_FILE) + '.map' ] modify_wasm = True # tell binaryen to look at the features section, and if there isn't one, to use MVP # (which matches what llvm+lld has given us) if shared.Settings.DEBUG_LEVEL >= 2 or shared.Settings.ASYNCIFY_ADD or shared.Settings.ASYNCIFY_ADVISE or shared.Settings.ASYNCIFY_ONLY or shared.Settings.ASYNCIFY_REMOVE or shared.Settings.EMIT_SYMBOL_MAP or shared.Settings.PROFILING_FUNCS: args.append('-g') if shared.Settings.WASM_BIGINT: args.append('--bigint') if shared.Settings.USE_LEGACY_DYNCALLS: # we need to add all dyncalls to the wasm modify_wasm = True else: if shared.Settings.WASM_BIGINT: args.append('--no-dyncalls') else: args.append('--dyncalls-i64') # we need to add some dyncalls to the wasm modify_wasm = True if shared.Settings.LEGALIZE_JS_FFI: # When we dynamically link our JS loader adds functions from wasm modules to # the table. It must add the original versions of them, not legalized ones, # so that indirect calls have the right type, so export those. if shared.Settings.RELOCATABLE: args.append('--pass-arg=legalize-js-interface-export-originals') modify_wasm = True else: args.append('--no-legalize-javascript-ffi') if memfile: args.append('--separate-data-segments=' + memfile) modify_wasm = True if shared.Settings.SIDE_MODULE: args.append('--side-module') else: # --global-base is used by wasm-emscripten-finalize to calculate the size # of the static data used. The argument we supply here needs to match the # global based used by lld (see building.link_lld). For relocatable this is # zero for the global base although at runtime __memory_base is used. # For non-relocatable output we used shared.Settings.GLOBAL_BASE. # TODO(sbc): Can we remove this argument infer this from the segment # initializer? if shared.Settings.RELOCATABLE: args.append('--global-base=0') else: args.append('--global-base=%s' % shared.Settings.GLOBAL_BASE) if shared.Settings.STACK_OVERFLOW_CHECK >= 2: args.append('--check-stack-overflow') modify_wasm = True if shared.Settings.STANDALONE_WASM: args.append('--standalone-wasm') modify_wasm = True if shared.Settings.DEBUG_LEVEL >= 3: args.append('--dwarf') stdout = building.run_binaryen_command( 'wasm-emscripten-finalize', infile=infile, outfile=infile if modify_wasm else None, args=args, stdout=subprocess.PIPE) if modify_wasm: building.save_intermediate(infile, 'post_finalize.wasm') if shared.Settings.GENERATE_SOURCE_MAP: building.save_intermediate(infile + '.map', 'post_finalize.map') if memfile: # we have a separate .mem file. binaryen did not strip any trailing zeros, # because it's an ABI question as to whether it is valid to do so or not. # we can do so here, since we make sure to zero out that memory (even in # the dynamic linking case, our loader zeros it out) remove_trailing_zeros(memfile) return load_metadata_wasm(stdout, DEBUG)