diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-11-15 18:53:12 +0100 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-11-15 18:53:12 +0100 |
| commit | 6c2108e6bd19ffa47b33f61501f25db47ddb4cfb (patch) | |
| tree | cb28509831024fa44f564bfb4cfd2dafeef97e73 | |
| parent | b1034b86023672e6750da49b01a7d429cd8339d0 (diff) | |
Add select operator
| -rw-r--r-- | include/nanowasm/private.h | 10 | ||||
| -rw-r--r-- | private_include/nw/ops.h | 1 | ||||
| -rw-r--r-- | src/interp/ops.c | 2 | ||||
| -rw-r--r-- | src/op/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/op/select.c | 119 |
5 files changed, 132 insertions, 1 deletions
diff --git a/include/nanowasm/private.h b/include/nanowasm/private.h index 4a378d3..e396a6b 100644 --- a/include/nanowasm/private.h +++ b/include/nanowasm/private.h @@ -439,6 +439,16 @@ union nw_i_sm union nw_value value; } drop; + struct nw_i_sm_select + { + long condition; + size_t sz; + enum nw_type type; + union nw_value left, right; + struct nw_sm_io io; + union nw_value value; + } select; + struct nw_i_sm_cm { struct nw_sm_leb128 leb128; diff --git a/private_include/nw/ops.h b/private_include/nw/ops.h index 9287cfa..0e5fb09 100644 --- a/private_include/nw/ops.h +++ b/private_include/nw/ops.h @@ -28,6 +28,7 @@ void nwp_op_return(struct nw_interp *i); void nwp_op_call(struct nw_interp *i); void nwp_op_call_indirect(struct nw_interp *i); void nwp_op_drop(struct nw_interp *i); +void nwp_op_select(struct nw_interp *i); void nwp_op_get_local(struct nw_interp *i); void nwp_op_set_local(struct nw_interp *i); void nwp_op_tee_local(struct nw_interp *i); diff --git a/src/interp/ops.c b/src/interp/ops.c index 4366a49..7c0d911 100644 --- a/src/interp/ops.c +++ b/src/interp/ops.c @@ -41,7 +41,7 @@ static void (*const ops[])(struct nw_interp *) = NULL, NULL, nwp_op_drop, /* OP_DROP */ - NULL, /* OP_SELECT */ + nwp_op_select, /* OP_SELECT */ NULL, NULL, NULL, diff --git a/src/op/CMakeLists.txt b/src/op/CMakeLists.txt index 7cc6ff8..90ce763 100644 --- a/src/op/CMakeLists.txt +++ b/src/op/CMakeLists.txt @@ -49,6 +49,7 @@ target_sources(${PROJECT_NAME} PRIVATE loop.c nop.c return.c + select.c set_global.c set_local.c tee_local.c diff --git a/src/op/select.c b/src/op/select.c new file mode 100644 index 0000000..7705af9 --- /dev/null +++ b/src/op/select.c @@ -0,0 +1,119 @@ +/* + * 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 <nw/interp.h> +#include <nw/io.h> +#include <nw/log.h> +#include <nw/opcodes.h> +#include <nw/ops.h> +#include <nw/stack.h> +#include <nw/types.h> + +static enum nw_state push(struct nw_interp *const i) +{ + struct nw_i_sm_select *const s = &i->sm.select; + const enum nw_state n = nwp_stack_push(i, &s->io); + + if (n) + return n; + + nwp_interp_resume(i); + return NW_AGAIN; +} + +static enum nw_state pop_left(struct nw_interp *const i) +{ + struct nw_i_sm_select *const s = &i->sm.select; + const enum nw_state n = nwp_stack_pop(i, &s->io); + struct nw_sm_io io = {0}; + + if (n) + return n; + + io.buf = s->condition ? &s->left : &s->right; + io.n = s->sz; + s->io = io; + i->next = push; + return NW_AGAIN; +} + +static enum nw_state pop_right(struct nw_interp *const i) +{ + struct nw_i_sm_select *const s = &i->sm.select; + const enum nw_state n = nwp_stack_pop(i, &s->io); + + if (n) + return n; + else + { + struct nw_sm_io io = {0}; + + io.buf = &s->left; + io.n = s->sz; + s->io = io; + } + + i->next = pop_left; + return NW_AGAIN; +} + +static enum nw_state pop_condition(struct nw_interp *const i) +{ + struct nw_i_sm_select *const s = &i->sm.select; + const enum nw_state n = nwp_stack_pop(i, &s->io); + + if (n) + return n; + else + { + struct nw_sm_io io = {0}; + + io.buf = &s->right; + io.n = s->sz; + s->io = io; + } + + i->next = pop_right; + return NW_AGAIN; +} + +static enum nw_state check(struct nw_interp *const i) +{ + struct nw_i_sm_select *const s = &i->sm.select; + + if (nwp_type_sz(i->push_type, &s->sz)) + { + static const char *const exc = "invalid type"; + + i->exception = exc; +#ifdef NW_LOG + nwp_log("%s: %#x\n", exc, (unsigned)i->push_type); +#endif + return NW_FATAL; + } + else + { + struct nw_sm_io io = {0}; + + io.buf = &s->condition; + io.n = sizeof s->condition; + s->io = io; + } + + i->next = pop_condition; + return NW_AGAIN; +} + +void nwp_op_select(struct nw_interp *const i) +{ + const struct nw_i_sm_select s = {0}; + + i->sm.select = s; + i->next = check; +} |
