← board

riscv32: storing a string LITERAL into a class field gives an empty string

Reproduction

type
  TA = class
    F: string;
    procedure SetLit;
  end;
procedure TA.SetLit;
begin
  F := 'lit';                  { -> '' on riscv32 }
end;
...
  a.F := 'direct';             { -> '' on riscv32 }

Measured 2026-07-13 (same program, all targets):

form x86-64 i386 aarch64 arm32 riscv32
F := 'lit' (literal, in a method) ok ok ok ok ''
a.F := 'direct' (literal, qualified) ok ok ok ok ''
F := 'cat:' + n (concatenation) ok ok ok ok ok
s := 'viavar'; a.F := s (via a variable) ok ok ok ok ok

So it is specifically a frozen string LITERAL stored straight into a class FIELD. Route the same literal through a local variable, or produce it with a concatenation (a managed result), and it stores fine. It is silent — no crash, no diagnostic, just an empty string — which is the worst shape for a bug and means anything riscv32 that initialises a field from a literal has been quietly wrong.

Where to look

The literal is a frozen string (inline storage, 8-byte length prefix, chars at +8) and the field is a managed slot; the store must materialise a handle. Compare the riscv32 emit for IR_STORE_MEM / the frozen-literal-to-managed-slot path against i386, which is the closest target (ILP32, and it works). The concatenation case working says the managed-handle store itself is fine — it is the FROZEN LITERAL source operand that is being dropped.

Gate

make test + self-host byte-identical + cross (riscv32 in particular).

Log