fix(asm): brace-comment strip must skip quoted strings

The asm brace-comment strip (added with the threads leaf to remove {...}
comments the lexer leaves inside asm blocks) ran over the WHOLE line, including
inside .ascii string literals.  The native backend emits string-const data as
.ascii directives, and the compiler's own codegen contains template strings with
literal braces (e.g. codegen.qbe.pas's 'data $__s%d = { w -1, w %d, w %d, b
"%s", b 0 }').  When the compiler was assembled by the internal assembler, the
strip ate the '{ ... }' span out of those .ascii literals, corrupting the
template strings.

The damage only showed when the compiler ran --emit-ir / GenerateIR: the
corrupted template produced garbage data lines (data $__s0 = <garbage>), so the
~1240 IR-assertion tests failed (TestHelloWorld_HasStrLitData etc.).  Compiled
user programs were unaffected (their own Format/strings come from freshly built
RTL), and the QBE-built compiler was unaffected (gcc assembles its .ascii), which
is why local QBE fixpoints stayed green while the CI native-internal TestRunner
went red.

Fix: skip over quoted strings in the brace strip, exactly as the adjacent
'#'-comment strip already does, so a brace inside a .ascii literal is left
intact.

Root-caused from the CI failure on ci/linux-direct-syscalls; the corruption is
visible as -clean but -garbled string data from a
native-internal-assembled compiler.
This commit is contained in:
Graeme Geldenhuys 2026-06-26 18:30:53 +01:00
parent e218b6978c
commit a20a82c417

View file

@ -670,11 +670,30 @@ begin
{ Strip a brace comment (open/close = ASCII 123/125) that survived the lexer:
a whole-line or trailing comment inside an asm block. Single line only;
remove the span from the open brace to the matching close brace, or to end
of line when unterminated. }
of line when unterminated. Skip over quoted strings so that a brace INSIDE
a .ascii string literal (the string-const data the native backend emits) is
left intact rather than mistaken for a comment. }
P := 0;
while P < Length(S) do
begin
if S[P] = 123 then
if S[P] = Ord('"') then
begin
{ Skip the whole quoted string, honouring \" escapes. }
P := P + 1;
while P < Length(S) do
begin
if S[P] = Ord('\') then
P := P + 2
else if S[P] = Ord('"') then
begin
P := P + 1;
Break;
end
else
P := P + 1;
end;
end
else if S[P] = 123 then
begin
Q := P + 1;
while (Q < Length(S)) and (S[Q] <> 125) do