/* * Rows match assembly fragments, not full-file goldens: golden matches * would bind the test to unrelated output details. */ #include "gc.h" #include #include #include #include "wwtestpkg.h" static char * codegen(const char *src) { Arena *a = newarena(); char *wrapped = wwtest_wrap(src); Lex l; Parser p; Checker c; Cg cg; lexinit(&l, a, "", wrapped, strlen(wrapped)); parserinit(&p, a, &l); Node *file = parsefile(&p); if (l.errs || p.errs) goto fail; check_init(&c, a); check_file(&c, file); if (c.errs) goto fail; char *out = NULL; size_t outlen = 0; FILE *f = open_memstream(&out, &outlen); if (f == NULL) goto fail; cg_init(&cg, a); cg_file(&cg, f, file); if (fclose(f) != 0) { free(out); out = NULL; } free(wrapped); freearena(a); return out; fail: free(wrapped); freearena(a); return NULL; } struct row { const char *src; const char *needle[3]; }; static const struct row rows[] = { { "fn main() i32 = { return 42; };", { "MOVQ\t$42, AX", "RET" } }, { "fn id(x: i32) i32 = { return x; };", { "MOVQ\tDI, -8(BP)" } }, { "fn add(a: i32, b: i32) i32 = { return a + b; };", { "ADDQ\tBX, AX" } }, { "fn sub(a: i32, b: i32) i32 = { return a - b; };", { "SUBQ\tBX, AX" } }, { "fn mul(a: i32, b: i32) i32 = { return a * b; };", { "IMULQ\tBX, AX" } }, { "fn neg(x: i32) i32 = { return -x; };", { "NEGQ\tAX" } }, { "fn cmp(a: i32, b: i32) bool = { return a == b; };", { "CMPQ\tBX, AX", "JE" } }, { "fn cond(x: i32) i32 = { if (x > 0) { return 1; }; return 0; };", { "CMPQ\t$0, AX" } }, { "fn lo() void = { for (let i: i32 = 0; i < 10; i += 1) { }; };", { "JMP" } }, { "fn callit() i32 = { return 1; };", { "TEXT main.callit,$0" } }, }; int main(void) { int n = sizeof rows / sizeof rows[0]; int nfrag = 0; int fail = 0; for (int i = 0; i < n; i++) { int want = 0; while (want < 3 && rows[i].needle[want] != NULL) want++; nfrag += want; char *out = codegen(rows[i].src); if (out == NULL) { fprintf(stderr, "row %d: frontend/codegen failed\n", i); fail += want; continue; } for (int j = 0; j < want; j++) { if (strstr(out, rows[i].needle[j]) != NULL) continue; fprintf(stderr, "row %d: missing '%s' in:\n%s\n", i, rows[i].needle[j], out); fail++; } free(out); } if (fail) { fprintf(stderr, "%d/%d w6c fragments failed\n", fail, nfrag); return 1; } printf("w6c: %d/%d fragments ok in %d sources\n", nfrag, nfrag, n); return 0; }