Skip to content

arrayLength() destroys per-dimension shape, which blocks multi-dimensional array recovery downstream #8

Description

@macabeus

packages/debug-info/src/types.ts arrayLength() returns the product of a type's DW_TAG_subrange_type dimensions, so u16 g[4][0x400] reaches a consumer as a flat count of 4096 with the dimensions gone.

That is fine for sizing, but it is lossy in a way consumers cannot recover, and it is currently the top blocker for asmlift's biggest matching gap.

Where it bites

In a real decomp. On Klonoa: Empire of Dreams, LoadBGTileData matches only when the ROM table is declared const u8 gBgLayerLookup[][2][2] — the [2][2] shape is what makes agbcc fold a +1 into the symbol (adds r0, r4, #1) instead of emitting ldrb r0, [r0, #1]. With the dimensions flattened, asmlift emits gBgLayerLookup[0][0][(a1<<1)+(a0<<2)] or abandons the array entirely for *(u8 *)(… + ((u32)&g + 1)). That output scores 24; the correctly-shaped declaration scores 0.

In asmlift's benchmark, it is the sole cause of both of its noncompile rows (kleod:CopyBGScrollTiles, kleod:UpdateHUDCounterDisplay). The project header declares extern u16 gBgTilemapBufs[4][0x400];, the map carries {"shape": "array", "elemSize": 2, "size": 8192}, so a single subscript is emitted and agbcc rejects it:

in.i:1081: incompatible types in assignment      # gBgTilemapBufs[594] = gBgTilemapBufs[659];

u16[1024] assigned to u16[1024] is not an lvalue assignment. Note this only shows up in the headers world — a self-declared extern u16 g[]; is 1-D and consistent with 1-D indexing, which is exactly why it went unnoticed.

What would fix it

Report the dimensions alongside the flat length — e.g. dims: number[] — in variableShape and in struct members, keeping arrayLength() as-is for callers that only want the total. Everything downstream then has what it needs to declare u16 g[4][0x400] and emit multi-subscript indexing.

Related: #memberLayout already returns {offset, size, bitOffset, bitWidth} with both DWARF 2/3 bit-numbering conventions normalised, so the precedent for reporting structural facts rather than a collapsed scalar is already there.

Found while dogfooding gba-kit, asmlift and Transmuter together on a decomp round.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions