Skip to content

Commit b238cc0

Browse files
Write binaries directly with s2wasm (emscripten-core#6323)
* Read invoke_funcs from metadata now * Initial support for binary-only s2wasm * Fix source map test expectations * Remove commented-out debug copy * Remove unused wast_temp * Actually call self.is_wasm_backend
1 parent 37bc37f commit b238cc0

File tree

3 files changed

+37
-49
lines changed

3 files changed

+37
-49
lines changed

emcc.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,9 +1625,7 @@ def get_final():
16251625
if shared.Settings.WASM_BACKEND:
16261626
# we also received wast and wasm at this stage
16271627
temp_basename = unsuffixed(final)
1628-
wast_temp = temp_basename + '.wast'
16291628
wasm_temp = temp_basename + '.wasm'
1630-
shutil.move(wast_temp, wasm_text_target)
16311629
shutil.move(wasm_temp, wasm_binary_target)
16321630
open(wasm_text_target + '.mappedGlobals', 'w').write('{}') # no need for mapped globals for now, but perhaps some day
16331631
if options.debug_level >= 4 and not shared.Settings.EXPERIMENTAL_USE_LLD:

emscripten.py

Lines changed: 25 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,10 +1732,9 @@ def emscript_wasm_backend(infile, settings, outfile, libraries=None, compiler_en
17321732
if libraries is None: libraries = []
17331733

17341734
if shared.Settings.EXPERIMENTAL_USE_LLD:
1735-
wast, metadata = build_wasm_lld(temp_files, infile, outfile, settings, DEBUG)
1735+
wasm, metadata = build_wasm_lld(temp_files, infile, outfile, settings, DEBUG)
17361736
else:
1737-
wast = build_wasm(temp_files, infile, outfile, settings, DEBUG)
1738-
metadata = read_metadata_wast(wast, DEBUG)
1737+
wasm, metadata = build_wasm(temp_files, infile, outfile, settings, DEBUG)
17391738

17401739
# optimize syscalls
17411740

@@ -1789,7 +1788,7 @@ def emscript_wasm_backend(infile, settings, outfile, libraries=None, compiler_en
17891788
outfile.write(pre)
17901789
pre = None
17911790

1792-
invoke_funcs = read_wast_invoke_imports(wast)
1791+
invoke_funcs = metadata.get('invokeFuncs', [])
17931792
# List of function signatures used in jsCall functions, e.g.['v', 'vi']
17941793
jscall_sigs = metadata.get('jsCallFuncType', [])
17951794

@@ -1827,33 +1826,29 @@ def build_wasm(temp_files, infile, outfile, settings, DEBUG):
18271826

18281827
assert shared.Settings.BINARYEN_ROOT, 'need BINARYEN_ROOT config set so we can use Binaryen s2wasm on the backend output'
18291828
basename = shared.unsuffixed(outfile.name)
1830-
wast = basename + '.wast'
18311829
wasm = basename + '.wasm'
1832-
s2wasm_args = create_s2wasm_args(temp_s)
1833-
if DEBUG:
1834-
logging.debug('emscript: binaryen s2wasm: ' + ' '.join(s2wasm_args))
1835-
t = time.time()
1836-
#s2wasm_args += ['--debug']
1837-
shared.check_call(s2wasm_args, stdout=open(wast, 'w'))
1838-
# Also convert wasm text to binary
1839-
wasm_as_args = [os.path.join(shared.Settings.BINARYEN_ROOT, 'bin', 'wasm-as'),
1840-
wast, '-o', wasm]
1830+
metadata_file = basename + '.metadata'
1831+
s2wasm_args = create_s2wasm_args(temp_s, wasm)
18411832
if settings['DEBUG_LEVEL'] >= 2 or settings['PROFILING_FUNCS']:
1842-
wasm_as_args += ['-g']
1833+
s2wasm_args += ['-g']
18431834
if settings['DEBUG_LEVEL'] >= 4:
1844-
wasm_as_args += ['--source-map=' + wasm + '.map']
1835+
s2wasm_args += ['--source-map=' + wasm + '.map']
18451836
if not settings['SOURCE_MAP_BASE']:
18461837
logging.warn("Wasm source map won't be usable in a browser without --source-map-base")
18471838
else:
1848-
wasm_as_args += ['--source-map-url=' + settings['SOURCE_MAP_BASE'] + os.path.basename(settings['WASM_BINARY_FILE']) + '.map']
1849-
logging.debug(' emscript: binaryen wasm-as: ' + ' '.join(wasm_as_args))
1850-
shared.check_call(wasm_as_args)
1839+
s2wasm_args += ['--source-map-url=' + settings['SOURCE_MAP_BASE'] + os.path.basename(settings['WASM_BINARY_FILE']) + '.map']
1840+
if DEBUG:
1841+
logging.debug('emscript: binaryen s2wasm: ' + ' '.join(s2wasm_args))
1842+
t = time.time()
1843+
#s2wasm_args += ['--debug']
1844+
shared.check_call(s2wasm_args, stdout=open(metadata_file, 'w'))
1845+
1846+
metadata = create_metadata_wasm(open(metadata_file).read(), DEBUG)
18511847

18521848
if DEBUG:
18531849
logging.debug(' emscript: binaryen s2wasm took %s seconds' % (time.time() - t))
18541850
t = time.time()
1855-
shutil.copyfile(wast, os.path.join(shared.CANONICAL_TEMP_DIR, 'emcc-s2wasm-output.wast'))
1856-
return wast
1851+
return wasm, metadata
18571852

18581853

18591854
def build_wasm_lld(temp_files, infile, outfile, settings, DEBUG):
@@ -1882,8 +1877,8 @@ def debug_copy(src, dst):
18821877
debug_copy(temp_o, 'emcc-llvm-backend-output.o')
18831878

18841879
basename = shared.unsuffixed(outfile.name)
1885-
wast = basename + '.wast'
18861880
wasm = basename + '.wasm'
1881+
metadata_file = basename + '.metadata'
18871882
base_wasm = basename + '.lld.wasm'
18881883

18891884
libc_rt_lib = shared.Cache.get('wasm_libc_rt.a', wasm_rt_fail('wasm_libc_rt.a'), 'a')
@@ -1907,20 +1902,15 @@ def debug_copy(src, dst):
19071902
t = time.time()
19081903
debug_copy(base_wasm, 'base_wasm.wasm')
19091904

1910-
# TODO: We currently read exports from the wast in order to generate
1911-
# metadata. So we emit text here so we can parse wast from python.
1912-
shared.check_call([wasm_emscripten_finalize, base_wasm, '-o', wast, '-S',
1905+
shared.check_call([wasm_emscripten_finalize, base_wasm, '-o', wasm,
19131906
'--global-base=%s' % shared.Settings.GLOBAL_BASE,
19141907
('--emscripten-reserved-function-pointers=%d' %
1915-
shared.Settings.RESERVED_FUNCTION_POINTERS)])
1916-
debug_copy(wast, 'lld-emscripten-output.wast')
1908+
shared.Settings.RESERVED_FUNCTION_POINTERS)],
1909+
stdout=open(metadata_file, 'w'))
19171910

1918-
shared.check_call([wasm_as, wast, '-o', wasm])
1919-
debug_copy(wasm, 'lld-emscripten-output.wasm')
1911+
metadata = create_metadata_wasm(open(metadata_file).read(), DEBUG)
19201912

1921-
metadata = read_metadata_wast(wast, DEBUG)
1922-
1923-
return wast, metadata
1913+
return wasm, metadata
19241914

19251915

19261916
def read_metadata_wast(wast, DEBUG):
@@ -2028,17 +2018,6 @@ def create_em_js(forwarded_json, metadata):
20282018
return em_js_funcs
20292019

20302020

2031-
def read_wast_invoke_imports(wast):
2032-
invoke_funcs = []
2033-
for line in open(wast).readlines():
2034-
if line.strip().startswith('(import '):
2035-
parts = line.split()
2036-
func_name = parts[2][1:-1]
2037-
if func_name.startswith('invoke_'):
2038-
invoke_funcs.append(func_name)
2039-
return invoke_funcs
2040-
2041-
20422021
def create_sending_wasm(invoke_funcs, jscall_sigs, forwarded_json, metadata,
20432022
settings):
20442023
basic_funcs = ['abort', 'assert', 'enlargeMemory', 'getTotalMemory']
@@ -2158,13 +2137,13 @@ def wrapped():
21582137
raise Exception('Expected {} to already be built'.format(archive_file))
21592138
return wrapped
21602139

2161-
def create_s2wasm_args(temp_s):
2140+
def create_s2wasm_args(temp_s, wasm):
21622141
compiler_rt_lib = shared.Cache.get('wasm_compiler_rt.a', wasm_rt_fail('wasm_compiler_rt.a'), 'a')
21632142
libc_rt_lib = shared.Cache.get('wasm_libc_rt.a', wasm_rt_fail('wasm_libc_rt.a'), 'a')
21642143

21652144
s2wasm_path = os.path.join(shared.Settings.BINARYEN_ROOT, 'bin', 's2wasm')
21662145

2167-
args = [s2wasm_path, temp_s, '--emscripten-glue']
2146+
args = [s2wasm_path, temp_s, '-o', wasm, '--emscripten-glue', '--emit-binary']
21682147
args += ['--global-base=%d' % shared.Settings.GLOBAL_BASE]
21692148
args += ['--initial-memory=%d' % shared.Settings.TOTAL_MEMORY]
21702149
args += ['--allow-memory-growth'] if shared.Settings.ALLOW_MEMORY_GROWTH else []
@@ -2194,6 +2173,7 @@ def load_metadata(metadata_raw):
21942173
'initializers': [],
21952174
'exports': [],
21962175
'emJsFuncs': {},
2176+
'invokeFuncs': [],
21972177
}
21982178

21992179
for k, v in metadata_json.items():

tests/test_core.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6929,8 +6929,18 @@ def encode_utf8(data):
69296929
# the file attribute is optional, but if it is present it needs to refer
69306930
# the output file.
69316931
self.assertPathsIdentical(map_referent, data['file'])
6932-
assert len(data['sources']) == 1, data['sources']
6933-
self.assertPathsIdentical(src_filename, data['sources'][0])
6932+
if not self.is_wasm_backend():
6933+
assert len(data['sources']) == 1, data['sources']
6934+
self.assertPathsIdentical(src_filename, data['sources'][0])
6935+
else:
6936+
# Wasm backend currently adds every file linked as part of compiler-rt
6937+
# to the 'sources' field.
6938+
# TODO(jgravelle): when LLD is the wasm-backend default, make sure it
6939+
# emits only the files we have lines for.
6940+
assert len(data['sources']) > 1, data['sources']
6941+
normalized_srcs = [src.replace('\\', '/') for src in data['sources']]
6942+
normalized_filename = src_filename.replace('\\', '/')
6943+
assert normalized_filename in normalized_srcs, "Source file not found"
69346944
if hasattr(data, 'sourcesContent'):
69356945
# the sourcesContent attribute is optional, but if it is present it
69366946
# needs to containt valid source text.

0 commit comments

Comments
 (0)