Assembler XF resolves EQU in pass 1, so its operand must already be defined. as370 evaluates it in pass 1 too — but with the pass-1 table, where a symbol defined further down is not there yet, and x_factor substitutes 0 without a word.
Measured
T CSECT
A EQU B
B EQU 4
DC A(A)
END
000000 2 A EQU B
000000 3 B EQU 4
000000 00000000 4 DC A(A)
A is 0, not 4, and the assembly is RC 0 with no diagnostic. IFOX00 flags B as IFO188 B IS AN UNDEFINED SYMBOL (severity 8, jermsgcd.asm SEV188) — the same message #82 just implemented everywhere else.
Note that pass 2 does not repair it either: DC A(A) in pass 2 still reads 0, so the wrong value reaches the deck.
Why #82 does not cover it
The IFO188 recorder added in #82 is gated on g_pass == 2, and it has to be: a forward reference is legal in a machine instruction, and flagging one in pass 1 would reject every ordinary BE LATER. By pass 2 B is in the table and defined, so the EQU is silent.
The divergence is therefore in the quiet direction — as370 accepts what IFOX rejects, and produces a value IFOX never produces. It is adjacent to #82, not a regression from it: the behaviour predates that change.
What a fix needs
An EQU-specific check at the statement, in pass 1, over the operand's symbol terms — every one must already be defined (or S_ER) at that point. That is a stricter rule than the general x_factor one and must not leak into it.
Not measured yet: whether any ecosystem module relies on the current leniency. The #82 probe (826 modules) counted pass-2 lookups only, so it says nothing about this. Measure before changing behaviour — a corpus that quietly depends on a forward EQU would move decks.
Assembler XF resolves
EQUin pass 1, so its operand must already be defined. as370 evaluates it in pass 1 too — but with the pass-1 table, where a symbol defined further down is not there yet, andx_factorsubstitutes 0 without a word.Measured
Ais 0, not 4, and the assembly is RC 0 with no diagnostic. IFOX00 flagsBasIFO188 B IS AN UNDEFINED SYMBOL(severity 8,jermsgcd.asmSEV188) — the same message #82 just implemented everywhere else.Note that pass 2 does not repair it either:
DC A(A)in pass 2 still reads 0, so the wrong value reaches the deck.Why #82 does not cover it
The IFO188 recorder added in #82 is gated on
g_pass == 2, and it has to be: a forward reference is legal in a machine instruction, and flagging one in pass 1 would reject every ordinaryBE LATER. By pass 2Bis in the table and defined, so the EQU is silent.The divergence is therefore in the quiet direction — as370 accepts what IFOX rejects, and produces a value IFOX never produces. It is adjacent to #82, not a regression from it: the behaviour predates that change.
What a fix needs
An EQU-specific check at the statement, in pass 1, over the operand's symbol terms — every one must already be
defined(orS_ER) at that point. That is a stricter rule than the generalx_factorone and must not leak into it.Not measured yet: whether any ecosystem module relies on the current leniency. The #82 probe (826 modules) counted pass-2 lookups only, so it says nothing about this. Measure before changing behaviour — a corpus that quietly depends on a forward EQU would move decks.