Skip to content

Commit 0345c79

Browse files
authored
Explicitly set bulk memory and nontrapping-fptoint clang flags (#22751)
When clang starts enabling features by default that Emscripten's minimum browser versions want disabled, Emscripten will need to explicitly disable them. This PR does that; once clang rolls, we can update the default versions and tests in a single commit if needed. See also llvm/llvm-project#112049
1 parent 7d18aa3 commit 0345c79

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

emcc.py

+9
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,15 @@ def get_clang_flags(user_args):
384384
if '-mbulk-memory' not in user_args:
385385
flags.append('-mbulk-memory')
386386

387+
# In emscripten we currently disable bulk memory by default.
388+
# This should be removed/updated when we als update the default browser targets.
389+
if '-mbulk-memory' not in user_args and '-mno-bulk-memory' not in user_args:
390+
# Bulk memory may be enabled via threads or directly via -s.
391+
if not settings.BULK_MEMORY:
392+
flags.append('-mno-bulk-memory')
393+
if '-mnontrapping-fptoint' not in user_args and '-mno-nontrapping-fptoint' not in user_args:
394+
flags.append('-mno-nontrapping-fptoint')
395+
387396
if settings.RELOCATABLE and '-fPIC' not in user_args:
388397
flags.append('-fPIC')
389398

test/test_other.py

+45
Original file line numberDiff line numberDiff line change
@@ -10268,6 +10268,51 @@ def test_wasm_features_section(self, args):
1026810268
self.run_process([EMCC, test_file('hello_world.c'), '-O2'] + args)
1026910269
self.verify_custom_sec_existence('a.out.wasm', 'target_features', False)
1027010270

10271+
def test_wasm_features(self):
10272+
# Test that wasm features are explicitly enabled or disabled based on target engine version
10273+
def verify_features_sec(feature, expect_in, linked=False):
10274+
with webassembly.Module('a.out.wasm' if linked else 'hello_world.o') as module:
10275+
features = module.get_target_features()
10276+
if expect_in:
10277+
self.assertTrue(feature in features and
10278+
features[feature] == webassembly.TargetFeaturePrefix.USED,
10279+
f'{feature} missing from wasm file')
10280+
else:
10281+
self.assertFalse(feature in features,
10282+
f'{feature} unexpectedly found in wasm file')
10283+
10284+
def verify_features_sec_linked(feature, expect_in):
10285+
return verify_features_sec(feature, expect_in, linked=True)
10286+
10287+
def compile(flags):
10288+
self.run_process([EMCC, test_file('hello_world.c')] + flags)
10289+
10290+
compile(['-c'])
10291+
verify_features_sec('bulk-memory', False)
10292+
verify_features_sec('nontrapping-fptoint', False)
10293+
verify_features_sec('sign-ext', True)
10294+
verify_features_sec('mutable-globals', True)
10295+
verify_features_sec('multivalue', True)
10296+
verify_features_sec('reference-types', True)
10297+
10298+
compile(['-mnontrapping-fptoint', '-c'])
10299+
verify_features_sec('nontrapping-fptoint', True)
10300+
10301+
# BIGINT causes binaryen to not run, and keeps the target_features section after link
10302+
# Setting this SAFARI_VERSION should enable bulk memory because it links in emscripten_memcpy_bulkmem
10303+
# However it does not enable nontrapping-fptoint yet because it has no effect at compile time and
10304+
# no libraries include nontrapping yet.
10305+
compile(['-sMIN_SAFARI_VERSION=150000', '-sWASM_BIGINT'])
10306+
verify_features_sec_linked('sign-ext', True)
10307+
verify_features_sec_linked('mutable-globals', True)
10308+
verify_features_sec_linked('multivalue', True)
10309+
verify_features_sec_linked('bulk-memory', True)
10310+
verify_features_sec_linked('nontrapping-fptoint', False)
10311+
10312+
compile(['-sMIN_SAFARI_VERSION=150000', '-mno-bulk-memory', '-sWASM_BIGINT'])
10313+
# FIXME? -mno-bulk-memory at link time does not override MIN_SAFARI_VERSION. it probably should?
10314+
verify_features_sec_linked('bulk-memory', True)
10315+
1027110316
def test_js_preprocess(self):
1027210317
# Use stderr rather than stdout here because stdout is redirected to the output JS file itself.
1027310318
create_file('lib.js', '''

tools/webassembly.py

+18
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,12 @@ class DylinkType(IntEnum):
162162
IMPORT_INFO = 4
163163

164164

165+
class TargetFeaturePrefix(IntEnum):
166+
USED = 0x2b
167+
DISALLOWED = 0x2d
168+
REQUIRED = 0x3d
169+
170+
165171
class InvalidWasmError(BaseException):
166172
pass
167173

@@ -561,6 +567,18 @@ def get_function_type(self, idx):
561567
func_type = self.get_function_types()[idx - self.num_imported_funcs()]
562568
return self.get_types()[func_type]
563569

570+
def get_target_features(self):
571+
section = self.get_custom_section('target_features')
572+
self.seek(section.offset)
573+
assert self.read_string() == 'target_features'
574+
features = {}
575+
self.read_byte() # ignore feature count
576+
while self.tell() < section.offset + section.size:
577+
prefix = TargetFeaturePrefix(self.read_byte())
578+
feature = self.read_string()
579+
features[feature] = prefix
580+
return features
581+
564582

565583
def parse_dylink_section(wasm_file):
566584
with Module(wasm_file) as module:

0 commit comments

Comments
 (0)