aboutsummaryrefslogtreecommitdiff
path: root/src/routines/section/table.c
blob: 3dec8360d855966a0bfd596b91f45fa19c84d71a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
 * nanowasm, a tiny WebAssembly/Wasm interpreter
 * Copyright (C) 2023-2024  Xavier Del Campo Romero
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

#include <nanowasm/nw.h>
#include <nw/io.h>
#include <nw/log.h>
#include <nw/routines.h>

static enum nw_state get_maximum(struct nw_mod *const m)
{
    nw_varuint32 maximum;
    const struct nw_io_cfg *const cfg = &m->cfg.io;
    struct nw_sm_tb *const tb = &m->sm.table;
    struct nw_sm_leb128 *const l = &tb->leb128;
    const enum nw_state n = nwp_varuint32(cfg, l, &maximum);

    if (n)
        return n;

    m->next = nwp_section_exit;
    return NW_AGAIN;
}

static enum nw_state get_initial(struct nw_mod *const m)
{
    const struct nw_io_cfg *const cfg = &m->cfg.io;
    struct nw_sm_tb *const tb = &m->sm.table;
    struct nw_sm_leb128 *const l = &tb->leb128;
    nw_varuint32 initial;
    const enum nw_state n = nwp_varuint32(cfg, l, &initial);

    if (n)
        return n;

    m->next = tb->flags ? get_maximum : nwp_section_exit;
    return NW_AGAIN;
}

static enum nw_state get_flags(struct nw_mod *const m)
{
    const struct nw_io_cfg *const cfg = &m->cfg.io;
    struct nw_sm_tb *const tb = &m->sm.table;
    struct nw_sm_leb128 *const l = &tb->leb128;
    const enum nw_state n = nwp_varuint1(cfg, l, &tb->flags);

    if (n)
        return n;

    m->next = get_initial;
    return NW_AGAIN;
}

static enum nw_state get_element_type(struct nw_mod *const m)
{
    const struct nw_io_cfg *const cfg = &m->cfg.io;
    struct nw_sm_tb *const tb = &m->sm.table;
    struct nw_sm_leb128 *const l = &tb->leb128;
    const enum nw_state n = nwp_varint7(cfg, l, &tb->elem_type);

    if (n)
        return n;
    /* TODO: replace with enum? */
    else if (tb->elem_type != 0x70)
    {
        LOG("%s: unexpected elem_type %hhx\n", __func__, (char)tb->elem_type);
        return NW_FATAL;
    }

    m->next = get_flags;
    return NW_AGAIN;
}

static enum nw_state entry_loop(struct nw_mod *const m)
{
    const struct nw_sm_tb *const tb = &m->sm.table;

    m->next = tb->entry_i < tb->count ? get_element_type : nwp_section_exit;
    return NW_AGAIN;
}

static enum nw_state get_count(struct nw_mod *const m)
{
    const struct nw_io_cfg *const cfg = &m->cfg.io;
    struct nw_sm_tb *const tb = &m->sm.table;
    struct nw_sm_leb128 *const l = &tb->leb128;
    const enum nw_state n = nwp_varuint32(cfg, l, &tb->count);

    if (n)
        return n;
    else if (tb->count > 1u)
    {
        LOG("%s: got %lu tables, but only 1 supported by the MVP\n", __func__,
            (unsigned long)tb->count);
        return NW_FATAL;
    }

    m->next = entry_loop;
    return NW_AGAIN;
}

void nwp_section_table(struct nw_mod *const m)
{
    m->next = get_count;
    m->sm.table = (const struct nw_sm_tb){0};
}