w6c: emit DATAR for let s: str = "literal" initialisers

Use the new DATAR mechanism so str-literal init on a top-level
mutable `let` lands in .data and links cleanly.

emit_lets, when it sees `let s: str = "lit"` (non-empty strlit),
emits:

  DATAW s(SB),"<8 zero placeholder><8 LE bytes of len>"
  DATAR s+0(SB),<strlit_label>(SB)

The linker patches the placeholder with the strlit's runtime VA at
program load time, so `s.ptr` reads as the real pointer and `s.len`
as the literal length. A new let_pre_intern pass scans top-level
lets ahead of emit_data so the strlit gets a DATA row in the same
.s file; running emit_lets after emit_data instead would have
flipped the (DATA strlits, DATAW lets) section order in the .s and
broken byte-identity with the wwstage cgen.

The wwstage cgen still emits the zero-init shape for str lets,
which only matters if the wwstage is asked to compile source that
uses str-literal init. None of the selfhost combined sources do
that today, so test 994 / 990 stay green. The selfhost mirror for
DATAR + DATAW + this w6c branch is a follow-up.

630_let_global gains two fixtures: a length-readback and a first-
byte readback through the patched ptr.
This commit is contained in:
2026-05-12 12:49:01 +09:00
parent d998425391
commit 003f707618
2 changed files with 82 additions and 18 deletions

View File

@@ -113,6 +113,27 @@ static const struct fixture fixtures[] = {
"};\n",
7,
},
{
"str-literal-init",
/* `let s: str = "literal";` — the ptr half is patched at
* link time by an R_X86_64_64 reloc against the strlit's
* data label; .len comes baked into the DATAW payload. */
"let g: str = \"hello world\";\n"
"fn main() i32 = { return g.len: i32; };\n",
11,
},
{
"str-literal-via-fn",
/* Confirm the patched ptr really points at the right bytes
* by reading the first byte of g.ptr through a pointer
* cast. 'h' == 104. */
"let g: str = \"hello\";\n"
"fn main() i32 = {\n"
"\tlet p: *u8 = g.ptr;\n"
"\treturn p[0]: i32;\n"
"};\n",
104,
},
{
"slice-zeroinit",
/* Slice globals start as {nil, 0, 0}. .len and .cap both