fix(native): stage-stable char-literal byte RHS in string subscript write
EmitByteRhsToEax lowered a single-character string-literal RHS via Ord(TStringLiteral(AExpr).Value[0]). That subscript-then-Ord idiom is miscompiled by the self-hosted native stage: a native-built compiler baked a pointer-sized garbage immediate (movl $0xd291f9ec) instead of the byte, so S[i] := 'c' wrote junk. It only surfaced in CI, where the test runner is built by the native-bootstrapped -pre binary; local verification used the QBE-built fixpoint binary, which lowers the idiom correctly, so the bug was invisible. Use StrAt(Value, 0) — the OrdAt-backed byte-read helper already used elsewhere in this backend and stage-stable — instead of Ord(Value[0]). Matches the QBE backend, which uses StrAt and was never affected. Verified by building the test runner with a native-built compiler (the CI configuration): full suite passes; all three fixpoints clean.
This commit is contained in:
parent
07aac3322f
commit
e9f705fdc8
|
|
@ -3899,8 +3899,13 @@ begin
|
|||
if (AExpr is TStringLiteral) and
|
||||
(Length(TStringLiteral(AExpr).Value) = 1) then
|
||||
begin
|
||||
{ Use StrAt (OrdAt) rather than Ord(Value[0]): the bare subscript-then-Ord
|
||||
idiom miscompiles under the self-hosted native stage (it produced a
|
||||
pointer-sized garbage immediate, surfacing as a CI-only failure of the
|
||||
S[i] := 'c' test), whereas StrAt is the stage-stable byte-read helper
|
||||
used everywhere else in this backend. }
|
||||
Self.Emit(Format(#9'movl $%d, %%eax',
|
||||
[Ord(TStringLiteral(AExpr).Value[0])]));
|
||||
[StrAt(TStringLiteral(AExpr).Value, 0)]));
|
||||
Exit;
|
||||
end;
|
||||
Self.EmitExprToEax(AExpr);
|
||||
|
|
|
|||
Loading…
Reference in a new issue