← board

aarch64/arm32: record temporary as a by-value arg fails codegen

Symptom

Passing a function-result temporary as a by-value record argument:

type R = record a, b, c, d: Byte end;        { 4 bytes }
function Mk(v: Byte): R;
function Sum(x: R): Integer;

n := Sum(Mk(3));     { aarch64/arm32: target ...: load through pointer of
                       this type not yet supported }
target result
x86-64 OK
aarch64 error: load through pointer of this type not yet supported
arm32 error: load through pointer of this type not yet supported
i386 error: only ordinal/pointer parameters supported yet (broader — see note)

A named variable argument works on every target:

r := Mk(3); n := Sum(r);     { OK on aarch64/arm32 }

So the aarch64/arm32 backends materialize a by-value record param from a real lvalue fine, but cannot lower a temporary (the hidden-local copy + load path the x86-64 backend uses).

Impact

Idiomatic value-style record APIs — ImageSetPixel(img,x,y,MakeRGBA(...)), vector/colour algebra, small value structs — won't cross-compile to aarch64/arm32 when an argument is a call result rather than a named local. Worked around in examples/raytracer by materializing a named TRGBA c := MakeRGBA(...) before ImageSetPixel (idiomatic anyway), which restores the aarch64 build.

Note — i386 is broader

i386 reports only ordinal/pointer parameters supported yet for the same code: that backend does not take any by-value record param (named or temp), a wider gap than the temp-specific aarch64/arm32 one. Track i386 record-by-value params separately if not already covered by the i386 maturity work.

Done when

Resolution (2026-06-25, v65)

The aarch64 and arm32 backends rejected IR_LOAD_MEM of a tyRecord value ("load through pointer of this type not yet supported") — the path a small (<=8-byte) by-value record argument takes (ir.inc wraps a record call/binop result in IR_LOAD_MEM tyRecord, loading its packed bytes into a register, like x86-64).

Fix: allow tyRecord in both backends' IR_LOAD_MEM type allow-list.

Regression test/test_record_temp_byval_arg.pas (temp + named, prints 18,46) in make test, test-aarch64, test-arm32. Self-host byte-identical (x86-64 codegen untouched); pinned v65.

Residual (separate, pre-existing — not this temp bug)