skip to content
==> 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}