Skip to content

Support static field byte[] arrays in ldelem.u1#275

Merged
jonathanpeppers merged 4 commits intomainfrom
copilot/fix-840039-430943403-fb21c864-21ec-4924-9b3b-06202277715e
Mar 18, 2026
Merged

Support static field byte[] arrays in ldelem.u1#275
jonathanpeppers merged 4 commits intomainfrom
copilot/fix-840039-430943403-fb21c864-21ec-4924-9b3b-06202277715e

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 18, 2026

Thanks for assigning this issue to me. I'm starting to work on it and will keep this PR's description up to date as I form a plan and make progress.

Original prompt

This section details on the original issue you should resolve

<issue_title>Transpiler: HandleLdelemU1 requires array in tracked local variable</issue_title>
<issue_description>## Problem

The transpiler's HandleLdelemU1ComplexIndex throws when the array being accessed is not stored in a tracked local variable. The error occurs during transpilation of the crypto sample after closure inlining.

TranspileException: Array element access requires the array to be stored in a local variable.
   at IL2NESWriter.HandleLdelemU1ComplexIndex() in IL2NESWriter.ArrayHandling.cs:line 530
   at IL2NESWriter.HandleLdelemU1() in IL2NESWriter.ArrayHandling.cs:line 368

Expected behavior

The transpiler should handle ldelem.u1 when the array reference comes from patterns other than a simple ldloc, such as when the compiler reuses a register or optimizes array access in inlined code.

Context

  • Blocking: crypto sample (PR Port 8bitworkshop crypto.c dungeon crawler sample #211)
  • This error surfaced after inlining all local functions to eliminate closure captures
  • The inlined code produces IL patterns where array references may not follow the expected ldloc+ldloc+ldelem sequence
    </issue_description>

Comments on the Issue (you are @copilot in this section)


📍 Connect Copilot coding agent with Jira, Azure Boards or Linear to delegate work to Copilot in one click without leaving your project management tool.

When byte[] arrays are stored as static fields (e.g., in static class G),
the IL uses ldsfld instead of ldloc to load the array reference before
ldelem.u1. The transpiler only checked GetLdlocIndex(), missing these.

Changes:
- Transpiler: scan .cctor for newarr->stsfld to determine array sizes
- Transpiler: detect ELEMENT_TYPE_SZARRAY (0x1D) in field signatures
- PreAllocateStaticFields: allocate proper byte counts for array fields
- IL2NESWriter: add TryResolveArrayLocal() helper for ldsfld arrays
- HandleLdelemU1: resolve arrays from both ldloc and ldsfld sources
- HandleLdelemU1ComplexIndex: same ldsfld fallback
- HandleLdelemU1: resolve indices from ldsfld (static field scalars)
- ILDispatch: handle newarr->stsfld to track runtime array allocations

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jonathanpeppers jonathanpeppers marked this pull request as ready for review March 18, 2026 01:05
Copilot AI review requested due to automatic review settings March 18, 2026 01:05
@jonathanpeppers
Copy link
Copy Markdown
Owner

🤖 Took over from CCA. CI is green, all 527 tests pass.

What this fixes

When byte[] arrays are stored as static fields in static class G, the IL uses ldsfld to load the array reference before ldelem.u1. The transpiler only checked GetLdlocIndex(), missing static field arrays entirely.

Changes

Transpiler (allocation):

  • Scan .cctor (static constructor) for newarr → stsfld patterns to determine array sizes
  • Detect ELEMENT_TYPE_SZARRAY (0x1D) in field signatures to identify array fields
  • PreAllocateStaticFields now allocates proper byte counts for array fields and returns array metadata

IL2NESWriter (code generation):

  • TryResolveArrayLocal() helper resolves arrays from both ldloc and ldsfld sources
  • HandleLdelemU1: falls back to static field array lookup when GetLdlocIndex returns null
  • HandleLdelemU1ComplexIndex: same ldsfld fallback
  • HandleLdelemU1: resolves indices from ldsfld (static field scalars like G.i)
  • ILDispatch: handles newarr → stsfld to track runtime array allocations

Verified with crypto sample

The crypto sample (PR #211) now progresses past this error. The next blocker is ldelema for byte arrays (a separate issue).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@jonathanpeppers jonathanpeppers changed the title [WIP] Transpiler: HandleLdelemU1 requires array in tracked local variable Support static field byte[] arrays in ldelem.u1 Mar 18, 2026
Take main's Transpiler.cs as base (methods moved to StructAnalysis.cs
and LocalFrameAllocation.cs), re-apply only the static array field
changes: destructuring tuple and StaticArrayFields property pass-through.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jonathanpeppers jonathanpeppers force-pushed the copilot/fix-840039-430943403-fb21c864-21ec-4924-9b3b-06202277715e branch from a6b1f71 to eb26291 Compare March 18, 2026 02:18
Three Roslyn tests with proper 6502 instruction assertions:
- StaticFieldArraySimpleIndex: verifies LDA \ (load G.i),
  TAX, LDA \,X (indexed array load from static field)
- StaticFieldArrayConstantIndex: verifies LDA \ (direct
  absolute load at arr base for constant index 0)
- StaticFieldArrayStelem: verifies LDA #42 + STA \,X
  (indexed array store to static field)

Also fixes:
- HandleStelemI1: add ldsfld support for target array and index
  (same TryResolveArrayLocal fallback as HandleLdelemU1)
- ILDispatch newarr→stsfld: add comment clarifying it handles
  Main() allocations (not dead code — .cctor path is separate)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jonathanpeppers jonathanpeppers force-pushed the copilot/fix-840039-430943403-fb21c864-21ec-4924-9b3b-06202277715e branch from eb26291 to 954e2d5 Compare March 18, 2026 02:29
@jonathanpeppers jonathanpeppers merged commit 7928ff5 into main Mar 18, 2026
1 check passed
@jonathanpeppers jonathanpeppers deleted the copilot/fix-840039-430943403-fb21c864-21ec-4924-9b3b-06202277715e branch March 18, 2026 03:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Transpiler: HandleLdelemU1 requires array in tracked local variable

3 participants