← board

Single field/element inside a record or array stores/loads as zero

Symptom

A Single record field or array element stores/loads as 0; a plain Single variable is fine.

type S2 = record a, b: Single end;
var sv: Single; s: S2; arr: array[0..2] of Single;
begin
  sv := 3.5;     writeln(sv:0:1);      { 3.5  — OK (plain Single var) }
  s.a := 4.5;    writeln(s.a:0:1);     { 0.0  — WRONG (Single record field) }
  arr[1] := 5.5; writeln(arr[1]:0:1);  { 0.0  — WRONG (Single array element) }
end.

So the per-variable Single narrow path (slot store/load, param prologue) is correct, but a Single at a 4-byte offset inside a record or array is not — the field/element store/load almost certainly uses the 8-byte double path (movsd/no cvtsd2ss) instead of the 4-byte movss with the proper single↔double narrowing, so the value is mis-sized.

Impact

Any record/array of Single (compact vectors/colors, vertex buffers). Double aggregates work; switching a field to Single silently zeroes it.

Likely area

The record-field / array-element store+load codegen for tySingle — mirror the per-variable Single handling (narrow to 4 bytes on store via cvtsd2ss + movss, widen on load via cvtss2sd) at the IR_FIELD/IR_INDEX access sites, on every target (the per-variable narrow is already target-split — see feature-single-first-class).

Done when

Resolution (2026-06-25, v66)

A Single field/element is a 4-byte float, but the IR value model carries floats as double bits, so the raw size-based field/element store/load mishandled them:

Verified Single + Double field/array, int and float values, and a Single-field record function result, identical on x86-64/i386/aarch64/arm32. Regression test/test_single_in_aggregate.pas in make test, test-aarch64, test-arm32. Self-host byte-identical; pinned v66.