/* * nanowasm, a tiny WebAssembly/Wasm interpreter * Copyright (C) 2023-2025 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 #include #include #include #include #include #include #include static enum nw_state get_target(struct nw_interp *const i) { nw_varuint32 target; struct nw_i_sm_br_table *const b = &i->sm.br_table; const struct nw_io_cfg *const cfg = &i->cfg.io; const enum nw_state n = nwp_varuint32(cfg, &b->leb128, &target, cfg->user); if (n) return n; else if (b->target_i == b->offset || (!b->set && b->target_i >= b->target_count)) { b->set = 1; b->relative_depth = target; } if (b->target_i >= b->target_count) nwp_break(i, b->relative_depth, b->offset); else b->target_i++; return NW_AGAIN; } static enum nw_state pop(struct nw_interp *const i) { struct nw_i_sm_br_table *const b = &i->sm.br_table; const enum nw_state n = nwp_stack_pop(i, &b->io); if (n) return n; i->next = get_target; return NW_AGAIN; } static enum nw_state get_target_count(struct nw_interp *const i) { struct nw_i_sm_br_table *const b = &i->sm.br_table; const struct nw_io_cfg *const cfg = &i->cfg.io; const enum nw_state n = nwp_varuint32(cfg, &b->leb128, &b->target_count, cfg->user); const enum nw_type pt = i->push_type; if (n) return n; else if (pt != NW_TYPE_I32) { static const char *const exc = "expected i32 expression for br_table"; const char *const stype = nwp_type_str(pt); i->exception = exc; #ifdef NW_LOG if (stype) nwp_log("%s, got: %s\n", exc, stype); else nwp_log("%s, got: unknown (%#x)\n", exc, (unsigned)pt); #endif return NW_FATAL; } else { struct nw_sm_io io = {0}; io.buf = &b->offset; io.n = sizeof b->offset; b->io = io; i->next = pop; } return NW_AGAIN; } void nwp_op_br_table(struct nw_interp *const i) { static const struct nw_i_sm_br_table b; i->next = get_target_count; i->sm.br_table = b; }