Exemple #1
0
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)
Exemple #2
0
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
Exemple #3
0
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)
Exemple #4
0
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)