#!/usr/bin/env python3 """Regenerate the committed ISL artefacts under `docs/re/data/`. isl_report.py calls -> the call-site census + a listing The artefact was produced by an uncommitted one-off, so it drifted out of date twice: once when operand staging was fixed (calls printed with too few arguments) and once when three built-in names were corrected. Keeping the generator in the tree is the point of this file. isl_report.py phase-ends -> every END_PHASE with its context The "needs the coroutine entry points" blocker recorded here is REFUTED: the instruction stream is FLAT and `isl.linear_offsets` reaches 25705/25705 call sites across all 28 stages. What broke the naive linear decode was `isl.dis` stopping at op 20 (`ret`), which in a coroutine VM is a yield, not an end of code -- see `docs/re/isl-stream-is-flat.md`. """ import collections import sys import isl def census(b): cs = isl.call_sites(b) return cs, collections.Counter(bid for _, bid, _ in cs) def emit_calls(b, path): cs, h = census(b) s1, s2 = isl.symbols(b, 1), isl.symbols(b, 2) print('# %s — ISL disassembly artefacts' % path) print() print('Generated by `tools/re-capture/isl_report.py calls`.') print() print('%d call sites, %d distinct built-ins' % (len(cs), len(h))) for bid, n in h.most_common(): print(' builtin %-4d %5d site(s)' % (bid, n)) print() print('## phase-control sites') for bid, nm in ((6, 'END_PHASE'), (62, 'FORCE_END_PHASE'), (39, 'MARK_LAST_PHASE'), (40, 'mark_not_last')): offs = [off for off, b2, _ in cs if b2 == bid] print('%-3d %-18s %2d: %s' % (bid, nm, len(offs), ' '.join('0x%x' % o for o in offs))) print() print('## named built-ins used, by traffic') for bid, n in h.most_common(): nm = isl.BUILTIN.get(bid) if nm: print(' %-3d %-24s %4d' % (bid, nm, n)) print() print('## phase code bases') print('Each phase has its OWN base; the file header offset is not it.') print(' ' + ' '.join('0x%x' % x for x in isl.phase_bases(b))) print() print('## disassembly into the first END_PHASE') target = [off for off, bid, _ in cs if bid == 6][0] start = isl.resync(b, target) print('resync from 0x%X' % start) for line in isl.dis(b, start, 64, code_base=0x24, sym2=s2, sym1=s1): print(line) def emit_phase_ends(b, path): """Every phase-ending call with the instructions that lead into it.""" offs = isl.linear_offsets(b) idx = {o: k for k, o in enumerate(offs)} bases = isl.phase_bases(b) s1, s2 = isl.symbols(b, 1), isl.symbols(b, 2) ends = [(o, bid) for o, bid, _ in isl.call_sites(b) if bid in (6, 62)] print('# %s — where each phase ends' % path) print() print('Generated by `tools/re-capture/isl_report.py phase-ends`.') print('Decoded with `stop_at_ret=False`; a `ret` is a coroutine YIELD, so') print('the listing continues past it.') print() print('phase code bases: ' + ' '.join('0x%x' % x for x in bases)) print('%d phase-ending call(s): %d END_PHASE, %d FORCE_END_PHASE' % (len(ends), sum(1 for _, b2 in ends if b2 == 6), sum(1 for _, b2 in ends if b2 == 62))) for o, bid in ends: ph = sum(1 for x in bases if x <= o) k = idx.get(o) if k is None: print('\n## 0x%X builtin %d — NOT on the linear stream' % (o, bid)) continue print('\n## phase %d — builtin %d (%s) at 0x%X' % (ph, bid, isl.BUILTIN.get(bid, '?'), o)) for line in isl.dis(b, offs[max(0, k - 16)], 22, code_base=bases[ph - 1], sym2=s2, sym1=s1, stop_at_ret=False): print(' ' + line) def main(): path = sys.argv[1] b = isl.load(path) name = path.replace('\\', '/').split('/')[-1] {'calls': emit_calls, 'phase-ends': emit_phase_ends}[sys.argv[2]](b, name) if __name__ == '__main__': main()