diff --git a/emcc.py b/emcc.py index 520ad404108b3..dfe088e7b75c0 100644 --- a/emcc.py +++ b/emcc.py @@ -46,6 +46,7 @@ from tools import cache from tools.settings import default_setting, user_settings, settings, MEM_SIZE_SETTINGS, COMPILE_TIME_SETTINGS from tools.utils import read_file, removeprefix +from tools import feature_matrix logger = logging.getLogger('emcc') @@ -1403,8 +1404,18 @@ def consume_arg_file(): settings.WASM_EXCEPTIONS = 0 elif arg == '-mbulk-memory': settings.BULK_MEMORY = 1 + feature_matrix.enable_feature(feature_matrix.Feature.BULK_MEMORY, + '-mbulk-memory', + override=True) elif arg == '-mno-bulk-memory': settings.BULK_MEMORY = 0 + feature_matrix.disable_feature(feature_matrix.Feature.BULK_MEMORY) + elif arg == '-msign-ext': + feature_matrix.enable_feature(feature_matrix.Feature.SIGN_EXT, + '-msign-ext', + override=True) + elif arg == '-mno-sign-ext': + feature_matrix.disable_feature(feature_matrix.Feature.SIGN_EXT) elif arg == '-fexceptions': # TODO Currently -fexceptions only means Emscripten EH. Switch to wasm # exception handling by default when -fexceptions is given when wasm diff --git a/test/test_other.py b/test/test_other.py index c0c6f33c3d1f0..bbef918ae4fa8 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -10434,23 +10434,37 @@ def compile(flags): verify_features_sec('multivalue', True) verify_features_sec('reference-types', True) + # Disable a feature + compile(['-mno-sign-ext', '-c']) + verify_features_sec('sign-ext', False) + # Disabling overrides default browser versions + compile(['-mno-sign-ext']) + verify_features_sec_linked('sign-ext', False) + # Disabling overrides manual browser versions + compile(['-sMIN_SAFARI_VERSION=150000', '-mno-sign-ext']) + # Disable via browser selection + compile(['-sMIN_FIREFOX_VERSION=61']) + verify_features_sec_linked('sign-ext', False) + # Manual enable overrides browser version + compile(['-sMIN_FIREFOX_VERSION=61', '-msign-ext']) + verify_features_sec_linked('sign-ext', True) + compile(['-mnontrapping-fptoint', '-c']) verify_features_sec('nontrapping-fptoint', True) - # BIGINT causes binaryen to not run, and keeps the target_features section after link # Setting this SAFARI_VERSION should enable bulk memory because it links in emscripten_memcpy_bulkmem # However it does not enable nontrapping-fptoint yet because it has no effect at compile time and # no libraries include nontrapping yet. - compile(['-sMIN_SAFARI_VERSION=150000', '-sWASM_BIGINT']) + compile(['-sMIN_SAFARI_VERSION=150000']) verify_features_sec_linked('sign-ext', True) verify_features_sec_linked('mutable-globals', True) verify_features_sec_linked('multivalue', True) verify_features_sec_linked('bulk-memory', True) verify_features_sec_linked('nontrapping-fptoint', False) - compile(['-sMIN_SAFARI_VERSION=150000', '-mno-bulk-memory', '-sWASM_BIGINT']) - # FIXME? -mno-bulk-memory at link time does not override MIN_SAFARI_VERSION. it probably should? - verify_features_sec_linked('bulk-memory', True) + compile(['-sMIN_SAFARI_VERSION=150000', '-mno-bulk-memory']) + # -mno-bulk-memory at link time overrides MIN_SAFARI_VERSION + verify_features_sec_linked('bulk-memory', False) def test_js_preprocess(self): # Use stderr rather than stdout here because stdout is redirected to the output JS file itself. diff --git a/tools/feature_matrix.py b/tools/feature_matrix.py index 0b6a26368e99e..53ee6f66ce716 100644 --- a/tools/feature_matrix.py +++ b/tools/feature_matrix.py @@ -39,6 +39,8 @@ class Feature(IntEnum): default_features = {Feature.SIGN_EXT, Feature.MUTABLE_GLOBALS} +disable_override_features = set() +enable_override_features = set() min_browser_versions = { Feature.NON_TRAPPING_FPTOINT: { @@ -93,6 +95,11 @@ class Feature(IntEnum): def caniuse(feature): + if feature in disable_override_features: + return False + if feature in enable_override_features: + return True + min_versions = min_browser_versions[feature] def report_missing(setting_name): @@ -114,10 +121,12 @@ def report_missing(setting_name): return True -def enable_feature(feature, reason): +def enable_feature(feature, reason, override=False): """Updates default settings for browser versions such that the given feature is available everywhere. """ + if override: + enable_override_features.add(feature) for name, min_version in min_browser_versions[feature].items(): name = f'MIN_{name.upper()}_VERSION' if settings[name] < min_version: @@ -132,6 +141,12 @@ def enable_feature(feature, reason): setattr(settings, name, min_version) +def disable_feature(feature): + """Allow the user to disable a feature that would otherwise be on by default. + """ + disable_override_features.add(feature) + + # apply minimum browser version defaults based on user settings. if # a user requests a feature that we know is only supported in browsers # from a specific version and above, we can assume that browser version.