← board

Whole dynamic-array variable assignment (b := a) unsupported on i386 + aarch64

Symptom

Assigning one dynamic-array variable to another (the whole-handle copy, not an element store) is broken on two cross targets:

var a, b: array of Integer;
begin
  SetLength(a, 3); a[0] := 5; a[1] := 6; a[2] := 7;
  b := a;            { i386: compile error; aarch64: SIGSEGV }
  Writeln(b[1]);     { x86-64: 6 / arm32: 6 }
end.

The IR is the same on every target: b := a lowers to store_sym b, lea(a) (the source handle), a pointer-width handle copy. i386 rejects the array sym in its scalar-store path; aarch64 mis-handles it at runtime.

Impact

Any value-style dynamic-array API whose result is assigned to a variable is limited to x86-64 + arm32. In particular the generic dynamic-array Copy(arr, index, count) intrinsic (feature-copy-intrinsic) produces a fresh array of T that the caller assigns — so b := Copy(a, i, n) inherits exactly this gap. The Copy lowering itself is target-independent; only the trailing whole-array assignment fails on i386/aarch64. The x86-64 self-host gate is unaffected.

test/test_dynarray_copy.pas therefore runs in test-core (x86-64) and the arm32 cross suite only; once this is fixed, add it to the i386 + aarch64 cross suites.

Direction

Give i386 (and aarch64) a real whole-dynamic-array assignment path: copy the pointer-sized handle into the destination slot (with the dyn-array refcount retain/release, like the managed-string publish), instead of routing it through the scalar-ordinal store that refuses array syms. On i386 the handle is a single 4-byte slot value, so it is a plain pointer store plus refcount bookkeeping.

Log

Resolution (2026-06-19) — FIXED

Both targets store the pointer-sized handle now:

b := a and b := Copy(...) now work on all four targets. test_dynarray_copy.pas re-added to the i386 + aarch64 cross suites (was x86-64 + arm32 only); all 3 cross suites output-identical to x86-64; self-host + cross-bootstrap byte-identical.