コード例 #1
0
def load_metadata_wasm(metadata_raw, DEBUG):
    try:
        metadata_json = json.loads(metadata_raw)
    except Exception:
        logger.error(
            'emscript: failure to parse metadata output from wasm-emscripten-finalize. raw output is: \n'
            + metadata_raw)
        raise

    metadata = {
        'declares': [],
        'globalImports': [],
        'staticBump': 0,
        'tableSize': 0,
        'exports': [],
        'namedGlobals': {},
        'emJsFuncs': {},
        'asmConsts': {},
        'invokeFuncs': [],
        'features': [],
        'mainReadsParams': 1,
    }
    legacy_keys = set(
        ['implementedFunctions', 'initializers', 'simd', 'externs'])

    assert 'tableSize' in metadata_json.keys()
    for key, value in metadata_json.items():
        if key in legacy_keys:
            continue
        if key not in metadata:
            exit_with_error(
                'unexpected metadata key received from wasm-emscripten-finalize: %s',
                key)
        metadata[key] = value

    # Support older metadata when asmConsts values were lists.  We only use the first element
    # nowadays
    # TODO(sbc): remove this once binaryen has been changed to only emit the single element
    metadata['asmConsts'] = {
        k: v[0] if type(v) is list else v
        for k, v in metadata['asmConsts'].items()
    }

    if DEBUG:
        logger.debug("Metadata parsed: " + pprint.pformat(metadata))

    # Calculate the subset of exports that were explicitly marked with llvm.used.
    # These are any exports that were not requested on the command line and are
    # not known auto-generated system functions.
    unexpected_exports = [
        e for e in metadata['exports'] if treat_as_user_function(e)
    ]
    unexpected_exports = [asmjs_mangle(e) for e in unexpected_exports]
    unexpected_exports = [
        e for e in unexpected_exports if e not in settings.EXPORTED_FUNCTIONS
    ]
    building.user_requested_exports.update(unexpected_exports)
    settings.EXPORTED_FUNCTIONS.extend(unexpected_exports)

    return metadata
コード例 #2
0
ファイル: emscripten.py プロジェクト: sumory/emscripten
def load_metadata_wasm(metadata_raw, DEBUG):
    try:
        metadata_json = json.loads(metadata_raw)
    except Exception:
        logger.error(
            'emscript: failure to parse metadata output from wasm-emscripten-finalize. raw output is: \n'
            + metadata_raw)
        raise

    metadata = {
        'declares': [],
        'externs': [],
        'staticBump': 0,
        'tableSize': 0,
        'exports': [],
        'namedGlobals': {},
        'emJsFuncs': {},
        'asmConsts': {},
        'invokeFuncs': [],
        'features': [],
        'mainReadsParams': 1,
    }
    legacy_keys = set(['implementedFunctions', 'initializers', 'simd'])

    assert 'tableSize' in metadata_json.keys()
    for key, value in metadata_json.items():
        if key in legacy_keys:
            continue
        # json.loads returns `unicode` for strings but other code in this file
        # generally works with utf8 encoded `str` objects, and they don't alwasy
        # mix well.  e.g. s.replace(x, y) will blow up is `s` a uts8 str containing
        # non-ascii and either x or y are unicode objects.
        # TODO(sbc): Remove this encoding if we switch to unicode elsewhere
        # (specifically the glue returned from compile_settings)
        if type(value) == list:
            value = [asstr(v) for v in value]
        if key not in metadata:
            exit_with_error(
                'unexpected metadata key received from wasm-emscripten-finalize: %s',
                key)
        metadata[key] = value

    if DEBUG:
        logger.debug("Metadata parsed: " + pprint.pformat(metadata))

    # Calculate the subset of exports that were explicitly marked with llvm.used.
    # These are any exports that were not requested on the command line and are
    # not known auto-generated system functions.
    unexpected_exports = [
        e for e in metadata['exports'] if treat_as_user_function(e)
    ]
    unexpected_exports = [asmjs_mangle(e) for e in unexpected_exports]
    unexpected_exports = [
        e for e in unexpected_exports
        if e not in shared.Settings.EXPORTED_FUNCTIONS
    ]
    building.user_requested_exports += unexpected_exports

    return metadata
コード例 #3
0
def load_metadata_json(metadata_raw):
    try:
        metadata_json = json.loads(metadata_raw)
    except Exception:
        logger.error(
            'emscript: failure to parse metadata output from wasm-emscripten-finalize. raw output is: \n'
            + metadata_raw)
        raise

    metadata = {
        'declares': [],
        'globalImports': [],
        'exports': [],
        'namedGlobals': {},
        'emJsFuncs': {},
        'asmConsts': {},
        'invokeFuncs': [],
        'features': [],
        'mainReadsParams': 1,
    }

    for key, value in metadata_json.items():
        if key not in metadata:
            exit_with_error(
                'unexpected metadata key received from wasm-emscripten-finalize: %s',
                key)
        metadata[key] = value

    if DEBUG:
        logger.debug("Metadata parsed: " + pprint.pformat(metadata))

    expected_exports = set(settings.EXPORTED_FUNCTIONS)
    expected_exports.update(asmjs_mangle(s) for s in settings.REQUIRED_EXPORTS)

    # Calculate the subset of exports that were explicitly marked with llvm.used.
    # These are any exports that were not requested on the command line and are
    # not known auto-generated system functions.
    unexpected_exports = [
        e for e in metadata['exports'] if treat_as_user_function(e)
    ]
    unexpected_exports = [asmjs_mangle(e) for e in unexpected_exports]
    unexpected_exports = [
        e for e in unexpected_exports if e not in expected_exports
    ]
    building.user_requested_exports.update(unexpected_exports)
    settings.EXPORTED_FUNCTIONS.extend(unexpected_exports)

    return metadata
コード例 #4
0
def load_metadata_wasm(metadata_raw, DEBUG):
    try:
        metadata_json = json.loads(metadata_raw)
    except Exception:
        logger.error(
            'emscript: failure to parse metadata output from wasm-emscripten-finalize. raw output is: \n'
            + metadata_raw)
        raise

    metadata = {
        'aliases': {},
        'declares': [],
        'implementedFunctions': [],
        'externs': [],
        'simd': False,  # Obsolete, always False
        'maxGlobalAlign': 0,
        'staticBump': 0,
        'tableSize': 0,
        'initializers': [],
        'exports': [],
        'namedGlobals': {},
        'emJsFuncs': {},
        'asmConsts': {},
        'invokeFuncs': [],
        'features': [],
        'mainReadsParams': 1,
    }

    assert 'tableSize' in metadata_json.keys()
    for key, value in metadata_json.items():
        # json.loads returns `unicode` for strings but other code in this file
        # generally works with utf8 encoded `str` objects, and they don't alwasy
        # mix well.  e.g. s.replace(x, y) will blow up is `s` a uts8 str containing
        # non-ascii and either x or y are unicode objects.
        # TODO(sbc): Remove this encoding if we switch to unicode elsewhere
        # (specifically the glue returned from compile_settings)
        if type(value) == list:
            value = [asstr(v) for v in value]
        if key not in metadata:
            exit_with_error(
                'unexpected metadata key received from wasm-emscripten-finalize: %s',
                key)
        metadata[key] = value

    if not shared.Settings.MINIMAL_RUNTIME:
        # In regular runtime initializers call the global var version of the export, so they get the mangled name.
        # In MINIMAL_RUNTIME, the initializers are called directly off the export object for minimal code size.
        metadata['initializers'] = [
            asmjs_mangle(i) for i in metadata['initializers']
        ]

    if DEBUG:
        logger.debug("Metadata parsed: " + pprint.pformat(metadata))

    # Calculate the subset of exports that were explicitly marked with llvm.used.
    # These are any exports that were not requested on the command line and are
    # not known auto-generated system functions.
    unexpected_exports = [
        e for e in metadata['exports'] if treat_as_user_function(e)
    ]
    unexpected_exports = [asmjs_mangle(e) for e in unexpected_exports]
    unexpected_exports = [
        e for e in unexpected_exports
        if e not in shared.Settings.EXPORTED_FUNCTIONS
    ]
    building.user_requested_exports += unexpected_exports

    # With the wasm backend the set of implemented functions is identical to the set of exports
    # Set this key here simply so that the shared code that handle it.
    metadata['implementedFunctions'] = [
        asmjs_mangle(x) for x in metadata['exports']
    ]

    return metadata
コード例 #5
0
ファイル: emscripten.py プロジェクト: aheejin/emscripten
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', 'python')
    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)

    expected_exports = set(settings.EXPORTED_FUNCTIONS)
    expected_exports.update(asmjs_mangle(s) for s in settings.REQUIRED_EXPORTS)

    # Calculate the subset of exports that were explicitly marked with llvm.used.
    # These are any exports that were not requested on the command line and are
    # not known auto-generated system functions.
    unexpected_exports = [
        e for e in metadata['exports'] if treat_as_user_function(e)
    ]
    unexpected_exports = [asmjs_mangle(e) for e in unexpected_exports]
    unexpected_exports = [
        e for e in unexpected_exports if e not in expected_exports
    ]
    building.user_requested_exports.update(unexpected_exports)
    settings.EXPORTED_FUNCTIONS.extend(unexpected_exports)

    return metadata