Problem
The HandleStelemI1 method in IL2NESWriter.ArrayHandling.cs emits arithmetic operations in a hardcoded order rather than preserving the order from the original IL. This means expressions where the C# evaluation order differs from the hardcoded emit order will produce incorrect 6502 code.
Current behavior
Operations are emitted in a fixed sequence regardless of IL order:
Constant-index path (line ~1443): shr -> and -> add -> or -> sub
Call/variable-index paths (multiple locations): and -> sub -> add -> or or and -> add -> or -> sub
For example, (v | 0xF0) + 1 in C# compiles to IL: ldloc, ldc 0xF0, or, ldc 1, add. But the transpiler emits ADC #$01 before ORA #$F0 because ADD is hardcoded before OR, producing the wrong result (0xF6 instead of 0xF1 for v = 5).
Affected code paths
All arithmetic emission blocks in HandleStelemI1 share this pattern - at least 6 separate locations where if (hasAnd) ... if (hasAdd) ... if (hasOr) ... if (hasSub) chains appear with a fixed order:
- Constant-index with local arithmetic (~line 1443-1456)
- Call pattern with AND/SUB/ADD/OR (~line 1733-1750)
- Multiply pattern (~line 1764-1768)
- Self-referencing update (~line 1778-1792)
- Cross-array copy (~line 1811-1825)
- Two-locals arithmetic (~line 1832-1842)
- Single-local value (~line 1867-1876)
Suggested approach
Instead of boolean flags (hasAdd, hasOr, etc.), record the operation sequence as an ordered list while scanning IL instructions. Then emit the 6502 operations in that recorded order. This preserves the C# evaluation semantics.
A simpler alternative: validate that the IL order matches the assumed emit order, and fall back to a non-optimized emission path (e.g., stack-based evaluation) when it doesn't match. This limits the blast radius of the fix.
Context
Discovered during review of PR #466 (adding OR support to stelem.i1). The issue predates that PR - AND, ADD, and SUB already had the same fixed-order behavior.
Problem
The
HandleStelemI1method inIL2NESWriter.ArrayHandling.csemits arithmetic operations in a hardcoded order rather than preserving the order from the original IL. This means expressions where the C# evaluation order differs from the hardcoded emit order will produce incorrect 6502 code.Current behavior
Operations are emitted in a fixed sequence regardless of IL order:
Constant-index path (line ~1443):
shr -> and -> add -> or -> subCall/variable-index paths (multiple locations):
and -> sub -> add -> ororand -> add -> or -> subFor example,
(v | 0xF0) + 1in C# compiles to IL:ldloc, ldc 0xF0, or, ldc 1, add. But the transpiler emitsADC #$01beforeORA #$F0because ADD is hardcoded before OR, producing the wrong result (0xF6instead of0xF1forv = 5).Affected code paths
All arithmetic emission blocks in
HandleStelemI1share this pattern - at least 6 separate locations whereif (hasAnd) ... if (hasAdd) ... if (hasOr) ... if (hasSub)chains appear with a fixed order:Suggested approach
Instead of boolean flags (
hasAdd,hasOr, etc.), record the operation sequence as an ordered list while scanning IL instructions. Then emit the 6502 operations in that recorded order. This preserves the C# evaluation semantics.A simpler alternative: validate that the IL order matches the assumed emit order, and fall back to a non-optimized emission path (e.g., stack-based evaluation) when it doesn't match. This limits the blast radius of the fix.
Context
Discovered during review of PR #466 (adding OR support to stelem.i1). The issue predates that PR - AND, ADD, and SUB already had the same fixed-order behavior.