def get_metadata_binaryen(infile, outfile, modify_wasm, args): stdout = building.run_binaryen_command( 'wasm-emscripten-finalize', infile=infile, outfile=outfile if modify_wasm else None, args=args, stdout=subprocess.PIPE) metadata = load_metadata_json(stdout) return metadata
def get_metadata_python(infile, outfile, modify_wasm, args): metadata = extract_metadata.extract_metadata(infile) if modify_wasm: # In some cases we still need to modify the wasm file # using wasm-emscripten-finalize. building.run_binaryen_command('wasm-emscripten-finalize', infile=infile, outfile=outfile, args=args, stdout=subprocess.PIPE) # When we do this we can generate new imports, so # re-read parts of the metadata post-finalize extract_metadata.update_metadata(outfile, metadata) elif 'main' in metadata['exports']: # Mimic a bug in wasm-emscripten-finalize where we don't correctly # detect the presense of the main wrapper function unless we are # modifying the binary. This is because binaryen doesn't reaad # the function bodies in this mode. # TODO(sbc): Remove this once we make the switch away from # binaryen metadata. metadata['mainReadsParams'] = 1 return metadata
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(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)