diff options
Diffstat (limited to 'scripts/fuzz_opt.py')
-rwxr-xr-x | scripts/fuzz_opt.py | 99 |
1 files changed, 82 insertions, 17 deletions
diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py index d4e9ccc4d..1fa9d2ace 100755 --- a/scripts/fuzz_opt.py +++ b/scripts/fuzz_opt.py @@ -164,23 +164,88 @@ def randomize_fuzz_settings(): print('randomized settings (NaNs, OOB, legalize):', NANS, OOB, LEGALIZE) -IMPORTANT_INITIAL_CONTENTS = [ - # Perenially-important passes - os.path.join('lit', 'passes', 'optimize-instructions.wast'), - os.path.join('passes', 'optimize-instructions_fuzz-exec.wast'), - - # Recently-added or modified passes. These can be added to and pruned - # frequently. - os.path.join('lit', 'passes', 'once-reduction.wast'), - os.path.join('passes', 'remove-unused-brs_enable-multivalue.wast'), - os.path.join('lit', 'passes', 'optimize-instructions-bulk-memory.wast'), - os.path.join('lit', 'passes', 'optimize-instructions-ignore-traps.wast'), - os.path.join('lit', 'passes', 'optimize-instructions-gc.wast'), - os.path.join('lit', 'passes', 'optimize-instructions-gc-iit.wast'), - os.path.join('lit', 'passes', 'optimize-instructions-call_ref.wast'), - os.path.join('lit', 'passes', 'inlining_splitting.wast'), -] -IMPORTANT_INITIAL_CONTENTS = [os.path.join(shared.get_test_dir('.'), t) for t in IMPORTANT_INITIAL_CONTENTS] +def get_important_initial_contents(): + FIXED_IMPORTANT_INITIAL_CONTENTS = [ + # Perenially-important passes + os.path.join('lit', 'passes', 'optimize-instructions.wast'), + os.path.join('passes', 'optimize-instructions_fuzz-exec.wast'), + ] + MANUAL_RECENT_INITIAL_CONTENTS = [ + # Recently-added or modified passes. These can be added to and pruned + # frequently. + os.path.join('lit', 'passes', 'once-reduction.wast'), + os.path.join('passes', 'remove-unused-brs_enable-multivalue.wast'), + os.path.join('lit', 'passes', 'optimize-instructions-bulk-memory.wast'), + os.path.join('lit', 'passes', 'optimize-instructions-ignore-traps.wast'), + os.path.join('lit', 'passes', 'optimize-instructions-gc.wast'), + os.path.join('lit', 'passes', 'optimize-instructions-gc-iit.wast'), + os.path.join('lit', 'passes', 'optimize-instructions-call_ref.wast'), + os.path.join('lit', 'passes', 'inlining_splitting.wast'), + ] + RECENT_DAYS = 30 + + # Returns the list of test wast/wat files added or modified within the + # RECENT_DAYS number of days counting from the commit time of HEAD + def auto_select_recent_initial_contents(): + # Print 'git log' with changed file status and without commit messages, + # with commits within RECENT_DAYS number of days, counting from the + # commit time of HEAD. The reason we use the commit time of HEAD instead + # of the current system time is to make the results deterministic given + # the Binaryen HEAD commit. + from datetime import datetime, timedelta, timezone + head_ts_str = run(['git', 'log', '-1', '--format=%cd', '--date=raw'], + silent=True).split()[0] + head_dt = datetime.utcfromtimestamp(int(head_ts_str)) + start_dt = head_dt - timedelta(days=RECENT_DAYS) + start_ts = start_dt.replace(tzinfo=timezone.utc).timestamp() + log = run(['git', 'log', '--name-status', '--format=', '--date=raw', '--no-renames', f'--since={start_ts}'], silent=True).splitlines() + # Pick up lines in the form of + # A test/../something.wast + # M test/../something.wast + # (wat extension is also included) + p = re.compile(r'^[AM]\stest' + os.sep + r'(.*\.(wat|wast))$') + matches = [p.match(e) for e in log] + auto_set = set([match.group(1) for match in matches if match]) + auto_set = auto_set.difference(set(FIXED_IMPORTANT_INITIAL_CONTENTS)) + return sorted(list(auto_set)) + + def is_git_repo(): + try: + ret = run(['git', 'rev-parse', '--is-inside-work-tree'], + silent=True, stderr=subprocess.DEVNULL) + return ret == 'true\n' + except subprocess.CalledProcessError: + return False + + if not is_git_repo() and shared.options.auto_initial_contents: + print('Warning: The current directory is not a git repository, so you cannot use "--auto-initial-contents". Using the manually selected contents.\n') + shared.options.auto_initial_contents = False + + print('- Perenially-important initial contents:') + for test in FIXED_IMPORTANT_INITIAL_CONTENTS: + print(' ' + test) + print() + + recent_contents = [] + print('- Recently added or modified initial contents ', end='') + if shared.options.auto_initial_contents: + print(f'(automatically selected: within last {RECENT_DAYS} days):') + recent_contents += auto_select_recent_initial_contents() + else: + print('(manually selected):') + recent_contents = MANUAL_RECENT_INITIAL_CONTENTS + for test in recent_contents: + print(' ' + test) + print() + ret = input('Do you want to proceed with these initial contents? (Y/n) ').lower() + if ret != 'y' and ret != '': + sys.exit(1) + + initial_contents = FIXED_IMPORTANT_INITIAL_CONTENTS + recent_contents + return [os.path.join(shared.get_test_dir('.'), t) for t in initial_contents] + + +IMPORTANT_INITIAL_CONTENTS = get_important_initial_contents() def pick_initial_contents(): |