skip to content
==> include/wasm/builder.h <==
1/* @ajax/wasm-builder: WebAssembly binaries assembled from C, for tests and tools.
2 *
3 * A wasm_buf is a growable byte buffer with the binary format's encoders (LEB128, names, floats).
4 * A wasm_builder collects a module's parts and wasm_builder_finish writes them as sections in the
5 * spec's order. Bodies are raw instruction bytes the caller writes into a wasm_buf (the final `end`
6 * is added). Indices are the caller's to get right: this builds invalid modules on request, which
7 * is what tests of a validator need. Allocation failure aborts. */
8#ifndef WASM_BUILDER_H
9#define WASM_BUILDER_H
10
11#include "wasm/types.h"
12
13#include <stdbool.h>
14#include <stddef.h>
15#include <stdint.h>
16
17typedef struct {
18    uint8_t *data;
19    size_t len, cap;
20} wasm_buf;
21
22void wasm_buf_free(wasm_buf *b);
23void wb_byte(wasm_buf *b, uint8_t v);
24void wb_bytes(wasm_buf *b, const void *p, size_t n);
25void wb_u32(wasm_buf *b, uint32_t v); /* unsigned LEB128 */
26void wb_u64(wasm_buf *b, uint64_t v);
27void wb_s32(wasm_buf *b, int32_t v); /* signed LEB128 */
28void wb_s64(wasm_buf *b, int64_t v);
29void wb_f32(wasm_buf *b, float v);
30void wb_f64(wasm_buf *b, double v);
31void wb_name(wasm_buf *b, const char *s);
32/* A section: id, the payload's size, the payload. */
33void wb_section(wasm_buf *b, uint8_t id, const wasm_buf *payload);
34
35/* Instruction shorthands. */
36void wb_i32_const(wasm_buf *b, int32_t v);
37void wb_i64_const(wasm_buf *b, int64_t v);
38void wb_op(wasm_buf *b, uint8_t op);                 /* a plain opcode */
39void wb_op_u32(wasm_buf *b, uint8_t op, uint32_t a); /* an opcode with one u32 (local.get 3, call 1, br 0) */
40void wb_fc(wasm_buf *b, uint32_t sub);               /* 0xfc sub */
41void wb_memarg(wasm_buf *b, uint8_t op, uint32_t align, uint32_t offset);
42
43typedef struct {
44    char *module, *name;
45    uint8_t kind;
46    uint32_t type;           /* functions */
47    wasm_valtype vtype;      /* globals; tables: element type */
48    bool mut;                /* globals */
49    uint32_t min, max;       /* memories, tables */
50    bool has_max;
51} wasm_builder_import;
52
53typedef struct {
54    uint32_t type;
55    wasm_valtype *locals; /* one entry per local (run-length encoded on output) */
56    uint32_t nlocals;
57    wasm_buf body; /* instructions without the final end */
58} wasm_builder_func;
59
60typedef struct {
61    wasm_valtype type;
62    bool mut;
63    wasm_buf init; /* instructions without the final end */
64} wasm_builder_global;
65
66typedef struct {
67    char *name;
68    uint8_t kind;
69    uint32_t index;
70} wasm_builder_export;
71
72typedef struct {
73    bool passive;
74    uint32_t offset; /* active: i32.const offset in memory 0 / table 0 */
75    wasm_buf bytes;  /* data: the bytes */
76    uint32_t *funcs; /* elements: function indices */
77    uint32_t nfuncs;
78} wasm_builder_segment;
79
80typedef struct {
81    wasm_buf types; /* the type section payload's entries, counted in ntypes */
82    uint32_t ntypes;
83    wasm_builder_import *imports;
84    uint32_t nimports, nfunc_imports;
85    wasm_builder_func *funcs;
86    uint32_t nfuncs;
87    bool has_memory;
88    uint32_t mem_min, mem_max;
89    bool mem_has_max;
90    bool has_table;
91    uint32_t table_min, table_max;
92    bool table_has_max;
93    wasm_builder_global *globals;
94    uint32_t nglobals;
95    wasm_builder_export *exports;
96    uint32_t nexports;
97    bool has_start;
98    uint32_t start;
99    wasm_builder_segment *elems;
100    uint32_t nelems;
101    wasm_builder_segment *datas;
102    uint32_t ndatas;
103    bool datacount;
104} wasm_builder;
105
106void wasm_builder_free(wasm_builder *w);
107/* A function type ("ii>i" over i l f d, F funcref, E externref, V v128); its index. */
108uint32_t wasm_builder_type(wasm_builder *w, const char *sig);
109uint32_t wasm_builder_import_func(wasm_builder *w, const char *module, const char *name, uint32_t type);
110void wasm_builder_import_memory(wasm_builder *w, const char *module, const char *name, uint32_t min);
111/* A defined function of `type` with locals (a string as in sig, e.g. "iif"); returns its body
112 * buffer to write instructions into. Its index is nfunc_imports + its position. */
113wasm_buf *wasm_builder_func_add(wasm_builder *w, uint32_t type, const char *locals, uint32_t *index);
114void wasm_builder_memory(wasm_builder *w, uint32_t min, uint32_t max, bool has_max);
115void wasm_builder_table(wasm_builder *w, uint32_t min, uint32_t max, bool has_max);
116/* A global; returns its init buffer (write a constant instruction into it). */
117wasm_buf *wasm_builder_add_global(wasm_builder *w, wasm_valtype type, bool mut);
118void wasm_builder_add_export(wasm_builder *w, const char *name, uint8_t kind, uint32_t index);
119void wasm_builder_data(wasm_builder *w, uint32_t offset, const void *bytes, size_t n);
120void wasm_builder_data_passive(wasm_builder *w, const void *bytes, size_t n);
121void wasm_builder_elem(wasm_builder *w, uint32_t offset, const uint32_t *funcs, uint32_t n);
122/* The binary. */
123void wasm_builder_finish(const wasm_builder *w, wasm_buf *out);
124
125#endif