Files
ww/test/wcc/719_signed_data_emit.c
Hojun-Cho 74cc35d488 test: migrate Fam4 static-init/DATA-emit value tests to @test (#30)
Continues the test-arch tower past Fam8-13. 11 module-level static-init
/ DATA-emit value drivers move from test/wcc/*_run.c into @test row-
tables under test/lang/; every classification empirically re-probed at
HEAD (refuting two stale worklist tags).

- value rows -> test/lang/*_test.ww (11 files)
- reject rows -> runww //ww:error carriers (3, dual-stage non-vacuous;
  947 const-divzero confirmed a both-stage compile-reject, not run-exit)
- 840_zeroinit, 944_array_zeroinit, 989_arrlit_tail_zero kept as byte-id
  .c pins (zero-over-dirtied-frame / DATAW-length is byte-id-blind to a
  runtime @test; #263), mutation-gated
- repoint two stale comment refs to deleted test names (719,
  989_structlocal_frame)

Migrated static-init @test ride the cs==ww T2 byte-id gate, preserving
DATA-emit byte-id. 2D global-struct array-field read (#137/#150)
confirmed cs==ww + correct at HEAD. Coverage parity verified row-by-row;
two-round reviewed. Floor ratchet follows.
2026-06-25 01:32:32 +09:00

223 lines
6.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 719_signed_data_emit — corpus-coverage-blind sentinel for #19.
*
* Confirms each cstage / wwstage `.s` for a top-level `let` of signed
* integer type contains a `DATAW <sym>(SB),"..."` row, *and* that the
* inline literal bytes encode the value's two's complement at the
* declared element width. Pre-fix:
* - cstage emit_lets dropped the row entirely on `let x: i8 = -1i8;`
* (link failed, no DATAW); the array arm dropped the whole row.
* - wwstage emitletdataw silently emitted zero bytes where the
* negative literal should have produced 0xFF... (link succeeded;
* runtime read 0). The array arm hit the same gap.
*
* Both test/lang/signed_data_emit_test.ww (the migrated runtime rows)
* and the broader bootstrap byte-id (995_self_rebuild) would catch a
* future regression, but this row
* pins the *asm shape* itself — a future cgen refactor that emits
* the slot via a different directive (e.g. via DATA + DATAR rather
* than DATAW) would silently divergent even with green semantics.
*
* Plus a cstage-vs-wwstage byte-id diff per row, mirroring 707's
* pattern.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
static int
runwait(const char *cmd)
{
int rc = system(cmd);
if (rc == -1) return -1;
if (WIFEXITED(rc)) return WEXITSTATUS(rc);
return -1;
}
struct row {
const char *label;
const char *src;
const char *sym;
const char *want_bytes; /* exact byte-payload inside the DATAW */
};
/* The .s emits each byte either as a printable ASCII glyph (b is 0x20-
* 0x7e and not '"'/'\\') or as `\xNN`. emit_data_byte's rules: 0x22 + 0x5c
* → `\"` / `\\`; printable → raw; everything else → `\xNN`. For the
* sign-extended pads we'll see `\xff` × N as a contiguous run. */
static const struct row rows[] = {
/* Scalar i8 = -1 → low byte 0xff, then 7 bytes of sign-extension. */
{ "i8_neg", "let x: i8 = -1i8;\n"
"fn main() i32 = { return 0; };\n",
"x",
"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff" },
/* Scalar i16 = -2 → 0xfe 0xff then 6 byte sign extension. */
{ "i16_neg", "let x: i16 = -2i16;\n"
"fn main() i32 = { return 0; };\n",
"x",
"\\xfe\\xff\\xff\\xff\\xff\\xff\\xff\\xff" },
/* Scalar i32 = -100 → 0x9C 0xFF 0xFF 0xFF then 4 byte sign extension. */
{ "i32_neg", "let x: i32 = -100i32;\n"
"fn main() i32 = { return 0; };\n",
"x",
"\\x9c\\xff\\xff\\xff\\xff\\xff\\xff\\xff" },
/* Scalar i64 = -1000 → 0xfffffffffffffc18 little-endian. */
{ "i64_neg", "let x: i64 = -1000i64;\n"
"fn main() i32 = { return 0; };\n",
"x",
"\\x18\\xfc\\xff\\xff\\xff\\xff\\xff\\xff" },
/* Array [4]i8 = [1, -2, 3, -4] → 0x01 0xfe 0x03 0xfc. */
{ "i8_arr", "let a: [4]i8 = [1i8, -2i8, 3i8, -4i8];\n"
"fn main() i32 = { return 0; };\n",
"a",
"\\x01\\xfe\\x03\\xfc" },
/* Array [4]i16 = [1, -2, 3, -4] → LE16 each. */
{ "i16_arr", "let a: [4]i16 = [1i16, -2i16, 3i16, -4i16];\n"
"fn main() i32 = { return 0; };\n",
"a",
"\\x01\\x00\\xfe\\xff\\x03\\x00\\xfc\\xff" },
/* Array [3]i32 = [10, -20, 30] → LE32 each. */
{ "i32_arr", "let a: [3]i32 = [10i32, -20i32, 30i32];\n"
"fn main() i32 = { return 0; };\n",
"a",
"\\x0a\\x00\\x00\\x00\\xec\\xff\\xff\\xff\\x1e\\x00\\x00\\x00" },
/* Array [2]i64 = [100, -200] → LE64 each. Note 100 == 'd' and
* 56 == '8' are printable ASCII so emit_data_byte writes them
* raw rather than as `\xNN`. */
{ "i64_arr", "let a: [2]i64 = [100i64, -200i64];\n"
"fn main() i32 = { return 0; };\n",
"a",
"d\\x00\\x00\\x00\\x00\\x00\\x00\\x00"
"8\\xff\\xff\\xff\\xff\\xff\\xff\\xff" },
};
static int
slurp(const char *path, char *buf, size_t cap)
{
FILE *f = fopen(path, "rb");
if (!f) return -1;
size_t n = fread(buf, 1, cap - 1, f);
fclose(f);
buf[n] = '\0';
return (int)n;
}
/* Check that the .s contains a DATAW row for `sym` whose payload
* matches `want_bytes`. Returns 0 on match. */
static int
check_dataw(const char *spath, const struct row *r)
{
char buf[1 << 16];
if (slurp(spath, buf, sizeof buf) < 0) return -1;
char needle[256];
snprintf(needle, sizeof needle, "DATAW %s(SB),\"%s\"",
r->sym, r->want_bytes);
return strstr(buf, needle) ? 0 : -1;
}
static int
emit_s(const char *w6c, const struct row *r, int i, char *out_s, size_t cap)
{
char src[64], cmd[1024];
snprintf(src, sizeof src, "/tmp/sde_asm_%d_%d.ww", getpid(), i);
snprintf(out_s, cap, "/tmp/sde_asm_%d_%d_%s.s",
getpid(), i, w6c[strlen(w6c) - 1] == 'w' ? "ww" : "c");
FILE *f = fopen(src, "wb");
if (!f) return -1;
fputs(r->src, f);
fclose(f);
snprintf(cmd, sizeof cmd, "%s -o %s %s 2>/dev/null", w6c, out_s, src);
int rc = runwait(cmd);
unlink(src);
return rc;
}
int
main(void)
{
const char *bin = getenv("BIN");
if (!bin) bin = "out/bin";
char absbin[512];
if (bin[0] != '/') {
char cwd[256];
if (getcwd(cwd, sizeof cwd) == NULL) return 1;
snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin);
bin = absbin;
}
char w6c[640], w6c_ww[640];
snprintf(w6c, sizeof w6c, "%s/w6c", bin);
snprintf(w6c_ww, sizeof w6c_ww, "%s/w6c_ww", bin);
int have_ww = (access(w6c_ww, X_OK) == 0);
int n = (int)(sizeof rows / sizeof rows[0]);
int total = 0, fail = 0;
for (int i = 0; i < n; i++) {
char cs_path[128], ws_path[128];
/* cstage row: DATAW emit + byte payload. */
if (emit_s(w6c, &rows[i], i, cs_path, sizeof cs_path) != 0) {
fprintf(stderr,
"signed_data_emit[cstage][%s]: w6c failed\n",
rows[i].label);
fail++; total++; continue;
}
total++;
if (check_dataw(cs_path, &rows[i]) != 0) {
fprintf(stderr,
"signed_data_emit[cstage][%s]: DATAW %s(SB),\"%s\" missing\n",
rows[i].label, rows[i].sym, rows[i].want_bytes);
fail++;
}
if (!have_ww) { unlink(cs_path); continue; }
/* wwstage row: same DATAW emit. */
if (emit_s(w6c_ww, &rows[i], i, ws_path, sizeof ws_path) != 0) {
fprintf(stderr,
"signed_data_emit[wwstage][%s]: w6c_ww failed\n",
rows[i].label);
fail++; total++;
unlink(cs_path);
continue;
}
total++;
if (check_dataw(ws_path, &rows[i]) != 0) {
fprintf(stderr,
"signed_data_emit[wwstage][%s]: DATAW %s(SB),\"%s\" missing\n",
rows[i].label, rows[i].sym, rows[i].want_bytes);
fail++;
}
/* Byte-id diff between stages. The bootstrap byte-id covers
* cross-stage drift globally; per-row diff here surfaces a
* focused regression in the emit_lets / emitletdataw arms. */
total++;
char cmd[512];
snprintf(cmd, sizeof cmd, "cmp -s %s %s", cs_path, ws_path);
if (runwait(cmd) != 0) {
fprintf(stderr,
"signed_data_emit[%s]: cstage vs wwstage asm differs\n",
rows[i].label);
fail++;
}
unlink(cs_path); unlink(ws_path);
}
if (fail) {
fprintf(stderr,
"signed_data_emit: %d/%d fixtures failed\n", fail, total);
return 1;
}
printf("signed_data_emit: %d/%d ok\n", total, total);
return 0;
}