Skip to content

Commit af76833

Browse files
authored
Only strip the producers' section in optimized builds (#11996)
In -O0 builds we want to leave the wasm from LLVM unmodified as much as possible (see WebAssembly/binaryen#3043), so this PR makes us stop modifying it to remove the producers section. There is no change to optimized builds (-O1+), so release builds are not changed in any way. There is also no change if the user told LLVM to not emit a producer's section in the first place. We basically just do less things on -O0 builds after this PR, and leave it to LLVM.
1 parent fe52d9b commit af76833

File tree

4 files changed

+52
-14
lines changed

4 files changed

+52
-14
lines changed

ChangeLog.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ See docs/process.md for how version tagging works.
1717

1818
Current Trunk
1919
-------------
20+
- Only strip the LLVM producer's section in release builds. In `-O0` builds, we
21+
try to leave the wasm from LLVM unmodified as much as possible, so if it
22+
emitted the producers section, it will be there. Normally that only matters
23+
in release builds, which is not changing here. If you want to not have a
24+
producer's section in debug builds, you can remove it a tool like
25+
`wasm-opt --strip-producers` (which is what Emscripten still does in release
26+
builds, as always) or use `llvm-objcopy`.
2027
- Do not remove `__original_main` using `--inline-main`. We used to do this
2128
so that it didn't show up in stack traces (which could be confusing because
2229
it is added by the linker - it's not in the source code). But this has had

emcc.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -603,8 +603,9 @@ def backend_binaryen_passes():
603603
passes += ['--low-memory-unused']
604604
if shared.Settings.DEBUG_LEVEL < 3:
605605
passes += ['--strip-debug']
606-
if not shared.Settings.EMIT_PRODUCERS_SECTION:
607-
passes += ['--strip-producers']
606+
if shared.Settings.OPT_LEVEL > 0:
607+
if not shared.Settings.EMIT_PRODUCERS_SECTION:
608+
passes += ['--strip-producers']
608609
if shared.Settings.AUTODEBUG:
609610
# adding '--flatten' here may make these even more effective
610611
passes += ['--instrument-locals']

src/settings.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,13 +1148,16 @@ var WASM_ASYNC_COMPILATION = 1;
11481148
var WASM_BIGINT = 0;
11491149

11501150
// WebAssembly defines a "producers section" which compilers and tools can
1151-
// annotate themselves in. Emscripten does not emit this by default, as it
1152-
// increases code size, and some users may not want information about their tools
1153-
// to be included in their builds for privacy or security reasons, see
1151+
// annotate themselves in, and LLVM emits this by default. In release builds,
1152+
// Emscripten will strip that out so that it is *not* emitted because it
1153+
// increases code size, and also some users may not want information
1154+
// about their tools to be included in their builds for privacy or security
1155+
// reasons, see
11541156
// https://github.com/WebAssembly/tool-conventions/issues/93.
1155-
// TODO: currently this flag just controls whether we run the binaryen pass
1156-
// to strip it out from the wasm (where the LLVM wasm backend may have
1157-
// created it)
1157+
// (In debug builds (-O0) we leave the wasm file as it is from LLVM, in which
1158+
// case it may contain this section, if you didn't tell LLVM to not emit it. You
1159+
// can also run wasm-opt --strip-producers manually, which is what Emscripten
1160+
// does in release builds for you automatically.)
11581161
var EMIT_PRODUCERS_SECTION = 0;
11591162

11601163
// If set then generated WASM files will contain a custom

tests/test_other.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,12 +2015,29 @@ def compile_to_debug_executable(compile_args):
20152015
self.assertLess(line_size, full_size)
20162016

20172017
def compile_to_release_executable(compile_args):
2018-
return compile_to_executable(compile_args, [])
2018+
return compile_to_executable(compile_args, ['-O1'])
20192019

20202020
no_size, line_size, full_size = test(compile_to_release_executable)
20212021
self.assertEqual(no_size, line_size)
20222022
self.assertEqual(line_size, full_size)
20232023

2024+
# "-O0 executable" means compiling without optimizations but *also* without
2025+
# -g (so, not a true debug build). the results here may change over time,
2026+
# since we are telling emcc both to try to do as little as possible during
2027+
# link (-O0), but also that debug info is not needed (no -g). if we end up
2028+
# doing post-link changes then we will strip the debug info, but if not then
2029+
# we don't.
2030+
def compile_to_O0_executable(compile_args):
2031+
return compile_to_executable(compile_args, [])
2032+
2033+
no_size, line_size, full_size = test(compile_to_O0_executable)
2034+
# the difference between these two is due to the producer's section which
2035+
# LLVM emits, and which we do not strip as this is not a release build.
2036+
# the specific difference is that LLVM emits language info (C_plus_plus_14)
2037+
# when emitting debug info, but not otherwise.
2038+
self.assertLess(no_size, line_size)
2039+
self.assertEqual(line_size, full_size)
2040+
20242041
def test_dwarf(self):
20252042
def compile_with_dwarf(args, output):
20262043
# Test that -g enables dwarf info in object files and linked wasm
@@ -7862,13 +7879,23 @@ def test_separate_dwarf_with_filename_and_path(self):
78627879
with open('a.out.wasm', 'rb') as f:
78637880
self.assertIn(b'somewhere.com/hosted.wasm', f.read())
78647881

7865-
def test_wasm_producers_section(self):
7866-
# no producers section by default
7867-
self.run_process([EMCC, path_from_root('tests', 'hello_world.c')])
7882+
@parameterized({
7883+
'O0': (True, ['-O0']), # unoptimized builds try not to modify the LLVM wasm.
7884+
'O1': (False, ['-O1']), # optimized builds strip the producer's section
7885+
'O2': (False, ['-O2']), # by default.
7886+
})
7887+
def test_wasm_producers_section(self, expect_producers_by_default, args):
7888+
self.run_process([EMCC, path_from_root('tests', 'hello_world.c')] + args)
78687889
with open('a.out.wasm', 'rb') as f:
7869-
self.assertNotIn('clang', str(f.read()))
7890+
data = f.read()
7891+
if expect_producers_by_default:
7892+
self.assertIn('clang', str(data))
7893+
return
7894+
# if there is no producers section expected by default, verify that, and
7895+
# see that the flag works to add it.
7896+
self.assertNotIn('clang', str(data))
78707897
size = os.path.getsize('a.out.wasm')
7871-
self.run_process([EMCC, path_from_root('tests', 'hello_world.c'), '-s', 'EMIT_PRODUCERS_SECTION=1'])
7898+
self.run_process([EMCC, path_from_root('tests', 'hello_world.c'), '-s', 'EMIT_PRODUCERS_SECTION=1'] + args)
78727899
with open('a.out.wasm', 'rb') as f:
78737900
self.assertIn('clang', str(f.read()))
78747901
size_with_section = os.path.getsize('a.out.wasm')

0 commit comments

Comments
 (0)