==> tests/backend.c <==1/* backend.rs's free functions: labels, pick_exec, check_manifest, prepare_any, cleanup order. */
2#include "mesh/backend.h"
3#include "mesh/check.h"
4
5#include <stdlib.h>
6#include <string.h>
7
8static mesh_manifest parse(const char *t) {
9 mesh_manifest m;
10 char *err = NULL;
11 if (!mesh_manifest_parse(t, strlen(t), &m, &err)) {
12 fprintf(stderr, "%s\n", err);
13 exit(1);
14 }
15 return m;
16}
17
18static int prepared_by;
19static bool fake_needs_ptx(const mesh_compiler *c) { return *(const int *)c->self == 0; }
20static bool fake_prepare(const mesh_compiler *c, mesh_payload *src, const uint64_t *expect, const char *root, mesh_prepared *out,
21 char **err) {
22 (void)expect, (void)root, (void)err;
23 prepared_by = *(const int *)c->self;
24 *out = (mesh_prepared){0};
25 out->src = *src;
26 *src = (mesh_payload){0};
27 out->exec = (uint32_t)prepared_by;
28 char *e = NULL;
29 return mesh_manifest_parse(out->src.manifest, strlen(out->src.manifest), &out->manifest, &e);
30}
31static const mesh_compiler_ops fake_ops = {fake_needs_ptx, fake_prepare};
32
33static char order[8];
34static void c_native(void) { strcat(order, "n"); }
35static void c_mps(void) { strcat(order, "m"); }
36
37int main(void) {
38 char *l;
39 CHECK_S(l = mesh_backend_label(mesh_backend_word(MESH_BACKEND_CUDA, 0)), "cuda");
40 free(l);
41 CHECK_S(l = mesh_backend_label(mesh_backend_word(MESH_BACKEND_METAL, 9)), "metal-apple9");
42 free(l);
43 CHECK_S(l = mesh_backend_label(mesh_backend_word(MESH_BACKEND_METAL, 0)), "metal");
44 free(l);
45 CHECK_S(l = mesh_backend_label(mesh_backend_word(MESH_BACKEND_WASM, 0)), "wasm");
46 free(l);
47 CHECK_S(l = mesh_backend_label(7), "backend7");
48 free(l);
49
50 /* pick_exec: the manifest's first backend this meshd runs. */
51 mesh_manifest m = parse("name = \"p\"\nabi = 6\nbackends = [\"wasm\", \"cuda\"]");
52 uint32_t have[] = {MESH_BACKEND_CUDA, MESH_BACKEND_WASM, MESH_BACKEND_NATIVE}, exec = 99;
53 CHECK(mesh_pick_exec(&m, have, 3, &exec, NULL) && exec == MESH_BACKEND_WASM);
54 char *err = NULL;
55 CHECK(!mesh_pick_exec(&m, (uint32_t[]){MESH_BACKEND_NATIVE}, 1, &exec, &err));
56 CHECK_S(err, "unsupported: p runs on wasm, cuda (manifest `backends`); this meshd runs native");
57 free(err);
58 err = NULL;
59 mesh_manifest_free(&m);
60
61 /* check_manifest: abi, backends, sms. */
62 mesh_payload src = {"p", "name = \"p\"\nabi = 5", NULL, 0};
63 CHECK(!mesh_check_manifest(&src, MESH_BACKEND_CUDA, &m, &err));
64 CHECK_S(err, "abi: p declares abi 5, meshd runs 6");
65 src.manifest = "name = \"p\"\nabi = 6\nbackends = [\"wasm\"]";
66 CHECK(!mesh_check_manifest(&src, MESH_BACKEND_CUDA, &m, &err));
67 CHECK_S(err, "unsupported: p runs on wasm (manifest `backends`); this meshd runs cuda");
68 src.manifest = "name = \"p\"\nabi = 6\nsms = 2";
69 CHECK(!mesh_check_manifest(&src, MESH_BACKEND_CUDA, &m, &err));
70 CHECK_S(err, "manifest: p: sms = 2: per-program green partitions are not implemented");
71 src.manifest = "name = \"p\"\nabi = 6\nbogus = 1";
72 CHECK(!mesh_check_manifest(&src, MESH_BACKEND_CUDA, &m, &err));
73 CHECK_S(err, "manifest: p: line 3: unknown key \"bogus\"");
74 src.manifest = "name = \"p\"\nabi = 6";
75 CHECK(mesh_check_manifest(&src, MESH_BACKEND_CUDA, &m, &err));
76 mesh_manifest_free(&m);
77 free(err);
78 err = NULL;
79
80 /* prepare_any: the executor's compiler; a PTX compiler refuses a catalog without PTX. */
81 int k_cuda = 0, k_wasm = 2;
82 mesh_compiler cuda = {&fake_ops, &k_cuda}, wasm = {&fake_ops, &k_wasm};
83 mesh_compiler_entry comps[] = {{MESH_BACKEND_CUDA, &cuda}, {MESH_BACKEND_WASM, &wasm}};
84 mesh_payload p = {mesh_strdup("w"), mesh_strdup("name = \"w\"\nabi = 6\nbackends = [\"wasm\"]"), NULL, 0};
85 mesh_prepared pr;
86 CHECK(mesh_prepare_any(comps, 2, &p, NULL, "/x", &pr, &err));
87 CHECK_I(prepared_by, 2);
88 CHECK_S(mesh_prepared_dir(&pr), "w");
89 mesh_prepared_free(&pr);
90 p = (mesh_payload){mesh_strdup("c"), mesh_strdup("name = \"c\"\nabi = 6"), NULL, 0};
91 CHECK(!mesh_prepare_any(comps, 2, &p, NULL, "/x", &pr, &err));
92 CHECK_S(err, "manifest: c/c.ptx (c): no PTX in the catalog (the cuda image)");
93 free(err);
94
95 /* Cleanups: native before MPS, whatever the registration order; once each. */
96 mesh_backend_on_cleanup(MESH_CLEANUP_MPS, c_mps);
97 mesh_backend_on_cleanup(MESH_CLEANUP_NATIVE, c_native);
98 mesh_backend_on_cleanup(MESH_CLEANUP_NATIVE, c_native);
99 mesh_backend_cleanup();
100 CHECK_S(order, "nm");
101
102 char *bin = mesh_native_binary("/progs/g", "g");
103 char *want = mesh_fmt("/progs/g/%s/g", mesh_native_target());
104 CHECK_S(bin, want);
105 free(bin);
106 free(want);
107 return mesh_check_done();
108}