Files
BFM-decomp/phase-ends/current/logs/T3.c4.md
T

3.8 KiB

T3.c4 — check-casts unbacked 96 → 0

Causes (96 unbacked K sites, 31 bodies, 18 files; scratch .run/T3c4/diag.py, diag2.py)

  • 60 base spelling local:param_1 (restruct) vs param:param_1 (census): restruct file_view/body_sites params_of matched only d["name"](; an alias-named def (func_X_impl(…) __asm__("func_X")) found no params → every param base classed local. Census find_decls_and_flows has the alias fallback (type_census.py:488-490). Rows t3_S1 32, S8 8, S10 6, S2 7, S3 4, S18 3. Side effect: those bodies' bbt bases (param:…) never met their sites → sites classed NON-STRUCT.
  • 23 superseded: a later S row re-judged a body already respelled; macro (form K) sites are not RAW_FORMS → the latest row has no KEPT entry for them (17: MEMBERS/KEPT rows, an earlier row backs exactly; 6: latest NO-SITE, outside BACKED_S_VERDICTS).
  • 13 nested base spelling: outer KEPT row keyed on pre-respell text (nested:*(s32 **)(a0 + 0x20)); after the inner site became CAST_SIGN(…) (or a member) the census parses the outer macro's base as other:None / another nested text. Same off, same line.
  • None from off format; no respell without a KEPT row.

Fix (tools/restruct.py)

  • params_of alias fallback in body_sites and file_view (census rule).
  • s_macro_rows(tu, text, rows) (called in work_file_S before the UNCHANGED return): every K site of a drawn body in the final text gets a KEPT(<cls>) row in the census key (site_row of the K site, macro_of=backing label), backed only by an entry KEPT() of this row or an earlier rung-S row of the body (s_prior_rows, lazy ledger index S_PRIOR) with same off and (same base or same line); REINTERP by line. No-edit verdict (NO-SITE/TYPE-NOT-*) carrying one → KEPT. Unbacked macros get nothing (gate stays red).
  • --redraw for rung S in --apply (was D only; key (rung,tu,unit)); lifted bodies not s_finished. --only TU:FN names one body (overlay fn names repeat). A lifted named TU:FN body with no drawable base (plan_S skips: bbt has only type-not-canonical bases) is re-walked with {} bases.
  • selftest: alias-def param control; real-case control (func_8017DD0C shape: CAST_WIDTH(s32, CAST_SIGN(s32 *, a0, 0x20), 8), prior t3_S1 row nested key, re-judge NO-SITE) negative unbacked 2 without prior row, positive KEPT unbacked 0 with it; TU:FN only. 93/93.
  • type_census matcher unchanged.

Backing

  • R22 make clean && make extract-all JOBS=16 && make check-all JOBS=16 → 218 passed, 0 failed of 218 (on 0938e511ed+); delever_oracle --snapshot-baseline (7428 objects); --calibrate ov_SC04_011 ov_SC03_015 md_SC07_004 main -j 16 OK (re-run at a83e31047f after the 3rd tool commit).
  • restruct --apply --rung S --batch 50 --label t3c4_rejudge --redraw KEPT MEMBERS NO-SITE -j 12 --only <31 TU:FN> (.run/T3c4/only.txt) → 18 files UNCHANGED, written 0, 31 rows all KEPT, 122 macro rows carried (t3_S1 57, S4 11, S2 16, S3 15, S8 8, S10 6, S5 4, S18 3, S9 1, S15 1). src untouched → no make check needed (git status src clean).
  • First apply attempt: plan_S drew 0 (all 18 bases type-not-canonical) → the named-body re-walk added.

Verified

  • type_census.py --sites --check-casts -j 16 → … (unbacked 0); lying=229 (ledgered 0) (rc 1 for raw, expected).
  • restruct.py --selftest 93/93; type_census.py --selftest 50/50; make kit-corpus ok; make tools-health OK.

For the expert

  • Bodies re-judged here now have bases=[] rows (not s_judged): not done, but plan_S never draws them (no usable base).
  • Latent: a REFUSED / COMBINATION-FAILED row on a body holding macros leaves them unbacked (not in the 96).
  • --plan path does not apply --redraw for S (apply only).
  • Census outputs under .run/P37/census and .run/P36/delever/calibration.json were already dirty at start; not committed here.