3.5 KiB
§261 — THE -O0 ORACLE: DERIVE THE OPT LEVEL FROM THE TARGET, AND $fp IS NOT THE TELL (P31 S59)
match_one --o0 existed for a year and nothing ever passed it. api_draft.match_one() — the
oracle every wave agent iterates against — builds a fixed argv without it, so an agent handed an
-O0 target was shown an -O2 compile of its own C and a mismatch on every instruction: feedback
that cannot converge, for a reason that never appears in the diff. It hit even the functions already
sitting in _o0 objects, where a match was otherwise bankable today.
DERIVE IT (R33), FROM TWO ORACLES (R34), BECAUSE NEITHER ALONE COVERS THE TREE:
- the target's own prologue —
sw $fp, N($sp)+addu $fp, $sp, $zero(21F0A003) inside the function's first instructions. gcc-2.7.2 keeps a frame pointer at -O0 and omits it at -O2. - the subseg's build flags —
bootand every*_o0*object are compiled -O0 by the Makefile.boot/start.sis -O0 with no ordinary prologue; only this oracle sees it.
$fp MENTIONS ARE NOT THE POPULATION. $fp is $s8, an ordinary allocatable callee-saved
register at -O2. Over 14,400 .s files: 311 mention $fp, 167 carry the -O0 prologue. Sizing a
lane off the 311 over-counts by 1.9×. Anchor the prologue scan at glabel, not the top of the file
— two md_MAIN_011 targets open with a migrated jump table / .asciz blob, and a naive "first 8
encoded lines" reads table words as the prologue and calls an -O0 function -O2.
A MATCH IS NOT A BANK FOR THIS CLASS. An -O0 function in an -O2 subseg cannot bank however
perfect the body: the object's CC1FLAGS decide, and the Makefile's -O0 globs cover boot,
ov_SC01_077_o0, src/ov_*/ov_*_o0.c and src/ov_*/ov_*_o0?.c — nothing matches src/md_*/.
Of the 167, 51 are inside an -O0 object and 116 (14,148 ins) are stranded in -O2 subsegs, so
match_one now says so on sight rather than letting an agent chase a body that can never land.
§261a — THE -O0 FRAME-RELOAD GRAMMAR: reload COUNT disambiguates the C spelling (P31 S59, byte-proven)
func_80184058 (131 ins, ov_SC03_014_o0c) banked on the FIRST compile — MATCH(131) then
whole-binary BYTE-IDENTICAL — because at -O0 the number of frame reloads of a pointer is a
fingerprint of the exact C spelling. Read it off the target before writing anything:
p->f += k(value unused) → 2 reloads ofp(STORE base first, read base second), no copy.--p->f/++p->f→ 3 reloads (the FIRST is dead), anaddu rd,rs,$zerocopy after the add, and — only when the value is used —sll 16; sra 16on the STORED register (no re-load). Soif (--p->f == 0)vsp->f -= 1; if (p->f == 0)(re-loads the field) vsp->f -= 1;(2 reloads, no copy) are all distinguishable from the asm alone.- s16 fields:
lhat a plain read, butlhuinside a read-modify-write. - Overlapping s32/s16 (a 16.16 accumulator at 0xE0 whose high half is read as the s16 at 0xE2):
spell the wide access through a SECOND struct view and cast the pointer —
((Ent_fx *)p)->unkE0 += 0x5CCCC;— the cast is free at -O0; no union needed. - §127a compounded: the decisive spellings (the call-arg marshaling,
++p->unk02) were lifted VERBATIM from banked siblings in the same_o0*TU. Read the TU's banked bodies first, always.
With the §261 auto-oracle + this grammar, an -O0 function is STRICTLY easier than -O2 of the same size: no scheduling, no regalloc steering, no permuter — every miss is a spelling miss, and the spelling is enumerable from the reload count.