skip to content
==> tests/float_guard.c <==
1/* The Rust's `float_guard` test (mesh-host/src/wasm.rs), case for case. */
2#include "mesh/check.h"
3#include "wasm/builder.h"
4#include "wasm/float_guard.h"
5
6#include <string.h>
7
8/* A module of one function of type (f32, f32) -> f32 (or () -> () with simd), exported as export,
9 * whose body is body; optionally one function import first (the Rust test's `module`). */
10static wasm_buf module(const char *imod, const char *iname, const char *export, const uint8_t *body, size_t n, bool simd) {
11    wasm_builder w = {0};
12    uint32_t t = wasm_builder_type(&w, simd ? ">" : "ff>f");
13    if (imod) wasm_builder_import_func(&w, imod, iname, t);
14    uint32_t f;
15    wb_bytes(wasm_builder_func_add(&w, t, "", &f), body, n);
16    wasm_builder_add_export(&w, export, WASM_EXTERN_FUNC, f);
17    wasm_buf out;
18    wasm_builder_finish(&w, &out);
19    wasm_builder_free(&w);
20    return out;
21}
22
23static const uint8_t ADD[] = {0x20, 0, 0x20, 1, 0x92}; /* local.get 0, local.get 1, f32.add */
24static const uint8_t MOVE[] = {0x20, 0};               /* local.get 0 (no f32 op) */
25
26static bool prefix(const char *s, const char *p) { return strncmp(s, p, strlen(p)) == 0; }
27
28int main(void) {
29    char err[512];
30    wasm_float_report r;
31    /* f32.add in a non-helper: refused in an FTZ image, fine in an IEEE one. */
32    wasm_buf raw = module(NULL, NULL, "f", ADD, sizeof ADD, false);
33    CHECK(!wasm_float_check(raw.data, raw.len, true, &r, err, sizeof err));
34    CHECK(prefix(err, "float: F32Add in function 0"));
35    CHECK(wasm_float_check(raw.data, raw.len, false, &r, err, sizeof err));
36    CHECK_U(r.funcs, 1);
37    CHECK_U(r.helpers, 0);
38    CHECK_U(r.f32_ops, 1);
39    wasm_buf_free(&raw);
40    /* The same op inside an exported mesh_ftz_* helper: allowed. */
41    wasm_buf helper = module(NULL, NULL, "mesh_ftz_add", ADD, sizeof ADD, false);
42    CHECK(wasm_float_check(helper.data, helper.len, true, &r, err, sizeof err));
43    CHECK_U(r.funcs, 1);
44    CHECK_U(r.helpers, 1);
45    CHECK_U(r.f32_ops, 1);
46    wasm_buf_free(&helper);
47    /* Moves are not flushing ops. */
48    wasm_buf mv = module(NULL, NULL, "f", MOVE, sizeof MOVE, false);
49    CHECK(wasm_float_check(mv.data, mv.len, true, &r, err, sizeof err));
50    CHECK_U(r.f32_ops, 0);
51    wasm_buf_free(&mv);
52    /* Imports: only `mesh` functions (the helper index counts the import). */
53    wasm_buf env = module("env", "x", "mesh_ftz_add", ADD, sizeof ADD, false);
54    CHECK(!wasm_float_check(env.data, env.len, true, &r, err, sizeof err));
55    CHECK(prefix(err, "load: import env::x"));
56    wasm_buf_free(&env);
57    wasm_buf mesh = module("mesh", "info", "mesh_ftz_add", ADD, sizeof ADD, false);
58    CHECK(wasm_float_check(mesh.data, mesh.len, true, &r, err, sizeof err));
59    CHECK_U(r.helpers, 1);
60    wasm_buf_free(&mesh);
61    /* SIMD (v128.const; drop): refused in an FTZ image only. */
62    uint8_t simd[19] = {0xfd, 0x0c};
63    simd[18] = 0x1a;
64    wasm_buf v = module(NULL, NULL, "f", simd, sizeof simd, true);
65    CHECK(!wasm_float_check(v.data, v.len, true, &r, err, sizeof err));
66    CHECK(prefix(err, "float: "));
67    CHECK(wasm_float_check(v.data, v.len, false, &r, err, sizeof err));
68    wasm_buf_free(&v);
69    /* Not wasm at all: the compiler's refusal. */
70    CHECK(!wasm_float_check((const uint8_t *)"\0asm\x01\0\0\0\x01\x05", 10, true, &r, err, sizeof err));
71    CHECK(prefix(err, "jit: "));
72    /* Threads and relaxed SIMD are refused even in an IEEE image. */
73    static const uint8_t fence[] = {0xfe, 0x03, 0x00};
74    wasm_buf th = module(NULL, NULL, "f", fence, sizeof fence, true);
75    CHECK(!wasm_float_check(th.data, th.len, false, &r, err, sizeof err));
76    CHECK(prefix(err, "float: threads support is not enabled"));
77    wasm_buf_free(&th);
78    /* Every flushing op is one of the 22 the Rust lists. */
79    int n = 0;
80    for (uint32_t op = 0; op < 256; op++) n += wasm_flushing_f32(op);
81    CHECK_I(n, 22);
82    return mesh_check_done();
83}