aarch64: comparing two string-valued Variants is always FALSE
Found while regression-testing the promotable int's variant fallback path 2026-07-20. Pre-existing and promo-independent — the repro contains no promotable int and does not load its runtime.
Repro
program p;
var v, w: Variant;
begin
v := 'ab'; w := 'cd';
Writeln(v < w);
Writeln(v > w);
end.
| target | v < w |
v > w |
|---|---|---|
| x86-64 | TRUE | FALSE |
| aarch64 (qemu) | FALSE | FALSE |
Both orderings report FALSE, so the comparison is not merely inverted — the
string branch of the aarch64 variant compare never produces an ordering. =
and <> are worth checking in the same pass; only < and > were measured.
Why it matters
It is a silent wrong ANSWER, not a crash, in a construct that looks obviously correct. Any aarch64 code sorting or ordering variant-held strings is affected — which includes NilPy, where values commonly live in variants and string comparison is ordinary Python.
Where to look
The variant binop is hand-written per backend. On x86-64 the ordering path is in
EmitVarBinOp (ir_codegen.inc), which has an explicit string branch reached
via the VT_STRING/VT_CHAR tag tests. Compare that against the aarch64
equivalent and establish whether the string branch is missing, mis-encoded, or
falling through to the numeric path (which, comparing two heap POINTERS, would
give an arbitrary but consistent answer — matching "always FALSE" here).
Gate
The repro above matching x86-64 on aarch64, plus =/<>/<=/>= and a
char-vs-string mix; --tier quick + self-host byte-identical + cross. Check
arm32/riscv32 for the same shape.
Log
- 2026-07-22 — resolved, commit a5042090.