/src/WasmEdge/lib/api/wasm_c.cpp
Line | Count | Source |
1 | | // SPDX-License-Identifier: Apache-2.0 |
2 | | // SPDX-FileCopyrightText: Copyright The WasmEdge Authors |
3 | | |
4 | | #include <algorithm> |
5 | | #include <unordered_map> |
6 | | |
7 | | #include "common/configure.h" |
8 | | #include "common/errcode.h" |
9 | | #include "common/span.h" |
10 | | |
11 | | #include "ast/module.h" |
12 | | #include "executor/executor.h" |
13 | | #include "loader/loader.h" |
14 | | #include "runtime/storemgr.h" |
15 | | #include "validator/validator.h" |
16 | | |
17 | | // When building the library on Windows, align WASM_API_EXTERN with |
18 | | // WASMEDGE_CAPI_EXPORT so that declarations and definitions have |
19 | | // the same linkage attribute. |
20 | | #if defined(_WIN32) && !defined(__MINGW32__) && \ |
21 | | defined(WASMEDGE_COMPILE_LIBRARY) |
22 | | #define WASM_API_EXTERN __declspec(dllexport) |
23 | | #endif |
24 | | |
25 | | // Suppress deprecated-copy-with-dtor warnings from thirdparty headers |
26 | | // triggered by dllexport forcing instantiation of implicit operators. |
27 | | #if defined(__clang__) |
28 | | #pragma clang diagnostic push |
29 | | #pragma clang diagnostic ignored "-Wdeprecated-copy-with-dtor" |
30 | | #endif |
31 | | |
32 | | #include "wasm.h" |
33 | | #include "wasm.hh" |
34 | | |
35 | | #if defined(__clang__) |
36 | | #pragma clang diagnostic pop |
37 | | #endif |
38 | | |
39 | | #include "wasmedge/wasmedge.h" |
40 | | |
41 | | #ifndef OWN |
42 | | #define OWN |
43 | | #endif |
44 | | |
45 | | namespace { |
46 | | |
47 | | // WasmEdge::ValType to wasm::ValKind conversion. |
48 | 0 | wasm::ValKind conv_valtype_from_wasmedge(const WasmEdge::ValType &vt) { |
49 | 0 | if (vt.isNumType()) { |
50 | 0 | switch (vt.getCode()) { |
51 | 0 | case WasmEdge::TypeCode::I32: |
52 | 0 | return wasm::ValKind::I32; |
53 | 0 | case WasmEdge::TypeCode::I64: |
54 | 0 | return wasm::ValKind::I64; |
55 | 0 | case WasmEdge::TypeCode::F32: |
56 | 0 | return wasm::ValKind::F32; |
57 | 0 | case WasmEdge::TypeCode::F64: |
58 | 0 | return wasm::ValKind::F64; |
59 | 0 | default: |
60 | 0 | break; |
61 | 0 | } |
62 | 0 | } else if (vt.isFuncRefType()) { |
63 | 0 | return wasm::ValKind::FUNCREF; |
64 | 0 | } else if (vt.isExternRefType()) { |
65 | 0 | return wasm::ValKind::EXTERNREF; |
66 | 0 | } |
67 | | // v128 and other types are not supported in wasm C API yet. |
68 | 0 | assumingUnreachable(); |
69 | 0 | } |
70 | | |
71 | | // WasmEdge::ValType (ref type) to wasm::ValKind conversion. |
72 | 0 | wasm::ValKind conv_reftype_from_wasmedge(const WasmEdge::ValType &vt) { |
73 | 0 | if (vt.isFuncRefType()) { |
74 | 0 | return wasm::ValKind::FUNCREF; |
75 | 0 | } else if (vt.isExternRefType()) { |
76 | 0 | return wasm::ValKind::EXTERNREF; |
77 | 0 | } else { |
78 | 0 | assumingUnreachable(); |
79 | 0 | } |
80 | 0 | } |
81 | | |
82 | | // WasmEdge::ValMut to wasm::Mutability conversion. |
83 | 0 | wasm::Mutability conv_valmut_from_wasmedge(WasmEdge::ValMut mut) { |
84 | 0 | switch (mut) { |
85 | 0 | case WasmEdge::ValMut::Const: |
86 | 0 | return wasm::Mutability::CONST; |
87 | 0 | case WasmEdge::ValMut::Var: |
88 | 0 | return wasm::Mutability::VAR; |
89 | 0 | default: |
90 | 0 | assumingUnreachable(); |
91 | 0 | } |
92 | 0 | } |
93 | | |
94 | | // wasm::ValType to WasmEdge::ValType conversion. |
95 | 0 | WasmEdge::ValType conv_valtype_to_wasmedge(wasm::ValKind vt) { |
96 | 0 | switch (vt) { |
97 | 0 | case wasm::ValKind::I32: |
98 | 0 | return WasmEdge::ValType(WasmEdge::TypeCode::I32); |
99 | 0 | case wasm::ValKind::I64: |
100 | 0 | return WasmEdge::ValType(WasmEdge::TypeCode::I64); |
101 | 0 | case wasm::ValKind::F32: |
102 | 0 | return WasmEdge::ValType(WasmEdge::TypeCode::F32); |
103 | 0 | case wasm::ValKind::F64: |
104 | 0 | return WasmEdge::ValType(WasmEdge::TypeCode::F64); |
105 | 0 | case wasm::ValKind::FUNCREF: |
106 | 0 | return WasmEdge::ValType(WasmEdge::TypeCode::FuncRef); |
107 | 0 | case wasm::ValKind::EXTERNREF: |
108 | 0 | return WasmEdge::ValType(WasmEdge::TypeCode::ExternRef); |
109 | 0 | default: |
110 | 0 | assumingUnreachable(); |
111 | 0 | } |
112 | 0 | } |
113 | | |
114 | | // wasm::ValKind to WasmEdge::ValType (ref type) conversion. |
115 | 0 | WasmEdge::ValType conv_reftype_to_wasmedge(wasm::ValKind vt) { |
116 | 0 | switch (vt) { |
117 | 0 | case wasm::ValKind::FUNCREF: |
118 | 0 | return WasmEdge::ValType(WasmEdge::TypeCode::FuncRef); |
119 | 0 | case wasm::ValKind::EXTERNREF: |
120 | 0 | return WasmEdge::ValType(WasmEdge::TypeCode::ExternRef); |
121 | 0 | default: |
122 | 0 | assumingUnreachable(); |
123 | 0 | } |
124 | 0 | } |
125 | | |
126 | | // wasm::Mutability to WasmEdge::ValMut conversion. |
127 | 0 | WasmEdge::ValMut conv_valmut_to_wasmedge(wasm::Mutability mut) { |
128 | 0 | switch (mut) { |
129 | 0 | case wasm::Mutability::CONST: |
130 | 0 | return WasmEdge::ValMut::Const; |
131 | 0 | case wasm::Mutability::VAR: |
132 | 0 | return WasmEdge::ValMut::Var; |
133 | 0 | default: |
134 | 0 | assumingUnreachable(); |
135 | 0 | } |
136 | 0 | } |
137 | | |
138 | | // Make wasm::Limits from WasmEdge::AST::Limit. |
139 | 0 | wasm::Limits make_limits_from_wasmedge(const WasmEdge::AST::Limit &lm) { |
140 | 0 | if (lm.hasMax()) { |
141 | 0 | return wasm::Limits(static_cast<uint32_t>(lm.getMin()), |
142 | 0 | static_cast<uint32_t>(lm.getMax())); |
143 | 0 | } else { |
144 | 0 | return wasm::Limits(static_cast<uint32_t>(lm.getMin())); |
145 | 0 | } |
146 | 0 | } |
147 | | |
148 | | // Make wasm::own<wasm::FuncType> from WasmEdge::AST::FunctionType. |
149 | | wasm::own<wasm::FuncType> |
150 | 0 | make_functype_from_wasmedge(const WasmEdge::AST::FunctionType &ft) { |
151 | 0 | auto p = wasm::ownvec<wasm::ValType>::make_uninitialized( |
152 | 0 | ft.getParamTypes().size()); |
153 | 0 | for (size_t i = 0; i < p.size(); ++i) { |
154 | 0 | p[i] = |
155 | 0 | wasm::ValType::make(conv_valtype_from_wasmedge(ft.getParamTypes()[i])); |
156 | 0 | } |
157 | 0 | auto r = wasm::ownvec<wasm::ValType>::make_uninitialized( |
158 | 0 | ft.getReturnTypes().size()); |
159 | 0 | for (size_t i = 0; i < r.size(); ++i) { |
160 | 0 | r[i] = |
161 | 0 | wasm::ValType::make(conv_valtype_from_wasmedge(ft.getReturnTypes()[i])); |
162 | 0 | } |
163 | 0 | return wasm::FuncType::make(std::move(p), std::move(r)); |
164 | 0 | } |
165 | | |
166 | | // Make WasmEdge::AST::FunctionType from wasm::FuncType. |
167 | 0 | WasmEdge::AST::FunctionType make_functype_from_wasm(const wasm::FuncType &ft) { |
168 | 0 | std::vector<WasmEdge::ValType> p(ft.params().size()), r(ft.results().size()); |
169 | 0 | for (size_t i = 0; i < p.size(); ++i) { |
170 | 0 | p[i] = conv_valtype_to_wasmedge(ft.params()[i]->kind()); |
171 | 0 | } |
172 | 0 | for (size_t i = 0; i < r.size(); ++i) { |
173 | 0 | r[i] = conv_valtype_to_wasmedge(ft.results()[i]->kind()); |
174 | 0 | } |
175 | 0 | return WasmEdge::AST::FunctionType(p, r); |
176 | 0 | } |
177 | | |
178 | | // Make wasm::own<wasm::GlobalType> from WasmEdge::AST::GlobalType. |
179 | | wasm::own<wasm::GlobalType> |
180 | 0 | make_globaltype_from_wasmedge(const WasmEdge::AST::GlobalType >) { |
181 | 0 | return wasm::GlobalType::make( |
182 | 0 | wasm::ValType::make(conv_valtype_from_wasmedge(gt.getValType())), |
183 | 0 | conv_valmut_from_wasmedge(gt.getValMut())); |
184 | 0 | } |
185 | | |
186 | | // Make wasm::own<wasm::TableType> from WasmEdge::AST::TableType. |
187 | | wasm::own<wasm::TableType> |
188 | 0 | make_tabletype_from_wasmedge(const WasmEdge::AST::TableType &tt) { |
189 | 0 | return wasm::TableType::make( |
190 | 0 | wasm::ValType::make(conv_reftype_from_wasmedge(tt.getRefType())), |
191 | 0 | make_limits_from_wasmedge(tt.getLimit())); |
192 | 0 | } |
193 | | |
194 | | // Make wasm::own<wasm::MemoryType> from WasmEdge::AST::MemoryType. |
195 | | wasm::own<wasm::MemoryType> |
196 | 0 | make_memorytype_from_wasmedge(const WasmEdge::AST::MemoryType &mt) { |
197 | 0 | return wasm::MemoryType::make(make_limits_from_wasmedge(mt.getLimit())); |
198 | 0 | } |
199 | | |
200 | | // Make wasm::own<wasm::TagType> from WasmEdge's tag-defining SubType. |
201 | | wasm::own<wasm::TagType> |
202 | 0 | make_tagtype_from_wasmedge(const WasmEdge::AST::SubType &st) { |
203 | 0 | if (st.getCompositeType().isFunc()) { |
204 | 0 | return wasm::TagType::make( |
205 | 0 | make_functype_from_wasmedge(st.getCompositeType().getFuncType())); |
206 | 0 | } |
207 | 0 | return wasm::TagType::make(wasm::FuncType::make()); |
208 | 0 | } |
209 | | |
210 | | // wasm_allocmgr_t: the allocation manager for the runtime objects. |
211 | | struct wasm_allocmgr_t { |
212 | | // Entry for each tracked runtime object, storing refcount, destroyer, |
213 | | // and cached host info for type-safe cleanup in the destructor. |
214 | | struct ref_entry_t { |
215 | | size_t refcount; |
216 | | std::function<void(void *)> destroyer; |
217 | | void *info; |
218 | | void (*finalizer)(void *); |
219 | | }; |
220 | | |
221 | | template <typename T> |
222 | | void link( |
223 | 0 | T *target, void (*dest)(void *) = [](void *target) { |
224 | 0 | delete static_cast<T *>(target); |
225 | 0 | }) {Unexecuted instantiation: wasm_c.cpp:(anonymous namespace)::wasm_allocmgr_t::link<wasm_trap_t>(wasm_trap_t*, void (*)(void*))::{default arg#1}::{lambda(void*)#1}::operator()(void*) constUnexecuted instantiation: wasm_c.cpp:(anonymous namespace)::wasm_allocmgr_t::link<wasm_module_t>(wasm_module_t*, void (*)(void*))::{default arg#1}::{lambda(void*)#1}::operator()(void*) constUnexecuted instantiation: wasm_c.cpp:(anonymous namespace)::wasm_allocmgr_t::link<wasm_func_t>(wasm_func_t*, void (*)(void*))::{default arg#1}::{lambda(void*)#1}::operator()(void*) constUnexecuted instantiation: wasm_c.cpp:(anonymous namespace)::wasm_allocmgr_t::link<wasm_foreign_t>(wasm_foreign_t*, void (*)(void*))::{default arg#1}::{lambda(void*)#1}::operator()(void*) constUnexecuted instantiation: wasm_c.cpp:(anonymous namespace)::wasm_allocmgr_t::link<wasm_global_t>(wasm_global_t*, void (*)(void*))::{default arg#1}::{lambda(void*)#1}::operator()(void*) constUnexecuted instantiation: wasm_c.cpp:(anonymous namespace)::wasm_allocmgr_t::link<wasm_table_t>(wasm_table_t*, void (*)(void*))::{default arg#1}::{lambda(void*)#1}::operator()(void*) constUnexecuted instantiation: wasm_c.cpp:(anonymous namespace)::wasm_allocmgr_t::link<wasm_memory_t>(wasm_memory_t*, void (*)(void*))::{default arg#1}::{lambda(void*)#1}::operator()(void*) constUnexecuted instantiation: wasm_c.cpp:(anonymous namespace)::wasm_allocmgr_t::link<wasm_instance_t>(wasm_instance_t*, void (*)(void*))::{default arg#1}::{lambda(void*)#1}::operator()(void*) constUnexecuted instantiation: wasm_c.cpp:(anonymous namespace)::wasm_allocmgr_t::link<wasm_ref_t>(wasm_ref_t*, void (*)(void*))::{default arg#1}::{lambda(void*)#1}::operator()(void*) constUnexecuted instantiation: wasm_c.cpp:(anonymous namespace)::wasm_allocmgr_t::link<wasm_extern_t>(wasm_extern_t*, void (*)(void*))::{default arg#1}::{lambda(void*)#1}::operator()(void*) const |
226 | 0 | auto it = entries.find(static_cast<void *>(target)); |
227 | 0 | if (it == entries.end()) { |
228 | 0 | entries.emplace(static_cast<void *>(target), |
229 | 0 | ref_entry_t{1, dest, target->info, target->finalizer}); |
230 | 0 | } else { |
231 | 0 | it->second.refcount += 1; |
232 | 0 | } |
233 | 0 | } Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::link<wasm_trap_t>(wasm_trap_t*, void (*)(void*)) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::link<wasm_module_t>(wasm_module_t*, void (*)(void*)) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::link<wasm_func_t>(wasm_func_t*, void (*)(void*)) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::link<wasm_foreign_t>(wasm_foreign_t*, void (*)(void*)) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::link<wasm_global_t>(wasm_global_t*, void (*)(void*)) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::link<wasm_table_t>(wasm_table_t*, void (*)(void*)) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::link<wasm_memory_t>(wasm_memory_t*, void (*)(void*)) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::link<wasm_instance_t>(wasm_instance_t*, void (*)(void*)) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::link<wasm_ref_t>(wasm_ref_t*, void (*)(void*)) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::link<wasm_extern_t>(wasm_extern_t*, void (*)(void*)) |
234 | | |
235 | 0 | template <typename T> void unlink(T *target) { |
236 | 0 | auto it = entries.find(static_cast<void *>(target)); |
237 | 0 | if (it != entries.end()) { |
238 | 0 | it->second.refcount -= 1; |
239 | 0 | if (it->second.refcount == 0) { |
240 | 0 | if (target->finalizer) { |
241 | 0 | target->finalizer(target->info); |
242 | 0 | } |
243 | | // Erase the entry before calling the destroyer to prevent |
244 | | // re-entrance if the destructor chain calls unlink() again. |
245 | 0 | auto dest = std::move(it->second.destroyer); |
246 | 0 | entries.erase(it); |
247 | 0 | dest(target); |
248 | 0 | } |
249 | 0 | } |
250 | 0 | } Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::unlink<wasm_ref_t>(wasm_ref_t*) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::unlink<wasm_trap_t>(wasm_trap_t*) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::unlink<wasm_foreign_t>(wasm_foreign_t*) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::unlink<wasm_module_t>(wasm_module_t*) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::unlink<wasm_func_t>(wasm_func_t*) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::unlink<wasm_global_t>(wasm_global_t*) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::unlink<wasm_table_t>(wasm_table_t*) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::unlink<wasm_memory_t>(wasm_memory_t*) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::unlink<wasm_extern_t>(wasm_extern_t*) Unexecuted instantiation: wasm_c.cpp:void (anonymous namespace)::wasm_allocmgr_t::unlink<wasm_instance_t>(wasm_instance_t*) |
251 | | |
252 | | ~wasm_allocmgr_t(); |
253 | | |
254 | | private: |
255 | | std::unordered_map<void *, ref_entry_t> entries; |
256 | | std::unordered_map<const WasmEdge::Runtime::Instance::FunctionInstance *, |
257 | | void *> |
258 | | funcmap; |
259 | | }; |
260 | | |
261 | | // Value conversion forward declaration. |
262 | | inline wasm_val_t conv_cval_from_wasmedge(const WasmEdge::ValVariant &, |
263 | | const WasmEdge::ValType &); |
264 | | inline wasm::Val conv_cppval_from_wasmedge(const WasmEdge::ValVariant &, |
265 | | const WasmEdge::ValType &); |
266 | | inline WasmEdge::ValVariant conv_cval_to_wasmedge(const wasm_val_t &); |
267 | | inline WasmEdge::ValVariant conv_cppval_to_wasmedge(const wasm::Val &); |
268 | | inline wasm::Val conv_val_to_cpp(const wasm_val_t &); |
269 | | inline wasm_val_t conv_val_to_c(const wasm::Val &); |
270 | | |
271 | | // wasm_hostfunc_t: the wrapper to host function in wasm C/C++ API. |
272 | | class wasm_hostfunc_t : public WasmEdge::Runtime::HostFunctionBase { |
273 | | public: |
274 | | wasm_hostfunc_t(const wasm::FuncType &ft, wasm_func_callback_t cb) noexcept |
275 | 0 | : WasmEdge::Runtime::HostFunctionBase(0), type(api_type_enum::C), |
276 | 0 | env(nullptr), finalizer(nullptr) { |
277 | 0 | callback.c = cb; |
278 | 0 | DefType = WasmEdge::AST::SubType(make_functype_from_wasm(ft)); |
279 | 0 | } |
280 | | wasm_hostfunc_t(const wasm::FuncType &ft, wasm_func_callback_with_env_t cb, |
281 | | void *e, void (*fin)(void *)) noexcept |
282 | 0 | : WasmEdge::Runtime::HostFunctionBase(0), type(api_type_enum::C_ENV), |
283 | 0 | env(e), finalizer(fin) { |
284 | 0 | callback.c_env = cb; |
285 | 0 | DefType = WasmEdge::AST::SubType(make_functype_from_wasm(ft)); |
286 | 0 | } |
287 | | wasm_hostfunc_t(const wasm::FuncType &ft, wasm::Func::callback cb) noexcept |
288 | 0 | : WasmEdge::Runtime::HostFunctionBase(0), type(api_type_enum::CPP), |
289 | 0 | env(nullptr), finalizer(nullptr) { |
290 | 0 | callback.cpp = cb; |
291 | 0 | DefType = WasmEdge::AST::SubType(make_functype_from_wasm(ft)); |
292 | 0 | } |
293 | | wasm_hostfunc_t(const wasm::FuncType &ft, wasm::Func::callback_with_env cb, |
294 | | void *e, void (*fin)(void *)) noexcept |
295 | 0 | : WasmEdge::Runtime::HostFunctionBase(0), type(api_type_enum::CPP_ENV), |
296 | 0 | env(e), finalizer(fin) { |
297 | 0 | callback.cpp_env = cb; |
298 | 0 | DefType = WasmEdge::AST::SubType(make_functype_from_wasm(ft)); |
299 | 0 | } |
300 | | // Alias copy: share callback + env without the finalizer, used when |
301 | | // importing a host wasm_func_t into another instance. |
302 | | explicit wasm_hostfunc_t(const wasm_hostfunc_t &other) noexcept |
303 | 0 | : WasmEdge::Runtime::HostFunctionBase(0), type(other.type), |
304 | 0 | callback(other.callback), env(other.env), finalizer(nullptr) { |
305 | 0 | DefType = other.DefType; |
306 | 0 | } |
307 | 0 | ~wasm_hostfunc_t() noexcept override { |
308 | 0 | if (finalizer) { |
309 | 0 | finalizer(env); |
310 | 0 | } |
311 | 0 | } |
312 | | |
313 | | WasmEdge::Expect<void> |
314 | | run(const WasmEdge::Runtime::CallingFrame &, |
315 | | WasmEdge::Span<const WasmEdge::ValVariant> Args, |
316 | 0 | WasmEdge::Span<WasmEdge::ValVariant> Rets) override { |
317 | 0 | auto &ptypes = getFuncType().getParamTypes(); |
318 | 0 | auto &rtypes = getFuncType().getReturnTypes(); |
319 | |
|
320 | 0 | if (type == api_type_enum::C || type == api_type_enum::C_ENV) { |
321 | | // Prepare the arguments. |
322 | 0 | std::vector<wasm_val_t> pdata(ptypes.size()); |
323 | 0 | std::vector<wasm_val_t> rdata(rtypes.size()); |
324 | 0 | wasm_val_vec_t params = {ptypes.size(), pdata.data()}; |
325 | 0 | wasm_val_vec_t returns = {rtypes.size(), rdata.data()}; |
326 | 0 | for (size_t i = 0; i < Args.size(); ++i) { |
327 | 0 | params.data[i] = conv_cval_from_wasmedge(Args[i], ptypes[i]); |
328 | 0 | } |
329 | | |
330 | | // Invocation. |
331 | 0 | wasm_trap_t *trap = nullptr; |
332 | 0 | if (callback.c) { |
333 | 0 | if (type == api_type_enum::C) { |
334 | 0 | trap = callback.c(¶ms, &returns); |
335 | 0 | } else { |
336 | 0 | trap = callback.c_env(env, ¶ms, &returns); |
337 | 0 | } |
338 | 0 | } |
339 | | |
340 | | // Get the results. |
341 | 0 | if (trap) { |
342 | 0 | wasm_trap_delete(trap); |
343 | 0 | return Unexpect(WasmEdge::ErrCode::Value::HostFuncError); |
344 | 0 | } |
345 | 0 | for (size_t i = 0; i < Rets.size(); ++i) { |
346 | 0 | Rets[i] = conv_cval_to_wasmedge(returns.data[i]); |
347 | 0 | } |
348 | 0 | } else { |
349 | | // Prepare the arguments. |
350 | 0 | auto params = wasm::vec<wasm::Val>::make_uninitialized(ptypes.size()); |
351 | 0 | auto returns = wasm::vec<wasm::Val>::make_uninitialized(rtypes.size()); |
352 | 0 | for (size_t i = 0; i < Args.size(); ++i) { |
353 | 0 | params[i] = conv_cppval_from_wasmedge(Args[i], ptypes[i]); |
354 | 0 | } |
355 | | |
356 | | // Invocation. |
357 | 0 | wasm::own<wasm::Trap> trap; |
358 | 0 | if (callback.cpp) { |
359 | 0 | if (type == api_type_enum::CPP) { |
360 | 0 | trap = callback.cpp(params, returns); |
361 | 0 | } else { |
362 | 0 | trap = callback.cpp_env(env, params, returns); |
363 | 0 | } |
364 | 0 | } |
365 | | |
366 | | // Get the results. |
367 | 0 | if (trap) { |
368 | 0 | return Unexpect(WasmEdge::ErrCode::Value::HostFuncError); |
369 | 0 | } |
370 | 0 | for (size_t i = 0; i < Rets.size(); ++i) { |
371 | 0 | Rets[i] = conv_cppval_to_wasmedge(returns[i]); |
372 | 0 | } |
373 | 0 | } |
374 | 0 | return {}; |
375 | 0 | } |
376 | | |
377 | | private: |
378 | | enum class api_type_enum { C, CPP, C_ENV, CPP_ENV }; |
379 | | api_type_enum type; |
380 | | union { |
381 | | wasm_func_callback_t c; |
382 | | wasm::Func::callback cpp; |
383 | | wasm_func_callback_with_env_t c_env; |
384 | | wasm::Func::callback_with_env cpp_env; |
385 | | } callback; |
386 | | void *env; |
387 | | void (*finalizer)(void *); |
388 | | }; |
389 | | |
390 | | // wasm_category_val implementation. |
391 | | template <class C> struct wasm_externkind_val; |
392 | | template <> struct wasm_externkind_val<wasm::FuncType> { |
393 | | static const auto value = wasm::ExternKind::FUNC; |
394 | | }; |
395 | | template <> struct wasm_externkind_val<wasm::GlobalType> { |
396 | | static const auto value = wasm::ExternKind::GLOBAL; |
397 | | }; |
398 | | template <> struct wasm_externkind_val<wasm::TableType> { |
399 | | static const auto value = wasm::ExternKind::TABLE; |
400 | | }; |
401 | | template <> struct wasm_externkind_val<wasm::MemoryType> { |
402 | | static const auto value = wasm::ExternKind::MEMORY; |
403 | | }; |
404 | | template <> struct wasm_externkind_val<wasm::TagType> { |
405 | | static const auto value = wasm::ExternKind::TAG; |
406 | | }; |
407 | | |
408 | | // wasm_category_enum for the runtime objects. |
409 | | enum class wasm_category_enum : uint8_t { |
410 | | TRAP, |
411 | | FOREIGN, |
412 | | MODULE, |
413 | | FUNC, |
414 | | GLOBAL, |
415 | | TABLE, |
416 | | MEMORY, |
417 | | INSTANCE |
418 | | }; |
419 | | |
420 | | // wasm_category_val implementation. |
421 | | template <class C> struct wasm_category_val; |
422 | | template <> struct wasm_category_val<wasm_trap_t> { |
423 | | static const auto value = wasm_category_enum::TRAP; |
424 | | }; |
425 | | template <> struct wasm_category_val<wasm_foreign_t> { |
426 | | static const auto value = wasm_category_enum::FOREIGN; |
427 | | }; |
428 | | template <> struct wasm_category_val<wasm_module_t> { |
429 | | static const auto value = wasm_category_enum::MODULE; |
430 | | }; |
431 | | template <> struct wasm_category_val<wasm_func_t> { |
432 | | static const auto value = wasm_category_enum::FUNC; |
433 | | }; |
434 | | template <> struct wasm_category_val<wasm_global_t> { |
435 | | static const auto value = wasm_category_enum::GLOBAL; |
436 | | }; |
437 | | template <> struct wasm_category_val<wasm_table_t> { |
438 | | static const auto value = wasm_category_enum::TABLE; |
439 | | }; |
440 | | template <> struct wasm_category_val<wasm_memory_t> { |
441 | | static const auto value = wasm_category_enum::MEMORY; |
442 | | }; |
443 | | template <> struct wasm_category_val<wasm_instance_t> { |
444 | | static const auto value = wasm_category_enum::INSTANCE; |
445 | | }; |
446 | | |
447 | | // Imports shim that aliases (does not own) the user's runtime instances. |
448 | | class wasm_import_module_t |
449 | | : public WasmEdge::Runtime::Instance::ModuleInstance { |
450 | | public: |
451 | | explicit wasm_import_module_t(std::string_view name) noexcept |
452 | 0 | : WasmEdge::Runtime::Instance::ModuleInstance(name) {} |
453 | | |
454 | | void aliasFunc(std::string_view name, |
455 | 0 | WasmEdge::Runtime::Instance::FunctionInstance *fi) { |
456 | | // Native/compiled funcs: linker reads the type from fi->getModule(). |
457 | | // Host funcs have no owner module, so register a copy under this shim. |
458 | 0 | if (fi->getModule()) { |
459 | 0 | importFunction(fi); |
460 | 0 | exportFunction(name, FuncCount++); |
461 | 0 | } else { |
462 | 0 | const auto &orig = static_cast<wasm_hostfunc_t &>(fi->getHostFunc()); |
463 | 0 | addHostFunc(name, std::make_unique<wasm_hostfunc_t>(orig)); |
464 | 0 | } |
465 | 0 | } |
466 | | void aliasGlobal(std::string_view name, |
467 | 0 | WasmEdge::Runtime::Instance::GlobalInstance *gi) { |
468 | 0 | importGlobal(gi); |
469 | 0 | exportGlobal(name, GlobCount++); |
470 | 0 | } |
471 | | void aliasTable(std::string_view name, |
472 | 0 | WasmEdge::Runtime::Instance::TableInstance *ti) { |
473 | 0 | importTable(ti); |
474 | 0 | exportTable(name, TabCount++); |
475 | 0 | } |
476 | | void aliasMemory(std::string_view name, |
477 | 0 | WasmEdge::Runtime::Instance::MemoryInstance *mi) { |
478 | 0 | importMemory(mi); |
479 | 0 | exportMemory(name, MemCount++); |
480 | 0 | } |
481 | | |
482 | | private: |
483 | | uint32_t FuncCount = 0; |
484 | | uint32_t GlobCount = 0; |
485 | | uint32_t TabCount = 0; |
486 | | uint32_t MemCount = 0; |
487 | | }; |
488 | | |
489 | | } // namespace |
490 | | |
491 | | // wasm_config_t implementation. |
492 | | struct wasm_config_t : public wasm::Config { |
493 | 0 | wasm_config_t() noexcept = default; |
494 | | WasmEdge::Configure conf; |
495 | | }; |
496 | | |
497 | | // wasm_engine_t implementation. |
498 | | struct wasm_engine_t : public wasm::Engine { |
499 | | wasm_engine_t() noexcept |
500 | 0 | : mconf(new (std::nothrow) wasm_config_t), |
501 | 0 | exec(static_cast<wasm_config_t *>(mconf.get())->conf, nullptr) {} |
502 | | wasm_engine_t(wasm::own<wasm::Config> &&c) noexcept |
503 | 0 | : mconf(std::move(c)), |
504 | 0 | exec(static_cast<wasm_config_t *>(mconf.get())->conf, nullptr) {} |
505 | | wasm::own<wasm::Config> mconf; |
506 | | WasmEdge::Executor::Executor exec; |
507 | | }; |
508 | | |
509 | | // wasm_store_t implementation. |
510 | | struct wasm_store_t : public wasm::Store { |
511 | | wasm_store_t(wasm::Engine *e) noexcept |
512 | 0 | : engine(static_cast<wasm_engine_t *>(e)), |
513 | 0 | load(static_cast<wasm_config_t *>(engine->mconf.get())->conf), |
514 | 0 | valid(static_cast<wasm_config_t *>(engine->mconf.get())->conf), |
515 | 0 | store() {} |
516 | | wasm_engine_t *engine; |
517 | | wasm_allocmgr_t allocmgr; |
518 | | WasmEdge::Loader::Loader load; |
519 | | WasmEdge::Validator::Validator valid; |
520 | | WasmEdge::Runtime::StoreManager store; |
521 | | }; |
522 | | |
523 | | // wasm_valtype_t implementation. |
524 | | struct wasm_valtype_t : public wasm::ValType { |
525 | 36 | wasm_valtype_t(wasm::ValKind k) noexcept : mkind(k) {} |
526 | | wasm::ValKind mkind; |
527 | | }; |
528 | | |
529 | | // wasm_externtype_base_t implementation. |
530 | | template <class C> struct wasm_externtype_base_t : public C { |
531 | 0 | wasm_externtype_base_t() noexcept : mkind(wasm_externkind_val<C>::value) {}Unexecuted instantiation: wasm_externtype_base_t<wasm::FuncType>::wasm_externtype_base_t() Unexecuted instantiation: wasm_externtype_base_t<wasm::GlobalType>::wasm_externtype_base_t() Unexecuted instantiation: wasm_externtype_base_t<wasm::TableType>::wasm_externtype_base_t() Unexecuted instantiation: wasm_externtype_base_t<wasm::MemoryType>::wasm_externtype_base_t() Unexecuted instantiation: wasm_externtype_base_t<wasm::TagType>::wasm_externtype_base_t() |
532 | | wasm::ExternKind mkind; |
533 | | }; |
534 | | |
535 | | // wasm_externtype_t implementation. |
536 | | struct wasm_externtype_t : wasm_externtype_base_t<wasm::ExternType> { |
537 | | wasm_externtype_t() = delete; |
538 | | }; |
539 | | |
540 | | // wasm_functype_t implementation. |
541 | | struct wasm_functype_t : public wasm_externtype_base_t<wasm::FuncType> { |
542 | | wasm_functype_t(wasm::ownvec<wasm::ValType> &&vp, |
543 | | wasm::ownvec<wasm::ValType> &&vr) noexcept |
544 | 0 | : mparams(std::move(vp)), mresults(std::move(vr)) {} |
545 | | wasm::ownvec<wasm::ValType> mparams, mresults; |
546 | | }; |
547 | | |
548 | | // wasm_globaltype_t implementation. |
549 | | struct wasm_globaltype_t : public wasm_externtype_base_t<wasm::GlobalType> { |
550 | | wasm_globaltype_t(wasm::own<wasm::ValType> &&vt, |
551 | | wasm::Mutability mut) noexcept |
552 | 0 | : mcontent(std::move(vt)), mmutability(mut) {} |
553 | | wasm::own<wasm::ValType> mcontent; |
554 | | wasm::Mutability mmutability; |
555 | | }; |
556 | | |
557 | | // wasm_tabletype_t implementation. |
558 | | struct wasm_tabletype_t : public wasm_externtype_base_t<wasm::TableType> { |
559 | | wasm_tabletype_t(wasm::own<wasm::ValType> &&vt, wasm::Limits lim) noexcept |
560 | 0 | : mvaltype(std::move(vt)), mlimits(lim) {} |
561 | | wasm::own<wasm::ValType> mvaltype; |
562 | | wasm::Limits mlimits; |
563 | | }; |
564 | | |
565 | | // wasm_memorytype_t implementation. |
566 | | struct wasm_memorytype_t : public wasm_externtype_base_t<wasm::MemoryType> { |
567 | 0 | wasm_memorytype_t(wasm::Limits lim) noexcept : mlimits(lim) {} |
568 | | ~wasm_memorytype_t() noexcept = default; |
569 | | wasm::Limits mlimits; |
570 | | }; |
571 | | |
572 | | // wasm_tagtype_t implementation. |
573 | | struct wasm_tagtype_t : public wasm_externtype_base_t<wasm::TagType> { |
574 | | wasm_tagtype_t(wasm::own<wasm::FuncType> &&ft) noexcept |
575 | 0 | : mfunctype(std::move(ft)) {} |
576 | | wasm::own<wasm::FuncType> mfunctype; |
577 | | }; |
578 | | |
579 | | // wasm_importtype_t implementation. |
580 | | struct wasm_importtype_t : public wasm::ImportType { |
581 | | wasm_importtype_t(wasm::Name &&mod, wasm::Name &&n, |
582 | | wasm::own<wasm::ExternType> &&ext) noexcept |
583 | 0 | : mmodname(std::move(mod)), mname(std::move(n)), mtype(std::move(ext)) {} |
584 | | wasm::Name mmodname, mname; |
585 | | wasm::own<wasm::ExternType> mtype; |
586 | | }; |
587 | | |
588 | | // wasm_exporttype_t implementation. |
589 | | struct wasm_exporttype_t : public wasm::ExportType { |
590 | | wasm_exporttype_t(wasm::Name &&n, wasm::own<wasm::ExternType> &&ext) noexcept |
591 | 0 | : mname(std::move(n)), mtype(std::move(ext)) {} |
592 | | wasm::Name mname; |
593 | | wasm::own<wasm::ExternType> mtype; |
594 | | }; |
595 | | |
596 | | // wasm_ref_base_t implementation. |
597 | | template <class C> struct wasm_ref_base_t { |
598 | | // `inner` must hold the outer C* address (allocmgr's destroyer calls |
599 | | // delete on it); when wasm_ref_base_t is a non-first base, `this` differs. |
600 | | wasm_ref_base_t(wasm::Store *s) noexcept |
601 | 0 | : store(static_cast<wasm_store_t *>(s)), |
602 | 0 | category(wasm_category_val<C>::value), inner(static_cast<C *>(this)), |
603 | 0 | info(nullptr), finalizer(nullptr) { |
604 | 0 | increase_ref(); |
605 | 0 | } Unexecuted instantiation: wasm_ref_base_t<wasm_trap_t>::wasm_ref_base_t(wasm::Store*) Unexecuted instantiation: wasm_ref_base_t<wasm_module_t>::wasm_ref_base_t(wasm::Store*) Unexecuted instantiation: wasm_ref_base_t<wasm_func_t>::wasm_ref_base_t(wasm::Store*) Unexecuted instantiation: wasm_ref_base_t<wasm_foreign_t>::wasm_ref_base_t(wasm::Store*) Unexecuted instantiation: wasm_ref_base_t<wasm_global_t>::wasm_ref_base_t(wasm::Store*) Unexecuted instantiation: wasm_ref_base_t<wasm_table_t>::wasm_ref_base_t(wasm::Store*) Unexecuted instantiation: wasm_ref_base_t<wasm_memory_t>::wasm_ref_base_t(wasm::Store*) Unexecuted instantiation: wasm_ref_base_t<wasm_instance_t>::wasm_ref_base_t(wasm::Store*) |
606 | | wasm_ref_base_t(wasm::Store *s, const wasm_ref_base_t &ref) noexcept |
607 | | : store(static_cast<wasm_store_t *>(s)), category(ref.category), |
608 | | inner(ref.inner), info(ref.info), finalizer(ref.finalizer) { |
609 | | increase_ref(); |
610 | | } |
611 | | // No unlink() here — destroy() calls decrease_ref() explicitly to avoid |
612 | | // recursing through the destructor chain. |
613 | | ~wasm_ref_base_t() noexcept = default; |
614 | 0 | void decrease_ref() noexcept { |
615 | 0 | store->allocmgr.unlink<C>(static_cast<C *>(inner)); |
616 | 0 | } Unexecuted instantiation: wasm_ref_base_t<wasm_ref_t>::decrease_ref() Unexecuted instantiation: wasm_ref_base_t<wasm_trap_t>::decrease_ref() Unexecuted instantiation: wasm_ref_base_t<wasm_foreign_t>::decrease_ref() Unexecuted instantiation: wasm_ref_base_t<wasm_module_t>::decrease_ref() Unexecuted instantiation: wasm_ref_base_t<wasm_func_t>::decrease_ref() Unexecuted instantiation: wasm_ref_base_t<wasm_global_t>::decrease_ref() Unexecuted instantiation: wasm_ref_base_t<wasm_table_t>::decrease_ref() Unexecuted instantiation: wasm_ref_base_t<wasm_memory_t>::decrease_ref() Unexecuted instantiation: wasm_ref_base_t<wasm_extern_t>::decrease_ref() Unexecuted instantiation: wasm_ref_base_t<wasm_instance_t>::decrease_ref() |
617 | 0 | void increase_ref() const noexcept { |
618 | 0 | store->allocmgr.link<C>(static_cast<C *>(inner)); |
619 | 0 | } Unexecuted instantiation: wasm_ref_base_t<wasm_trap_t>::increase_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_module_t>::increase_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_func_t>::increase_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_foreign_t>::increase_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_global_t>::increase_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_table_t>::increase_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_memory_t>::increase_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_instance_t>::increase_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_ref_t>::increase_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_extern_t>::increase_ref() const |
620 | 0 | wasm::own<C> copy_ref() const noexcept { |
621 | 0 | increase_ref(); |
622 | 0 | return wasm::make_own<C>(static_cast<C *>(inner)); |
623 | 0 | } Unexecuted instantiation: wasm_ref_base_t<wasm_ref_t>::copy_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_trap_t>::copy_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_foreign_t>::copy_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_module_t>::copy_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_func_t>::copy_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_global_t>::copy_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_table_t>::copy_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_memory_t>::copy_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_extern_t>::copy_ref() const Unexecuted instantiation: wasm_ref_base_t<wasm_instance_t>::copy_ref() const |
624 | | |
625 | | wasm_store_t *store; |
626 | | wasm_category_enum category; |
627 | | void *inner; |
628 | | void *info; |
629 | | void (*finalizer)(void *); |
630 | | }; |
631 | | |
632 | | // wasm_ref_t implementation. wasm::X is the first base (EBO'd to size 0) |
633 | | // in every ref-bearing concrete type, so wasm_ref_base_t<C> lands at offset 0. |
634 | | struct wasm_ref_t : public wasm::Ref, public wasm_ref_base_t<wasm_ref_t> { |
635 | | wasm_ref_t() = delete; |
636 | | }; |
637 | | |
638 | | // wasm_frame_t implementation. funcoff / moduleoff are kept for the spec |
639 | | // API surface but stay 0 until the engine exposes address-map info. |
640 | | struct wasm_frame_t : public wasm::Frame { |
641 | | explicit wasm_frame_t(uint32_t idx) noexcept |
642 | 0 | : funcidx(idx), funcoff(0), moduleoff(0) {} |
643 | | wasm_frame_t(const wasm_frame_t &) noexcept = default; |
644 | | wasm_frame_t &operator=(const wasm_frame_t &) noexcept = default; |
645 | | uint32_t funcidx; |
646 | | size_t funcoff; |
647 | | size_t moduleoff; |
648 | | }; |
649 | | |
650 | | // wasm_trap_t implementation. morigin holds the outermost called funcidx; |
651 | | // deeper frames and offsets are unavailable from the engine. |
652 | | struct wasm_trap_t : public wasm::Trap, wasm_ref_base_t<wasm_trap_t> { |
653 | | wasm_trap_t(wasm::Store *s, wasm::Message &&m, |
654 | | wasm_frame_t origin = wasm_frame_t(0)) noexcept |
655 | 0 | : wasm_ref_base_t<wasm_trap_t>(s), mmsg(std::move(m)), morigin(origin) {} |
656 | | wasm::Message mmsg; |
657 | | wasm_frame_t morigin; |
658 | | }; |
659 | | |
660 | | // wasm_foreign_t implementation. |
661 | | // TODO: the foreign object is not supported yet. |
662 | | struct wasm_foreign_t : public wasm::Foreign, wasm_ref_base_t<wasm_foreign_t> { |
663 | | wasm_foreign_t(wasm::Store *s) noexcept |
664 | 0 | : wasm_ref_base_t<wasm_foreign_t>(s) {} |
665 | | }; |
666 | | |
667 | | // wasm_module_t implementation. |
668 | | struct wasm_module_t : public wasm::Module, wasm_ref_base_t<wasm_module_t> { |
669 | | wasm_module_t(wasm::Store *s, std::unique_ptr<WasmEdge::AST::Module> &&mod, |
670 | | wasm::vec<byte_t> &&bin) noexcept |
671 | 0 | : wasm_ref_base_t<wasm_module_t>(s), ast(std::move(mod)), |
672 | 0 | binary(std::move(bin)) {} |
673 | | std::unique_ptr<WasmEdge::AST::Module> ast; |
674 | | wasm::vec<byte_t> binary; |
675 | | }; |
676 | | |
677 | | // wasm_shared_module_t implementation. |
678 | | struct wasm_shared_module_t : public wasm::Shared<wasm::Module> { |
679 | | // Currently, the shared object is only used in modules. |
680 | | // Therefore we can use the serialize/deserialize mechanism to share and |
681 | | // obtain the object here. If there are other types of shared objects in the |
682 | | // future, the implementations should be updated. |
683 | | wasm_shared_module_t(wasm::vec<byte_t> &&bin) noexcept |
684 | 0 | : binary(std::move(bin)) {} |
685 | | wasm::vec<byte_t> binary; |
686 | | }; |
687 | | |
688 | | // wasm_extern_t implementation. Never instantiated; only a layout shim so |
689 | | // static_cast from wasm::Extern * finds mkind at the same offset as the |
690 | | // other wasm_X_t extern types. |
691 | | struct wasm_extern_t : public wasm::Extern, |
692 | | public wasm_ref_base_t<wasm_extern_t> { |
693 | | const wasm::ExternKind mkind; |
694 | | wasm_extern_t() = delete; |
695 | | }; |
696 | | |
697 | | // wasm_func_t implementation. |
698 | | struct wasm_func_t : public wasm::Func, public wasm_ref_base_t<wasm_func_t> { |
699 | | wasm_func_t(wasm::Store *s, const wasm::FuncType &ft, |
700 | | wasm_func_callback_t cb) noexcept |
701 | 0 | : wasm_ref_base_t<wasm_func_t>(s), owned(true) { |
702 | 0 | inst = new WasmEdge::Runtime::Instance::FunctionInstance( |
703 | 0 | std::make_unique<wasm_hostfunc_t>(ft, cb)); |
704 | 0 | } |
705 | | wasm_func_t(wasm::Store *s, const wasm::FuncType &ft, |
706 | | wasm_func_callback_with_env_t cb, void *env, |
707 | | void (*fin)(void *)) noexcept |
708 | 0 | : wasm_ref_base_t<wasm_func_t>(s), owned(true) { |
709 | 0 | inst = new WasmEdge::Runtime::Instance::FunctionInstance( |
710 | 0 | std::make_unique<wasm_hostfunc_t>(ft, cb, env, fin)); |
711 | 0 | } |
712 | | wasm_func_t(wasm::Store *s, const wasm::FuncType &ft, |
713 | | wasm::Func::callback cb) noexcept |
714 | 0 | : wasm_ref_base_t<wasm_func_t>(s), owned(true) { |
715 | 0 | inst = new WasmEdge::Runtime::Instance::FunctionInstance( |
716 | 0 | std::make_unique<wasm_hostfunc_t>(ft, cb)); |
717 | 0 | } |
718 | | wasm_func_t(wasm::Store *s, const wasm::FuncType &ft, |
719 | | wasm::Func::callback_with_env cb, void *env, |
720 | | void (*fin)(void *)) noexcept |
721 | 0 | : wasm_ref_base_t<wasm_func_t>(s), owned(true) { |
722 | 0 | inst = new WasmEdge::Runtime::Instance::FunctionInstance( |
723 | 0 | std::make_unique<wasm_hostfunc_t>(ft, cb, env, fin)); |
724 | 0 | } |
725 | | // Non-owning view (for wasm_instance_exports / wasm_table_get funcref). |
726 | | wasm_func_t(wasm::Store *s, |
727 | | WasmEdge::Runtime::Instance::FunctionInstance *fi) noexcept |
728 | 0 | : wasm_ref_base_t<wasm_func_t>(s), owned(false) { |
729 | 0 | inst = fi; |
730 | 0 | } |
731 | 0 | ~wasm_func_t() { |
732 | 0 | if (owned && inst) { |
733 | 0 | delete inst; |
734 | 0 | } |
735 | 0 | } |
736 | | const wasm::ExternKind mkind = wasm::ExternKind::FUNC; |
737 | | bool owned; |
738 | | WasmEdge::Runtime::Instance::FunctionInstance *inst; |
739 | | }; |
740 | | |
741 | | // wasm_global_t implementation. |
742 | | struct wasm_global_t : public wasm::Global, |
743 | | public wasm_ref_base_t<wasm_global_t> { |
744 | | // Owning ctor (wasm_global_new). |
745 | | wasm_global_t(wasm::Store *s, const wasm::GlobalType >, |
746 | | const wasm::Val &v) noexcept |
747 | 0 | : wasm_ref_base_t<wasm_global_t>(s), owned(true), keepval(v.copy()), |
748 | 0 | inst(new WasmEdge::Runtime::Instance::GlobalInstance( |
749 | 0 | WasmEdge::AST::GlobalType( |
750 | 0 | conv_valtype_to_wasmedge(gt.content()->kind()), |
751 | 0 | conv_valmut_to_wasmedge(gt.mutability())), |
752 | 0 | conv_cppval_to_wasmedge(v))) {} |
753 | | // Non-owning view (wasm_instance_exports). |
754 | | wasm_global_t(wasm::Store *s, |
755 | | WasmEdge::Runtime::Instance::GlobalInstance *gi) noexcept |
756 | 0 | : wasm_ref_base_t<wasm_global_t>(s), owned(false), inst(gi) {} |
757 | 0 | ~wasm_global_t() { |
758 | 0 | if (owned && inst) { |
759 | 0 | delete inst; |
760 | 0 | } |
761 | 0 | } |
762 | | const wasm::ExternKind mkind = wasm::ExternKind::GLOBAL; |
763 | | bool owned; |
764 | | // Copy the init val to keep the reference if the valtype is a ref. |
765 | | wasm::Val keepval; |
766 | | WasmEdge::Runtime::Instance::GlobalInstance *inst; |
767 | | }; |
768 | | |
769 | | // wasm_table_t implementation. |
770 | | struct wasm_table_t : public wasm::Table, public wasm_ref_base_t<wasm_table_t> { |
771 | | // Owning ctor (wasm_table_new). |
772 | | wasm_table_t(wasm::Store *s, const wasm::TableType &tt, |
773 | | const wasm::Ref *r) noexcept |
774 | 0 | : wasm_ref_base_t<wasm_table_t>(s), owned(true), |
775 | 0 | inst(new WasmEdge::Runtime::Instance::TableInstance( |
776 | 0 | WasmEdge::AST::TableType( |
777 | 0 | conv_reftype_to_wasmedge(tt.element()->kind()), tt.limits().min, |
778 | 0 | tt.limits().max))) { |
779 | 0 | if (inst->getTableType().getRefType().isFuncRefType()) { |
780 | 0 | if (r && static_cast<const wasm_ref_t *>(r)->category == |
781 | 0 | wasm_category_enum::FUNC) { |
782 | 0 | inst->fillRefs( |
783 | 0 | WasmEdge::RefVariant(static_cast<const wasm_func_t *>(r)->inst), 0, |
784 | 0 | inst->getSize()); |
785 | 0 | } else { |
786 | 0 | inst->fillRefs(WasmEdge::RefVariant( |
787 | 0 | WasmEdge::ValType(WasmEdge::TypeCode::FuncRef)), |
788 | 0 | 0, inst->getSize()); |
789 | 0 | } |
790 | 0 | } else { |
791 | 0 | inst->fillRefs(WasmEdge::RefVariant(const_cast<wasm::Ref *>(r)), 0, |
792 | 0 | inst->getSize()); |
793 | 0 | } |
794 | 0 | } |
795 | | // Non-owning view (wasm_instance_exports). |
796 | | wasm_table_t(wasm::Store *s, |
797 | | WasmEdge::Runtime::Instance::TableInstance *ti) noexcept |
798 | 0 | : wasm_ref_base_t<wasm_table_t>(s), owned(false), inst(ti) {} |
799 | 0 | ~wasm_table_t() { |
800 | 0 | if (owned && inst) { |
801 | 0 | delete inst; |
802 | 0 | } |
803 | 0 | } |
804 | | const wasm::ExternKind mkind = wasm::ExternKind::TABLE; |
805 | | bool owned; |
806 | | WasmEdge::Runtime::Instance::TableInstance *inst; |
807 | | }; |
808 | | |
809 | | // wasm_memory_t implementation. |
810 | | struct wasm_memory_t : public wasm::Memory, |
811 | | public wasm_ref_base_t<wasm_memory_t> { |
812 | | // Owning ctor (wasm_memory_new). |
813 | | wasm_memory_t(wasm::Store *s, const wasm::MemoryType &mt) noexcept |
814 | 0 | : wasm_ref_base_t<wasm_memory_t>(s), owned(true), |
815 | 0 | inst(new WasmEdge::Runtime::Instance::MemoryInstance( |
816 | 0 | WasmEdge::AST::MemoryType(mt.limits().min, mt.limits().max))) {} |
817 | | // Non-owning view (wasm_instance_exports). |
818 | | wasm_memory_t(wasm::Store *s, |
819 | | WasmEdge::Runtime::Instance::MemoryInstance *mi) noexcept |
820 | 0 | : wasm_ref_base_t<wasm_memory_t>(s), owned(false), inst(mi) {} |
821 | 0 | ~wasm_memory_t() { |
822 | 0 | if (owned && inst) { |
823 | 0 | delete inst; |
824 | 0 | } |
825 | 0 | } |
826 | | const wasm::ExternKind mkind = wasm::ExternKind::MEMORY; |
827 | | bool owned; |
828 | | WasmEdge::Runtime::Instance::MemoryInstance *inst; |
829 | | }; |
830 | | |
831 | | // wasm_instance_t implementation. |
832 | | struct wasm_instance_t : public wasm::Instance, |
833 | | wasm_ref_base_t<wasm_instance_t> { |
834 | | // Captures export order at instantiation (ModuleInstance maps sort by name). |
835 | | struct export_entry_t { |
836 | | std::string name; |
837 | | WasmEdge::ExternalType kind; |
838 | | }; |
839 | | wasm_instance_t( |
840 | | wasm::Store *s, |
841 | | std::unique_ptr<WasmEdge::Runtime::Instance::ModuleInstance> &&mi, |
842 | | std::vector<std::unique_ptr<wasm_import_module_t>> &&imps, |
843 | | std::vector<wasm::own<wasm::Extern>> &&retained, |
844 | | std::vector<export_entry_t> &&exps) noexcept |
845 | 0 | : wasm_ref_base_t<wasm_instance_t>(s), exportorder(std::move(exps)), |
846 | 0 | retainedImports(std::move(retained)), importmods(std::move(imps)), |
847 | 0 | modinst(std::move(mi)) {} |
848 | | std::vector<export_entry_t> exportorder; |
849 | | // Keep host-provided imports alive for the instance's lifetime. |
850 | | std::vector<wasm::own<wasm::Extern>> retainedImports; |
851 | | std::vector<std::unique_ptr<wasm_import_module_t>> importmods; |
852 | | std::unique_ptr<WasmEdge::Runtime::Instance::ModuleInstance> modinst; |
853 | | }; |
854 | | |
855 | | namespace { |
856 | | |
857 | | // Reverse-lookup funcidx within fi's owning module; 0 if fi is a host |
858 | | // function with no owner module or otherwise unresolvable. |
859 | | uint32_t |
860 | 0 | lookupFuncIdx(const WasmEdge::Runtime::Instance::FunctionInstance *fi) { |
861 | 0 | if (!fi) { |
862 | 0 | return 0; |
863 | 0 | } |
864 | 0 | const auto *mi = fi->getModule(); |
865 | 0 | if (!mi) { |
866 | 0 | return 0; |
867 | 0 | } |
868 | 0 | auto funcs = mi->getFunctionInstances(); |
869 | 0 | for (uint32_t i = 0; i < funcs.size(); ++i) { |
870 | 0 | if (funcs[i] == fi) { |
871 | 0 | return i; |
872 | 0 | } |
873 | 0 | } |
874 | 0 | return 0; |
875 | 0 | } |
876 | | |
877 | | wasm::own<wasm::Trap> buildTrap(wasm::Store *store, |
878 | | const WasmEdge::ErrCode &code, |
879 | 0 | uint32_t originFuncIdx = 0) { |
880 | 0 | auto msg = wasm::Message::make_nt( |
881 | 0 | fmt::format("{} failed: {}, Code: 0x{:03x}", code.getErrCodePhase(), |
882 | 0 | WasmEdge::ErrCodeStr[code.getEnum()], code.getCode())); |
883 | 0 | return wasm::make_own(new (std::nothrow) wasm_trap_t( |
884 | 0 | store, std::move(msg), wasm_frame_t(originFuncIdx))); |
885 | 0 | } |
886 | | |
887 | | // Global variables to prevent from new/delete. |
888 | | wasm_valtype_t wasm_valtype_i32(wasm::ValKind::I32); |
889 | | wasm_valtype_t wasm_valtype_i64(wasm::ValKind::I64); |
890 | | wasm_valtype_t wasm_valtype_f32(wasm::ValKind::F32); |
891 | | wasm_valtype_t wasm_valtype_f64(wasm::ValKind::F64); |
892 | | wasm_valtype_t wasm_valtype_externref(wasm::ValKind::EXTERNREF); |
893 | | wasm_valtype_t wasm_valtype_funcref(wasm::ValKind::FUNCREF); |
894 | | |
895 | | // Helper macro for the C APIs to get attributtes. |
896 | | #define WASM_DECLARE_C_GET_ATTR(name, target, attr, cast_type, def_val, \ |
897 | | is_ref, is_const) \ |
898 | | WASMEDGE_CAPI_EXPORT is_const target wasm_##name##_##attr( \ |
899 | 0 | const wasm_##name##_t *ptr) { \ |
900 | 0 | if (ptr) { \ |
901 | 0 | return cast_type##_cast<is_const target>(is_ref(ptr->attr())); \ |
902 | 0 | } \ |
903 | 0 | return def_val; \ |
904 | 0 | } Unexecuted instantiation: wasm_valtype_kind Unexecuted instantiation: wasm_functype_params Unexecuted instantiation: wasm_functype_results Unexecuted instantiation: wasm_globaltype_content Unexecuted instantiation: wasm_globaltype_mutability Unexecuted instantiation: wasm_tabletype_element Unexecuted instantiation: wasm_tabletype_limits Unexecuted instantiation: wasm_memorytype_limits Unexecuted instantiation: wasm_tagtype_functype Unexecuted instantiation: wasm_externtype_kind Unexecuted instantiation: wasm_importtype_module Unexecuted instantiation: wasm_importtype_name Unexecuted instantiation: wasm_importtype_type Unexecuted instantiation: wasm_exporttype_name Unexecuted instantiation: wasm_exporttype_type Unexecuted instantiation: wasm_frame_instance Unexecuted instantiation: wasm_frame_func_index Unexecuted instantiation: wasm_frame_func_offset Unexecuted instantiation: wasm_frame_module_offset Unexecuted instantiation: wasm_func_param_arity Unexecuted instantiation: wasm_func_result_arity Unexecuted instantiation: wasm_table_size Unexecuted instantiation: wasm_memory_data_size Unexecuted instantiation: wasm_memory_size Unexecuted instantiation: wasm_extern_kind |
905 | | |
906 | | // Helper macro for the WASM_DECLARE_OWN implementation. |
907 | | #define WASM_DECLARE_OWN_IMPL(name, Name) \ |
908 | 0 | WASMEDGE_CAPI_EXPORT void wasm_##name##_delete(OWN wasm_##name##_t *obj) { \ |
909 | 0 | wasm::own<Name> ptr(obj); \ |
910 | 0 | } Unexecuted instantiation: wasm_config_delete Unexecuted instantiation: wasm_engine_delete Unexecuted instantiation: wasm_store_delete Unexecuted instantiation: wasm_valtype_delete Unexecuted instantiation: wasm_functype_delete Unexecuted instantiation: wasm_globaltype_delete Unexecuted instantiation: wasm_tabletype_delete Unexecuted instantiation: wasm_memorytype_delete Unexecuted instantiation: wasm_tagtype_delete Unexecuted instantiation: wasm_externtype_delete Unexecuted instantiation: wasm_importtype_delete Unexecuted instantiation: wasm_exporttype_delete Unexecuted instantiation: wasm_ref_delete Unexecuted instantiation: wasm_frame_delete Unexecuted instantiation: wasm_trap_delete Unexecuted instantiation: wasm_foreign_delete Unexecuted instantiation: wasm_module_delete Unexecuted instantiation: wasm_shared_module_delete Unexecuted instantiation: wasm_func_delete Unexecuted instantiation: wasm_global_delete Unexecuted instantiation: wasm_table_delete Unexecuted instantiation: wasm_memory_delete Unexecuted instantiation: wasm_extern_delete Unexecuted instantiation: wasm_instance_delete |
911 | | |
912 | | // Helper macro for the base of WASM_DECLARE_VEC implementation. |
913 | | #define WASM_DECLARE_VEC_BASE_IMPL(name, Name, ownvec, vec, ptr) \ |
914 | | WASMEDGE_CAPI_EXPORT void wasm_##name##_vec_new_uninitialized( \ |
915 | 0 | OWN wasm_##name##_vec_t *out, size_t size) { \ |
916 | 0 | if (out) { \ |
917 | 0 | if (size < UINT32_MAX) { \ |
918 | 0 | auto v = ownvec<Name>::make_uninitialized(size); \ |
919 | 0 | out->size = v.size(); \ |
920 | 0 | out->data = reinterpret_cast<wasm_##name##_t ptr *>(v.release()); \ |
921 | 0 | } else { \ |
922 | 0 | out->size = 0; \ |
923 | 0 | out->data = nullptr; \ |
924 | 0 | } \ |
925 | 0 | } \ |
926 | 0 | } \ |
927 | | WASMEDGE_CAPI_EXPORT void wasm_##name##_vec_new_empty( \ |
928 | 0 | OWN wasm_##name##_vec_t *out) { \ |
929 | 0 | wasm_##name##_vec_new_uninitialized(out, 0); \ |
930 | 0 | } \ Unexecuted instantiation: wasm_byte_vec_new_empty Unexecuted instantiation: wasm_valtype_vec_new_empty Unexecuted instantiation: wasm_functype_vec_new_empty Unexecuted instantiation: wasm_globaltype_vec_new_empty Unexecuted instantiation: wasm_tabletype_vec_new_empty Unexecuted instantiation: wasm_memorytype_vec_new_empty Unexecuted instantiation: wasm_tagtype_vec_new_empty Unexecuted instantiation: wasm_externtype_vec_new_empty Unexecuted instantiation: wasm_importtype_vec_new_empty Unexecuted instantiation: wasm_exporttype_vec_new_empty Unexecuted instantiation: wasm_val_vec_new_empty Unexecuted instantiation: wasm_frame_vec_new_empty Unexecuted instantiation: wasm_extern_vec_new_empty |
931 | | WASMEDGE_CAPI_EXPORT void wasm_##name##_vec_delete( \ |
932 | 0 | OWN wasm_##name##_vec_t *v) { \ |
933 | 0 | if (v) { \ |
934 | 0 | ownvec<Name>::adopt( \ |
935 | 0 | v->size, reinterpret_cast<ownvec<Name>::elem_type *>(v->data)); \ |
936 | 0 | v->size = 0; \ |
937 | 0 | v->data = nullptr; \ |
938 | 0 | } \ |
939 | 0 | } Unexecuted instantiation: wasm_byte_vec_delete Unexecuted instantiation: wasm_valtype_vec_delete Unexecuted instantiation: wasm_functype_vec_delete Unexecuted instantiation: wasm_globaltype_vec_delete Unexecuted instantiation: wasm_tabletype_vec_delete Unexecuted instantiation: wasm_memorytype_vec_delete Unexecuted instantiation: wasm_tagtype_vec_delete Unexecuted instantiation: wasm_externtype_vec_delete Unexecuted instantiation: wasm_importtype_vec_delete Unexecuted instantiation: wasm_exporttype_vec_delete Unexecuted instantiation: wasm_val_vec_delete Unexecuted instantiation: wasm_frame_vec_delete Unexecuted instantiation: wasm_extern_vec_delete |
940 | | |
941 | | // Helper macro for the parts of WASM_DECLARE_VEC implementation. |
942 | | #define WASM_DECLARE_VEC_SCALAR_IMPL(name, Name) \ |
943 | | WASM_DECLARE_VEC_BASE_IMPL(name, Name, wasm::vec, wasm::vec, ) \ |
944 | | WASMEDGE_CAPI_EXPORT void wasm_##name##_vec_new( \ |
945 | | OWN wasm_##name##_vec_t *out, size_t size, \ |
946 | 0 | OWN wasm_##name##_t const vals[]) { \ |
947 | 0 | if (out) { \ |
948 | 0 | *out = {0, nullptr}; \ |
949 | 0 | if (size < UINT32_MAX) { \ |
950 | 0 | auto v = wasm::vec<Name>::make_uninitialized(size); \ |
951 | 0 | if (v.size() > 0) { \ |
952 | 0 | std::copy_n(vals, size, v.get()); \ |
953 | 0 | } \ |
954 | 0 | *out = {v.size(), reinterpret_cast<wasm_##name##_t *>(v.release())}; \ |
955 | 0 | } \ |
956 | 0 | } \ |
957 | 0 | } \ |
958 | | WASMEDGE_CAPI_EXPORT void wasm_##name##_vec_copy( \ |
959 | 0 | OWN wasm_##name##_vec_t *out, const wasm_##name##_vec_t *in) { \ |
960 | 0 | if (out) { \ |
961 | 0 | *out = {0, nullptr}; \ |
962 | 0 | } \ |
963 | 0 | if (in && out) { \ |
964 | 0 | wasm_##name##_vec_new(out, in->size, in->data); \ |
965 | 0 | } \ |
966 | 0 | } |
967 | | |
968 | | // Helper macro for the parts of WASM_DECLARE_VEC implementation. |
969 | | #define WASM_DECLARE_VEC_PTR_IMPL(name, Name) \ |
970 | | WASM_DECLARE_VEC_BASE_IMPL(name, Name, wasm::ownvec, wasm::vec, *) \ |
971 | | WASMEDGE_CAPI_EXPORT void wasm_##name##_vec_new( \ |
972 | | OWN wasm_##name##_vec_t *out, size_t size, \ |
973 | 0 | OWN wasm_##name##_t *const data[]) { \ |
974 | 0 | if (out) { \ |
975 | 0 | *out = {0, nullptr}; \ |
976 | 0 | if (size < UINT32_MAX) { \ |
977 | 0 | auto v = wasm::ownvec<Name>::make_uninitialized(size); \ |
978 | 0 | for (size_t i = 0; i < v.size(); ++i) { \ |
979 | 0 | v[i] = wasm::make_own(data[i]); \ |
980 | 0 | } \ |
981 | 0 | *out = {v.size(), reinterpret_cast<wasm_##name##_t **>(v.release())}; \ |
982 | 0 | } \ |
983 | 0 | } \ |
984 | 0 | } \ |
985 | | WASMEDGE_CAPI_EXPORT void wasm_##name##_vec_copy( \ |
986 | 0 | OWN wasm_##name##_vec_t *out, const wasm_##name##_vec_t *in) { \ |
987 | 0 | if (out) { \ |
988 | 0 | *out = {0, nullptr}; \ |
989 | 0 | } \ |
990 | 0 | if (in && out && in->size < UINT32_MAX) { \ |
991 | 0 | auto v = wasm::ownvec<Name>::make_uninitialized(in->size); \ |
992 | 0 | for (size_t i = 0; i < v.size(); ++i) { \ |
993 | 0 | v[i] = wasm::make_own(wasm_##name##_copy(in->data[i])); \ |
994 | 0 | } \ |
995 | 0 | *out = {v.size(), reinterpret_cast<wasm_##name##_t **>(v.release())}; \ |
996 | 0 | } \ |
997 | 0 | } |
998 | | |
999 | | // Helper macro for the WASM_DECLARE_TYPE implementation. |
1000 | | #define WASM_DECLARE_TYPE_IMPL(name, Name) \ |
1001 | | WASM_DECLARE_OWN_IMPL(name, Name) \ |
1002 | | WASM_DECLARE_VEC_PTR_IMPL(name, Name) \ |
1003 | | WASMEDGE_CAPI_EXPORT wasm_##name##_t OWN *wasm_##name##_copy( \ |
1004 | 0 | const wasm_##name##_t *inst) { \ |
1005 | 0 | if (inst) { \ |
1006 | 0 | return static_cast<wasm_##name##_t *>((inst->copy()).release()); \ |
1007 | 0 | } \ |
1008 | 0 | return nullptr; \ |
1009 | 0 | } Unexecuted instantiation: wasm_valtype_copy Unexecuted instantiation: wasm_functype_copy Unexecuted instantiation: wasm_globaltype_copy Unexecuted instantiation: wasm_tabletype_copy Unexecuted instantiation: wasm_memorytype_copy Unexecuted instantiation: wasm_tagtype_copy Unexecuted instantiation: wasm_externtype_copy Unexecuted instantiation: wasm_importtype_copy Unexecuted instantiation: wasm_exporttype_copy |
1010 | | |
1011 | | // Helper macro for the base of WASM_DECLARE_REF implementation. |
1012 | | #define WASM_DECLARE_REF_BASE_IMPL(name, Name) \ |
1013 | | WASM_DECLARE_OWN_IMPL(name, Name) \ |
1014 | | WASMEDGE_CAPI_EXPORT OWN wasm_##name##_t *wasm_##name##_copy( \ |
1015 | 0 | const wasm_##name##_t *t) { \ |
1016 | 0 | return static_cast<wasm_##name##_t *>(t->copy().release()); \ |
1017 | 0 | } \ Unexecuted instantiation: wasm_ref_copy Unexecuted instantiation: wasm_trap_copy Unexecuted instantiation: wasm_foreign_copy Unexecuted instantiation: wasm_module_copy Unexecuted instantiation: wasm_func_copy Unexecuted instantiation: wasm_global_copy Unexecuted instantiation: wasm_table_copy Unexecuted instantiation: wasm_memory_copy Unexecuted instantiation: wasm_extern_copy Unexecuted instantiation: wasm_instance_copy |
1018 | | WASMEDGE_CAPI_EXPORT bool wasm_##name##_same(const wasm_##name##_t *t1, \ |
1019 | 0 | const wasm_##name##_t *t2) { \ |
1020 | 0 | return t1->same(t2); \ |
1021 | 0 | } \ Unexecuted instantiation: wasm_ref_same Unexecuted instantiation: wasm_trap_same Unexecuted instantiation: wasm_foreign_same Unexecuted instantiation: wasm_module_same Unexecuted instantiation: wasm_func_same Unexecuted instantiation: wasm_global_same Unexecuted instantiation: wasm_table_same Unexecuted instantiation: wasm_memory_same Unexecuted instantiation: wasm_extern_same Unexecuted instantiation: wasm_instance_same |
1022 | | WASMEDGE_CAPI_EXPORT void *wasm_##name##_get_host_info( \ |
1023 | 0 | const wasm_##name##_t *r) { \ |
1024 | 0 | return r->get_host_info(); \ |
1025 | 0 | } \ Unexecuted instantiation: wasm_ref_get_host_info Unexecuted instantiation: wasm_trap_get_host_info Unexecuted instantiation: wasm_foreign_get_host_info Unexecuted instantiation: wasm_module_get_host_info Unexecuted instantiation: wasm_func_get_host_info Unexecuted instantiation: wasm_global_get_host_info Unexecuted instantiation: wasm_table_get_host_info Unexecuted instantiation: wasm_memory_get_host_info Unexecuted instantiation: wasm_extern_get_host_info Unexecuted instantiation: wasm_instance_get_host_info |
1026 | | WASMEDGE_CAPI_EXPORT void wasm_##name##_set_host_info(wasm_##name##_t *r, \ |
1027 | 0 | void *info) { \ |
1028 | 0 | r->set_host_info(info); \ |
1029 | 0 | } \ Unexecuted instantiation: wasm_ref_set_host_info Unexecuted instantiation: wasm_trap_set_host_info Unexecuted instantiation: wasm_foreign_set_host_info Unexecuted instantiation: wasm_module_set_host_info Unexecuted instantiation: wasm_func_set_host_info Unexecuted instantiation: wasm_global_set_host_info Unexecuted instantiation: wasm_table_set_host_info Unexecuted instantiation: wasm_memory_set_host_info Unexecuted instantiation: wasm_extern_set_host_info Unexecuted instantiation: wasm_instance_set_host_info |
1030 | | WASMEDGE_CAPI_EXPORT void wasm_##name##_set_host_info_with_finalizer( \ |
1031 | 0 | wasm_##name##_t *r, void *info, void (*finalizer)(void *)) { \ |
1032 | 0 | r->set_host_info(info, finalizer); \ |
1033 | 0 | } Unexecuted instantiation: wasm_ref_set_host_info_with_finalizer Unexecuted instantiation: wasm_trap_set_host_info_with_finalizer Unexecuted instantiation: wasm_foreign_set_host_info_with_finalizer Unexecuted instantiation: wasm_module_set_host_info_with_finalizer Unexecuted instantiation: wasm_func_set_host_info_with_finalizer Unexecuted instantiation: wasm_global_set_host_info_with_finalizer Unexecuted instantiation: wasm_table_set_host_info_with_finalizer Unexecuted instantiation: wasm_memory_set_host_info_with_finalizer Unexecuted instantiation: wasm_extern_set_host_info_with_finalizer Unexecuted instantiation: wasm_instance_set_host_info_with_finalizer |
1034 | | |
1035 | | // Helper macro for the WASM_DECLARE_REF implementation. |
1036 | | #define WASM_DECLARE_REF_IMPL(name, Name) \ |
1037 | | WASM_DECLARE_REF_BASE_IMPL(name, Name) \ |
1038 | 0 | WASMEDGE_CAPI_EXPORT wasm_ref_t *wasm_##name##_as_ref(wasm_##name##_t *r) { \ |
1039 | 0 | return static_cast<wasm_ref_t *>( \ |
1040 | 0 | static_cast<wasm::Ref *>(static_cast<Name *>(r))); \ |
1041 | 0 | } \ Unexecuted instantiation: wasm_trap_as_ref Unexecuted instantiation: wasm_foreign_as_ref Unexecuted instantiation: wasm_module_as_ref Unexecuted instantiation: wasm_func_as_ref Unexecuted instantiation: wasm_global_as_ref Unexecuted instantiation: wasm_table_as_ref Unexecuted instantiation: wasm_memory_as_ref Unexecuted instantiation: wasm_extern_as_ref Unexecuted instantiation: wasm_instance_as_ref |
1042 | 0 | WASMEDGE_CAPI_EXPORT wasm_##name##_t *wasm_ref_as_##name(wasm_ref_t *r) { \ |
1043 | 0 | return static_cast<wasm_##name##_t *>( \ |
1044 | 0 | static_cast<Name *>(static_cast<wasm::Ref *>(r))); \ |
1045 | 0 | } \ Unexecuted instantiation: wasm_ref_as_trap Unexecuted instantiation: wasm_ref_as_foreign Unexecuted instantiation: wasm_ref_as_module Unexecuted instantiation: wasm_ref_as_func Unexecuted instantiation: wasm_ref_as_global Unexecuted instantiation: wasm_ref_as_table Unexecuted instantiation: wasm_ref_as_memory Unexecuted instantiation: wasm_ref_as_extern Unexecuted instantiation: wasm_ref_as_instance |
1046 | | WASMEDGE_CAPI_EXPORT const wasm_ref_t *wasm_##name##_as_ref_const( \ |
1047 | 0 | const wasm_##name##_t *r) { \ |
1048 | 0 | return static_cast<const wasm_ref_t *>( \ |
1049 | 0 | static_cast<const wasm::Ref *>(static_cast<const Name *>(r))); \ |
1050 | 0 | } \ Unexecuted instantiation: wasm_trap_as_ref_const Unexecuted instantiation: wasm_foreign_as_ref_const Unexecuted instantiation: wasm_module_as_ref_const Unexecuted instantiation: wasm_func_as_ref_const Unexecuted instantiation: wasm_global_as_ref_const Unexecuted instantiation: wasm_table_as_ref_const Unexecuted instantiation: wasm_memory_as_ref_const Unexecuted instantiation: wasm_extern_as_ref_const Unexecuted instantiation: wasm_instance_as_ref_const |
1051 | | WASMEDGE_CAPI_EXPORT const wasm_##name##_t *wasm_ref_as_##name##_const( \ |
1052 | 0 | const wasm_ref_t *r) { \ |
1053 | 0 | return static_cast<const wasm_##name##_t *>( \ |
1054 | 0 | static_cast<const Name *>(static_cast<const wasm::Ref *>(r))); \ |
1055 | 0 | } Unexecuted instantiation: wasm_ref_as_trap_const Unexecuted instantiation: wasm_ref_as_foreign_const Unexecuted instantiation: wasm_ref_as_module_const Unexecuted instantiation: wasm_ref_as_func_const Unexecuted instantiation: wasm_ref_as_global_const Unexecuted instantiation: wasm_ref_as_table_const Unexecuted instantiation: wasm_ref_as_memory_const Unexecuted instantiation: wasm_ref_as_extern_const Unexecuted instantiation: wasm_ref_as_instance_const |
1056 | | |
1057 | | // Helper macro for the WASM_DECLARE_SHARABLE_REF implementation. |
1058 | | #define WASM_DECLARE_SHARABLE_REF_IMPL(name, Name) \ |
1059 | | WASM_DECLARE_REF_IMPL(name, Name) \ |
1060 | | WASM_DECLARE_OWN_IMPL(shared_##name, wasm::Shared<wasm::Module>) |
1061 | | |
1062 | | // Helper macro for the wasm_externtype_t and wasm_extern_t conversions. |
1063 | | #define WASM_EXTERNTYPE_C_CONV(in, out, type, Type, connect, const_quant) \ |
1064 | | WASMEDGE_CAPI_EXPORT const_quant wasm_##out##type##_t * \ |
1065 | | wasm_##in##type##_as_##out##type##connect##const_quant( \ |
1066 | 0 | const_quant wasm_##in##type##_t *ptr) { \ |
1067 | 0 | return static_cast<const_quant wasm_##out##type##_t *>( \ |
1068 | 0 | static_cast<const_quant wasm::Extern##Type *>(ptr)); \ |
1069 | 0 | } Unexecuted instantiation: wasm_functype_as_externtype Unexecuted instantiation: wasm_functype_as_externtype_const Unexecuted instantiation: wasm_globaltype_as_externtype Unexecuted instantiation: wasm_globaltype_as_externtype_const Unexecuted instantiation: wasm_tabletype_as_externtype Unexecuted instantiation: wasm_tabletype_as_externtype_const Unexecuted instantiation: wasm_memorytype_as_externtype Unexecuted instantiation: wasm_memorytype_as_externtype_const Unexecuted instantiation: wasm_tagtype_as_externtype Unexecuted instantiation: wasm_tagtype_as_externtype_const Unexecuted instantiation: wasm_externtype_as_functype Unexecuted instantiation: wasm_externtype_as_functype_const Unexecuted instantiation: wasm_externtype_as_globaltype Unexecuted instantiation: wasm_externtype_as_globaltype_const Unexecuted instantiation: wasm_externtype_as_tabletype Unexecuted instantiation: wasm_externtype_as_tabletype_const Unexecuted instantiation: wasm_externtype_as_memorytype Unexecuted instantiation: wasm_externtype_as_memorytype_const Unexecuted instantiation: wasm_externtype_as_tagtype Unexecuted instantiation: wasm_externtype_as_tagtype_const Unexecuted instantiation: wasm_func_as_extern Unexecuted instantiation: wasm_func_as_extern_const Unexecuted instantiation: wasm_global_as_extern Unexecuted instantiation: wasm_global_as_extern_const Unexecuted instantiation: wasm_table_as_extern Unexecuted instantiation: wasm_table_as_extern_const Unexecuted instantiation: wasm_memory_as_extern Unexecuted instantiation: wasm_memory_as_extern_const Unexecuted instantiation: wasm_extern_as_func Unexecuted instantiation: wasm_extern_as_func_const Unexecuted instantiation: wasm_extern_as_global Unexecuted instantiation: wasm_extern_as_global_const Unexecuted instantiation: wasm_extern_as_table Unexecuted instantiation: wasm_extern_as_table_const Unexecuted instantiation: wasm_extern_as_memory Unexecuted instantiation: wasm_extern_as_memory_const |
1070 | | |
1071 | | // Helper macro for the wasm::ExternType and wasm::Extern conversions. |
1072 | | #define WASM_EXTERNTYPE_CPP_CONV(name, Name, Type, enum, const_quant) \ |
1073 | 0 | const_quant wasm::Name##Type *wasm::Extern##Type::name() const_quant { \ |
1074 | 0 | if (kind() == wasm::ExternKind::enum) { \ |
1075 | 0 | return static_cast<const_quant wasm::Name##Type *>(this); \ |
1076 | 0 | } \ |
1077 | 0 | return nullptr; \ |
1078 | 0 | } Unexecuted instantiation: wasm::ExternType::func() Unexecuted instantiation: wasm::ExternType::func() const Unexecuted instantiation: wasm::ExternType::global() Unexecuted instantiation: wasm::ExternType::global() const Unexecuted instantiation: wasm::ExternType::table() Unexecuted instantiation: wasm::ExternType::table() const Unexecuted instantiation: wasm::ExternType::memory() Unexecuted instantiation: wasm::ExternType::memory() const Unexecuted instantiation: wasm::ExternType::tag() Unexecuted instantiation: wasm::ExternType::tag() const Unexecuted instantiation: wasm::Extern::func() Unexecuted instantiation: wasm::Extern::func() const Unexecuted instantiation: wasm::Extern::global() Unexecuted instantiation: wasm::Extern::global() const Unexecuted instantiation: wasm::Extern::table() Unexecuted instantiation: wasm::Extern::table() const Unexecuted instantiation: wasm::Extern::memory() Unexecuted instantiation: wasm::Extern::memory() const |
1079 | | |
1080 | 0 | inline wasm::Val conv_val_to_cpp(const wasm_val_t &v) { |
1081 | 0 | switch (v.kind) { |
1082 | 0 | case wasm_valkind_enum::WASM_I32: |
1083 | 0 | return wasm::Val(v.of.i32); |
1084 | 0 | case wasm_valkind_enum::WASM_I64: |
1085 | 0 | return wasm::Val(v.of.i64); |
1086 | 0 | case wasm_valkind_enum::WASM_F32: |
1087 | 0 | return wasm::Val(v.of.f32); |
1088 | 0 | case wasm_valkind_enum::WASM_F64: |
1089 | 0 | return wasm::Val(v.of.f64); |
1090 | 0 | case wasm_valkind_enum::WASM_EXTERNREF: |
1091 | 0 | case wasm_valkind_enum::WASM_FUNCREF: { |
1092 | 0 | if (v.of.ref) { |
1093 | 0 | return wasm::Val(v.of.ref->copy_ref()); |
1094 | 0 | } |
1095 | 0 | return wasm::Val(); |
1096 | 0 | } |
1097 | 0 | default: |
1098 | 0 | assumingUnreachable(); |
1099 | 0 | } |
1100 | 0 | } |
1101 | | |
1102 | 0 | inline wasm_val_t conv_val_to_c(const wasm::Val &v) { |
1103 | 0 | wasm_val_t r; |
1104 | 0 | switch (v.kind()) { |
1105 | 0 | case wasm::ValKind::I32: |
1106 | 0 | r.kind = wasm_valkind_enum::WASM_I32; |
1107 | 0 | r.of.i32 = v.i32(); |
1108 | 0 | break; |
1109 | 0 | case wasm::ValKind::I64: |
1110 | 0 | r.kind = wasm_valkind_enum::WASM_I64; |
1111 | 0 | r.of.i64 = v.i64(); |
1112 | 0 | break; |
1113 | 0 | case wasm::ValKind::F32: |
1114 | 0 | r.kind = wasm_valkind_enum::WASM_F32; |
1115 | 0 | r.of.f32 = v.f32(); |
1116 | 0 | break; |
1117 | 0 | case wasm::ValKind::F64: |
1118 | 0 | r.kind = wasm_valkind_enum::WASM_F64; |
1119 | 0 | r.of.f64 = v.f64(); |
1120 | 0 | break; |
1121 | 0 | case wasm::ValKind::FUNCREF: |
1122 | 0 | r.kind = wasm_valkind_enum::WASM_FUNCREF; |
1123 | 0 | r.of.ref = static_cast<wasm_ref_t *>(v.ref()); |
1124 | 0 | break; |
1125 | 0 | case wasm::ValKind::EXTERNREF: |
1126 | 0 | r.kind = wasm_valkind_enum::WASM_EXTERNREF; |
1127 | 0 | r.of.ref = static_cast<wasm_ref_t *>(v.ref()); |
1128 | 0 | break; |
1129 | 0 | default: |
1130 | 0 | assumingUnreachable(); |
1131 | 0 | } |
1132 | 0 | return r; |
1133 | 0 | } |
1134 | | |
1135 | | // WasmEdge::ValVariant to wasm_val_t conversion. |
1136 | | wasm_val_t conv_cval_from_wasmedge(const WasmEdge::ValVariant &v, |
1137 | 0 | const WasmEdge::ValType &vt) { |
1138 | | // Note: the conversion will not add the ref count of wasm_ref_t. |
1139 | 0 | wasm_val_t r{}; |
1140 | 0 | if (vt.isNumType()) { |
1141 | 0 | switch (vt.getCode()) { |
1142 | 0 | case WasmEdge::TypeCode::I32: |
1143 | 0 | r.kind = wasm_valkind_enum::WASM_I32; |
1144 | 0 | r.of.i32 = static_cast<int32_t>(v.get<uint32_t>()); |
1145 | 0 | return r; |
1146 | 0 | case WasmEdge::TypeCode::I64: |
1147 | 0 | r.kind = wasm_valkind_enum::WASM_I64; |
1148 | 0 | r.of.i64 = static_cast<int64_t>(v.get<uint64_t>()); |
1149 | 0 | return r; |
1150 | 0 | case WasmEdge::TypeCode::F32: |
1151 | 0 | r.kind = wasm_valkind_enum::WASM_F32; |
1152 | 0 | r.of.f32 = v.get<float>(); |
1153 | 0 | return r; |
1154 | 0 | case WasmEdge::TypeCode::F64: |
1155 | 0 | r.kind = wasm_valkind_enum::WASM_F64; |
1156 | 0 | r.of.f64 = v.get<double>(); |
1157 | 0 | return r; |
1158 | 0 | default: |
1159 | 0 | break; |
1160 | 0 | } |
1161 | 0 | } else if (vt.isFuncRefType()) { |
1162 | 0 | r.kind = wasm_valkind_enum::WASM_FUNCREF; |
1163 | | // TODO: implement this |
1164 | 0 | return r; |
1165 | 0 | } else if (vt.isExternRefType()) { |
1166 | 0 | r.kind = wasm_valkind_enum::WASM_EXTERNREF; |
1167 | 0 | r.of.ref = v.get<WasmEdge::RefVariant>().getPtr<wasm_ref_t>(); |
1168 | 0 | return r; |
1169 | 0 | } |
1170 | | // v128 and other types are not supported in wasm C API yet. |
1171 | 0 | assumingUnreachable(); |
1172 | 0 | } |
1173 | | |
1174 | | // WasmEdge::ValVariant to wasm::Val conversion. |
1175 | | wasm::Val conv_cppval_from_wasmedge(const WasmEdge::ValVariant &v, |
1176 | 0 | const WasmEdge::ValType &vt) { |
1177 | | // Note: the conversion will add the ref count of wasm::Ref to make the |
1178 | | // wasm::Val. |
1179 | 0 | if (vt.isNumType()) { |
1180 | 0 | switch (vt.getCode()) { |
1181 | 0 | case WasmEdge::TypeCode::I32: |
1182 | 0 | return wasm::Val::i32(static_cast<int32_t>(v.get<uint32_t>())); |
1183 | 0 | case WasmEdge::TypeCode::I64: |
1184 | 0 | return wasm::Val::i64(static_cast<int64_t>(v.get<uint64_t>())); |
1185 | 0 | case WasmEdge::TypeCode::F32: |
1186 | 0 | return wasm::Val::f32(v.get<float>()); |
1187 | 0 | case WasmEdge::TypeCode::F64: |
1188 | 0 | return wasm::Val::f64(v.get<double>()); |
1189 | 0 | default: |
1190 | 0 | break; |
1191 | 0 | } |
1192 | 0 | } else if (vt.isFuncRefType()) { |
1193 | | // TODO: implement this |
1194 | 0 | return wasm::Val(); |
1195 | 0 | } else if (vt.isExternRefType()) { |
1196 | 0 | auto *ref = v.get<WasmEdge::RefVariant>().getPtr<wasm_ref_t>(); |
1197 | 0 | return wasm::Val::ref(ref ? ref->copy_ref() : wasm::own<wasm_ref_t>()); |
1198 | 0 | } |
1199 | | // v128 and other types are not supported in wasm C API yet. |
1200 | 0 | assumingUnreachable(); |
1201 | 0 | } |
1202 | | |
1203 | | // wasm_val_t to WasmEdge::ValVariant conversion. |
1204 | 0 | WasmEdge::ValVariant conv_cval_to_wasmedge(const wasm_val_t &v) { |
1205 | | // Note: the conversion will not transfer the ownership of wasm_ref_t*. |
1206 | 0 | switch (v.kind) { |
1207 | 0 | case wasm_valkind_enum::WASM_I32: |
1208 | 0 | return v.of.i32; |
1209 | 0 | case wasm_valkind_enum::WASM_I64: |
1210 | 0 | return v.of.i64; |
1211 | 0 | case wasm_valkind_enum::WASM_F32: |
1212 | 0 | return v.of.f32; |
1213 | 0 | case wasm_valkind_enum::WASM_F64: |
1214 | 0 | return v.of.f64; |
1215 | 0 | case wasm_valkind_enum::WASM_EXTERNREF: |
1216 | 0 | return WasmEdge::RefVariant(v.of.ref); |
1217 | 0 | case wasm_valkind_enum::WASM_FUNCREF: |
1218 | 0 | if (v.of.ref && v.of.ref->category == wasm_category_enum::FUNC) { |
1219 | 0 | return WasmEdge::RefVariant( |
1220 | 0 | static_cast<wasm_func_t *>(static_cast<wasm::Ref *>(v.of.ref))->inst); |
1221 | 0 | } else { |
1222 | 0 | return WasmEdge::RefVariant( |
1223 | 0 | WasmEdge::ValType(WasmEdge::TypeCode::FuncRef)); |
1224 | 0 | } |
1225 | 0 | default: |
1226 | 0 | assumingUnreachable(); |
1227 | 0 | } |
1228 | 0 | } |
1229 | | |
1230 | | // wasm::Val to WasmEdge::ValVariant conversion. |
1231 | 0 | WasmEdge::ValVariant conv_cppval_to_wasmedge(const wasm::Val &v) { |
1232 | | // Note: the conversion will not transfer the ownership of wasm::Ref. |
1233 | 0 | switch (v.kind()) { |
1234 | 0 | case wasm::ValKind::I32: |
1235 | 0 | return v.i32(); |
1236 | 0 | case wasm::ValKind::I64: |
1237 | 0 | return v.i64(); |
1238 | 0 | case wasm::ValKind::F32: |
1239 | 0 | return v.f32(); |
1240 | 0 | case wasm::ValKind::F64: |
1241 | 0 | return v.f64(); |
1242 | 0 | case wasm::ValKind::EXTERNREF: |
1243 | 0 | return WasmEdge::RefVariant(v.ref()); |
1244 | 0 | case wasm::ValKind::FUNCREF: { |
1245 | | // C-API funcrefs always come from wasm_func_as_ref / wasm_table_get, so |
1246 | | // ref() is a wasm::Func — recover the wasm_func_t and store its inst. |
1247 | 0 | if (v.ref()) { |
1248 | 0 | auto *cfunc = static_cast<wasm_func_t *>( |
1249 | 0 | static_cast<wasm::Func *>(static_cast<wasm::Extern *>(v.ref()))); |
1250 | 0 | return WasmEdge::RefVariant(cfunc->inst); |
1251 | 0 | } |
1252 | 0 | return WasmEdge::RefVariant(WasmEdge::ValType(WasmEdge::TypeCode::FuncRef)); |
1253 | 0 | } |
1254 | 0 | default: |
1255 | 0 | assumingUnreachable(); |
1256 | 0 | } |
1257 | 0 | } |
1258 | | |
1259 | | // allocmgr destructor backward implementation. |
1260 | | // Uses cached info/finalizer from ref_entry_t to avoid type-unsafe casts. |
1261 | 0 | wasm_allocmgr_t::~wasm_allocmgr_t() { |
1262 | 0 | for (auto &&[ptr, entry] : entries) { |
1263 | 0 | if (entry.finalizer) { |
1264 | 0 | entry.finalizer(entry.info); |
1265 | 0 | } |
1266 | 0 | entry.destroyer(ptr); |
1267 | 0 | } |
1268 | 0 | entries.clear(); |
1269 | 0 | } |
1270 | | |
1271 | | } // namespace |
1272 | | |
1273 | | // The following are the C API implementation. |
1274 | | #ifdef __cplusplus |
1275 | | extern "C" { |
1276 | | #endif |
1277 | | |
1278 | | // >>>>>>>> wasm_byte_vec_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1279 | | |
1280 | 0 | WASM_DECLARE_VEC_SCALAR_IMPL(byte, byte_t) Unexecuted instantiation: wasm_byte_vec_new_uninitialized Unexecuted instantiation: wasm_byte_vec_new |
1281 | | |
1282 | | // <<<<<<<< wasm_byte_vec_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1283 | | |
1284 | | // >>>>>>>> wasm_config_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1285 | | |
1286 | | WASM_DECLARE_OWN_IMPL(config, wasm::Config) |
1287 | | |
1288 | 0 | WASMEDGE_CAPI_EXPORT OWN wasm_config_t *wasm_config_new() { |
1289 | 0 | return new (std::nothrow) wasm_config_t; |
1290 | 0 | } |
1291 | | |
1292 | | // <<<<<<<< wasm_config_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1293 | | |
1294 | | // >>>>>>>> wasm_engine_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1295 | | |
1296 | | WASM_DECLARE_OWN_IMPL(engine, wasm::Engine) |
1297 | | |
1298 | 0 | WASMEDGE_CAPI_EXPORT OWN wasm_engine_t *wasm_engine_new() { |
1299 | 0 | return new (std::nothrow) wasm_engine_t(); |
1300 | 0 | } |
1301 | | |
1302 | | WASMEDGE_CAPI_EXPORT OWN wasm_engine_t * |
1303 | 0 | wasm_engine_new_with_config(OWN wasm_config_t *conf) { |
1304 | 0 | if (conf) { |
1305 | 0 | return new (std::nothrow) wasm_engine_t(wasm::make_own<wasm::Config>(conf)); |
1306 | 0 | } else { |
1307 | 0 | return wasm_engine_new(); |
1308 | 0 | } |
1309 | 0 | } |
1310 | | |
1311 | | // <<<<<<<< wasm_engine_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1312 | | |
1313 | | // >>>>>>>> wasm_store_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1314 | | |
1315 | | WASM_DECLARE_OWN_IMPL(store, wasm::Store) |
1316 | | |
1317 | 0 | WASMEDGE_CAPI_EXPORT OWN wasm_store_t *wasm_store_new(wasm_engine_t *engine) { |
1318 | 0 | return static_cast<wasm_store_t *>(wasm::Store::make(engine).release()); |
1319 | 0 | } |
1320 | | |
1321 | | // <<<<<<<< wasm_store_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1322 | | |
1323 | | // >>>>>>>> wasm_valtype_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1324 | | |
1325 | 0 | WASM_DECLARE_TYPE_IMPL(valtype, wasm::ValType) Unexecuted instantiation: wasm_valtype_vec_new_uninitialized Unexecuted instantiation: wasm_valtype_vec_new Unexecuted instantiation: wasm_valtype_vec_copy |
1326 | 0 |
|
1327 | 0 | WASMEDGE_CAPI_EXPORT OWN wasm_valtype_t *wasm_valtype_new(wasm_valkind_t kind) { |
1328 | | // Return the pointer to the instances. |
1329 | | // When delete the `wasm_valtype_t`, the `destroy()` function will do nothing |
1330 | | // when the unique pointer releases the pointer. |
1331 | 0 | switch (kind) { |
1332 | 0 | case WASM_I32: |
1333 | 0 | return &wasm_valtype_i32; |
1334 | 0 | case WASM_I64: |
1335 | 0 | return &wasm_valtype_i64; |
1336 | 0 | case WASM_F32: |
1337 | 0 | return &wasm_valtype_f32; |
1338 | 0 | case WASM_F64: |
1339 | 0 | return &wasm_valtype_f64; |
1340 | 0 | case WASM_EXTERNREF: |
1341 | 0 | return &wasm_valtype_externref; |
1342 | 0 | case WASM_FUNCREF: |
1343 | 0 | return &wasm_valtype_funcref; |
1344 | 0 | default: |
1345 | 0 | assumingUnreachable(); |
1346 | 0 | } |
1347 | 0 | } |
1348 | | |
1349 | | WASM_DECLARE_C_GET_ATTR(valtype, wasm_valkind_t, kind, static, WASM_I32, , ) |
1350 | | |
1351 | | // <<<<<<<< wasm_valtype_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1352 | | |
1353 | | // >>>>>>>> wasm_functype_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1354 | | |
1355 | 0 | WASM_DECLARE_TYPE_IMPL(functype, wasm::FuncType) Unexecuted instantiation: wasm_functype_vec_new_uninitialized Unexecuted instantiation: wasm_functype_vec_new Unexecuted instantiation: wasm_functype_vec_copy |
1356 | 0 |
|
1357 | 0 | WASMEDGE_CAPI_EXPORT OWN wasm_functype_t * |
1358 | 0 | wasm_functype_new(OWN wasm_valtype_vec_t *params, |
1359 | 0 | OWN wasm_valtype_vec_t *results) { |
1360 | 0 | if (params && results) { |
1361 | 0 | return new (std::nothrow) wasm_functype_t( |
1362 | 0 | wasm::ownvec<wasm::ValType>::adopt( |
1363 | 0 | params->size, |
1364 | 0 | reinterpret_cast<wasm::own<wasm::ValType> *>(params->data)), |
1365 | 0 | wasm::ownvec<wasm::ValType>::adopt( |
1366 | 0 | results->size, |
1367 | 0 | reinterpret_cast<wasm::own<wasm::ValType> *>(results->data))); |
1368 | 0 | } |
1369 | 0 | return nullptr; |
1370 | 0 | } |
1371 | | |
1372 | | WASM_DECLARE_C_GET_ATTR(functype, wasm_valtype_vec_t *, params, reinterpret, |
1373 | | nullptr, &, const) |
1374 | | WASM_DECLARE_C_GET_ATTR(functype, wasm_valtype_vec_t *, results, reinterpret, |
1375 | | nullptr, &, const) |
1376 | | |
1377 | | // <<<<<<<< wasm_functype_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1378 | | |
1379 | | // >>>>>>>> wasm_globaltype_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1380 | | |
1381 | 0 | WASM_DECLARE_TYPE_IMPL(globaltype, wasm::GlobalType) Unexecuted instantiation: wasm_globaltype_vec_new_uninitialized Unexecuted instantiation: wasm_globaltype_vec_new Unexecuted instantiation: wasm_globaltype_vec_copy |
1382 | 0 |
|
1383 | 0 | WASMEDGE_CAPI_EXPORT OWN wasm_globaltype_t * |
1384 | 0 | wasm_globaltype_new(OWN wasm_valtype_t *valtype, wasm_mutability_t mutability) { |
1385 | 0 | if (valtype) { |
1386 | 0 | return new (std::nothrow) wasm_globaltype_t( |
1387 | 0 | wasm::make_own(valtype), static_cast<wasm::Mutability>(mutability)); |
1388 | 0 | } |
1389 | 0 | return nullptr; |
1390 | 0 | } |
1391 | | |
1392 | | WASM_DECLARE_C_GET_ATTR(globaltype, wasm_valtype_t *, content, static, nullptr, |
1393 | | , const) |
1394 | | WASM_DECLARE_C_GET_ATTR(globaltype, wasm_mutability_t, mutability, static, |
1395 | | WASM_CONST, , ) |
1396 | | |
1397 | | // <<<<<<<< wasm_globaltype_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1398 | | |
1399 | | // >>>>>>>> wasm_tabletype_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1400 | | |
1401 | 0 | WASM_DECLARE_TYPE_IMPL(tabletype, wasm::TableType) Unexecuted instantiation: wasm_tabletype_vec_new_uninitialized Unexecuted instantiation: wasm_tabletype_vec_new Unexecuted instantiation: wasm_tabletype_vec_copy |
1402 | 0 |
|
1403 | 0 | WASMEDGE_CAPI_EXPORT OWN wasm_tabletype_t * |
1404 | 0 | wasm_tabletype_new(OWN wasm_valtype_t *valtype, const wasm_limits_t *limits) { |
1405 | 0 | if (valtype && limits) { |
1406 | 0 | return new (std::nothrow) wasm_tabletype_t( |
1407 | 0 | wasm::make_own(valtype), wasm::Limits(limits->min, limits->max)); |
1408 | 0 | } |
1409 | 0 | return nullptr; |
1410 | 0 | } |
1411 | | |
1412 | | WASM_DECLARE_C_GET_ATTR(tabletype, wasm_valtype_t *, element, static, nullptr, , |
1413 | | const) |
1414 | | WASM_DECLARE_C_GET_ATTR(tabletype, wasm_limits_t *, limits, reinterpret, |
1415 | | nullptr, &, const) |
1416 | | |
1417 | | // <<<<<<<< wasm_tabletype_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1418 | | |
1419 | | // >>>>>>>> wasm_memorytype_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1420 | | |
1421 | 0 | WASM_DECLARE_TYPE_IMPL(memorytype, wasm::MemoryType) Unexecuted instantiation: wasm_memorytype_vec_new_uninitialized Unexecuted instantiation: wasm_memorytype_vec_new Unexecuted instantiation: wasm_memorytype_vec_copy |
1422 | 0 |
|
1423 | 0 | WASMEDGE_CAPI_EXPORT OWN wasm_memorytype_t * |
1424 | 0 | wasm_memorytype_new(const wasm_limits_t *limits) { |
1425 | 0 | if (limits) { |
1426 | 0 | return new (std::nothrow) |
1427 | 0 | wasm_memorytype_t(wasm::Limits(limits->min, limits->max)); |
1428 | 0 | } |
1429 | 0 | return nullptr; |
1430 | 0 | } |
1431 | | |
1432 | | WASM_DECLARE_C_GET_ATTR(memorytype, wasm_limits_t *, limits, reinterpret, |
1433 | | nullptr, &, const) |
1434 | | |
1435 | | // <<<<<<<< wasm_memorytype_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1436 | | |
1437 | | // >>>>>>>> wasm_tagtype_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1438 | | |
1439 | 0 | WASM_DECLARE_TYPE_IMPL(tagtype, wasm::TagType) Unexecuted instantiation: wasm_tagtype_vec_new_uninitialized Unexecuted instantiation: wasm_tagtype_vec_new Unexecuted instantiation: wasm_tagtype_vec_copy |
1440 | 0 |
|
1441 | 0 | WASMEDGE_CAPI_EXPORT OWN wasm_tagtype_t * |
1442 | 0 | wasm_tagtype_new(OWN wasm_functype_t *functype) { |
1443 | 0 | if (functype) { |
1444 | 0 | return new (std::nothrow) wasm_tagtype_t(wasm::make_own(functype)); |
1445 | 0 | } |
1446 | 0 | return nullptr; |
1447 | 0 | } |
1448 | | |
1449 | | WASM_DECLARE_C_GET_ATTR(tagtype, wasm_functype_t *, functype, static, nullptr, , |
1450 | | const) |
1451 | | |
1452 | | // <<<<<<<< wasm_tagtype_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1453 | | |
1454 | | // >>>>>>>> wasm_externtype_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1455 | | |
1456 | 0 | WASM_DECLARE_TYPE_IMPL(externtype, wasm::ExternType) Unexecuted instantiation: wasm_externtype_vec_new_uninitialized Unexecuted instantiation: wasm_externtype_vec_new Unexecuted instantiation: wasm_externtype_vec_copy |
1457 | 0 |
|
1458 | 0 | WASM_DECLARE_C_GET_ATTR(externtype, wasm_externkind_t, kind, static, |
1459 | 0 | WASM_EXTERN_FUNC, , ) |
1460 | 0 |
|
1461 | 0 | WASM_EXTERNTYPE_C_CONV(func, extern, type, Type, , ) |
1462 | 0 | WASM_EXTERNTYPE_C_CONV(func, extern, type, Type, _, const) |
1463 | 0 | WASM_EXTERNTYPE_C_CONV(global, extern, type, Type, , ) |
1464 | 0 | WASM_EXTERNTYPE_C_CONV(global, extern, type, Type, _, const) |
1465 | 0 | WASM_EXTERNTYPE_C_CONV(table, extern, type, Type, , ) |
1466 | 0 | WASM_EXTERNTYPE_C_CONV(table, extern, type, Type, _, const) |
1467 | 0 | WASM_EXTERNTYPE_C_CONV(memory, extern, type, Type, , ) |
1468 | 0 | WASM_EXTERNTYPE_C_CONV(memory, extern, type, Type, _, const) |
1469 | 0 | WASM_EXTERNTYPE_C_CONV(tag, extern, type, Type, , ) |
1470 | 0 | WASM_EXTERNTYPE_C_CONV(tag, extern, type, Type, _, const) |
1471 | 0 | WASM_EXTERNTYPE_C_CONV(extern, func, type, Type, , ) |
1472 | 0 | WASM_EXTERNTYPE_C_CONV(extern, func, type, Type, _, const) |
1473 | 0 | WASM_EXTERNTYPE_C_CONV(extern, global, type, Type, , ) |
1474 | 0 | WASM_EXTERNTYPE_C_CONV(extern, global, type, Type, _, const) |
1475 | 0 | WASM_EXTERNTYPE_C_CONV(extern, table, type, Type, , ) |
1476 | 0 | WASM_EXTERNTYPE_C_CONV(extern, table, type, Type, _, const) |
1477 | 0 | WASM_EXTERNTYPE_C_CONV(extern, memory, type, Type, , ) |
1478 | 0 | WASM_EXTERNTYPE_C_CONV(extern, memory, type, Type, _, const) |
1479 | 0 | WASM_EXTERNTYPE_C_CONV(extern, tag, type, Type, , ) |
1480 | 0 | WASM_EXTERNTYPE_C_CONV(extern, tag, type, Type, _, const) |
1481 | 0 |
|
1482 | 0 | // <<<<<<<< wasm_externtype_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1483 | 0 |
|
1484 | 0 | // >>>>>>>> wasm_importtype_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1485 | 0 |
|
1486 | 0 | WASM_DECLARE_TYPE_IMPL(importtype, wasm::ImportType) Unexecuted instantiation: wasm_importtype_vec_new_uninitialized Unexecuted instantiation: wasm_importtype_vec_new Unexecuted instantiation: wasm_importtype_vec_copy |
1487 | 0 |
|
1488 | 0 | WASMEDGE_CAPI_EXPORT OWN wasm_importtype_t * |
1489 | 0 | wasm_importtype_new(OWN wasm_name_t *module, OWN wasm_name_t *name, |
1490 | 0 | OWN wasm_externtype_t *externtype) { |
1491 | 0 | if (module && name && externtype) { |
1492 | 0 | return new (std::nothrow) |
1493 | 0 | wasm_importtype_t(wasm::vec<byte_t>::adopt(module->size, module->data), |
1494 | 0 | wasm::vec<byte_t>::adopt(name->size, name->data), |
1495 | 0 | wasm::make_own(externtype)); |
1496 | 0 | } |
1497 | 0 | return nullptr; |
1498 | 0 | } |
1499 | | |
1500 | | WASM_DECLARE_C_GET_ATTR(importtype, wasm_name_t *, module, reinterpret, |
1501 | | nullptr, &, const) |
1502 | | WASM_DECLARE_C_GET_ATTR(importtype, wasm_name_t *, name, reinterpret, |
1503 | | nullptr, &, const) |
1504 | | WASM_DECLARE_C_GET_ATTR(importtype, wasm_externtype_t *, type, static, nullptr, |
1505 | | , const) |
1506 | | |
1507 | | // <<<<<<<< wasm_importtype_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1508 | | |
1509 | | // >>>>>>>> wasm_exporttype_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1510 | | |
1511 | 0 | WASM_DECLARE_TYPE_IMPL(exporttype, wasm::ExportType) Unexecuted instantiation: wasm_exporttype_vec_new_uninitialized Unexecuted instantiation: wasm_exporttype_vec_new Unexecuted instantiation: wasm_exporttype_vec_copy |
1512 | 0 |
|
1513 | 0 | WASMEDGE_CAPI_EXPORT OWN wasm_exporttype_t * |
1514 | 0 | wasm_exporttype_new(OWN wasm_name_t *name, OWN wasm_externtype_t *externtype) { |
1515 | 0 | if (name && externtype) { |
1516 | 0 | return new (std::nothrow) |
1517 | 0 | wasm_exporttype_t(wasm::vec<byte_t>::adopt(name->size, name->data), |
1518 | 0 | wasm::make_own(externtype)); |
1519 | 0 | } |
1520 | 0 | return nullptr; |
1521 | 0 | } |
1522 | | |
1523 | | WASM_DECLARE_C_GET_ATTR(exporttype, wasm_name_t *, name, reinterpret, |
1524 | | nullptr, &, const) |
1525 | | WASM_DECLARE_C_GET_ATTR(exporttype, wasm_externtype_t *, type, static, nullptr, |
1526 | | , const) |
1527 | | |
1528 | | // <<<<<<<< wasm_exporttype_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1529 | | |
1530 | | //////////////////////////////////////////////////////////////////////////////// |
1531 | | |
1532 | | // Runtime Objects |
1533 | | |
1534 | | // >>>>>>>> wasm_val_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1535 | | |
1536 | 0 | WASM_DECLARE_VEC_BASE_IMPL(val, wasm::Val, wasm::vec, wasm::vec, ) |
1537 | | |
1538 | | WASMEDGE_CAPI_EXPORT void wasm_val_vec_new(OWN wasm_val_vec_t *out, size_t size, |
1539 | 0 | OWN wasm_val_t const data[]) { |
1540 | 0 | if (out) { |
1541 | 0 | *out = {0, nullptr}; |
1542 | 0 | if (size < UINT32_MAX) { |
1543 | 0 | auto v = wasm::vec<wasm::Val>::make_uninitialized(size); |
1544 | 0 | for (size_t i = 0; i < v.size(); ++i) { |
1545 | 0 | v[i] = conv_val_to_cpp(data[i]); |
1546 | 0 | } |
1547 | 0 | *out = {v.size(), reinterpret_cast<wasm_val_t *>(v.release())}; |
1548 | 0 | } |
1549 | 0 | } |
1550 | 0 | } |
1551 | | |
1552 | | WASMEDGE_CAPI_EXPORT void wasm_val_vec_copy(OWN wasm_val_vec_t *out, |
1553 | 0 | const wasm_val_vec_t *in) { |
1554 | 0 | if (out) { |
1555 | 0 | *out = {0, nullptr}; |
1556 | 0 | } |
1557 | 0 | if (in && out && in->size < UINT32_MAX) { |
1558 | 0 | auto v = wasm::vec<wasm::Val>::make_uninitialized(in->size); |
1559 | 0 | for (size_t i = 0; i < v.size(); ++i) { |
1560 | 0 | wasm_val_t val; |
1561 | 0 | wasm_val_copy(&in->data[i], &val); |
1562 | 0 | v[i] = conv_val_to_cpp(val); |
1563 | 0 | } |
1564 | 0 | *out = {v.size(), reinterpret_cast<wasm_val_t *>(v.release())}; |
1565 | 0 | } |
1566 | 0 | } |
1567 | | |
1568 | 0 | WASMEDGE_CAPI_EXPORT void wasm_val_delete(OWN wasm_val_t *v) { |
1569 | 0 | if (v && is_ref(static_cast<wasm::ValKind>(v->kind))) { |
1570 | 0 | wasm::make_own(v->of.ref); |
1571 | 0 | } |
1572 | 0 | } |
1573 | | |
1574 | | WASMEDGE_CAPI_EXPORT void wasm_val_copy(OWN wasm_val_t *out, |
1575 | 0 | const wasm_val_t *in) { |
1576 | 0 | if (out) { |
1577 | 0 | if (in) { |
1578 | 0 | *out = *in; |
1579 | 0 | if (wasm::is_ref(static_cast<wasm::ValKind>(in->kind)) && in->of.ref) { |
1580 | 0 | out->of.ref = static_cast<wasm_ref_t *>(in->of.ref->copy().release()); |
1581 | 0 | } |
1582 | 0 | } else { |
1583 | 0 | out->kind = WASM_I32; |
1584 | 0 | out->of.i64 = 0; |
1585 | 0 | } |
1586 | 0 | } |
1587 | 0 | } |
1588 | | |
1589 | | // <<<<<<<< wasm_val_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1590 | | |
1591 | | // >>>>>>>> wasm_ref_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1592 | | |
1593 | | WASM_DECLARE_REF_BASE_IMPL(ref, wasm::Ref) |
1594 | | |
1595 | | // <<<<<<<< wasm_ref_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1596 | | |
1597 | | // >>>>>>>> wasm_frame_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1598 | | |
1599 | | WASM_DECLARE_OWN_IMPL(frame, wasm::Frame) |
1600 | 0 | WASM_DECLARE_VEC_PTR_IMPL(frame, wasm::Frame) Unexecuted instantiation: wasm_frame_vec_new_uninitialized Unexecuted instantiation: wasm_frame_vec_new Unexecuted instantiation: wasm_frame_vec_copy |
1601 | | |
1602 | | WASMEDGE_CAPI_EXPORT OWN wasm_frame_t * |
1603 | 0 | wasm_frame_copy(const wasm_frame_t *frame) { |
1604 | 0 | return static_cast<wasm_frame_t *>(frame->copy().release()); |
1605 | 0 | } |
1606 | | |
1607 | | WASM_DECLARE_C_GET_ATTR(frame, wasm_instance_t *, instance, static, nullptr, , ) |
1608 | | WASM_DECLARE_C_GET_ATTR(frame, uint32_t, func_index, static, 0, , ) |
1609 | | WASM_DECLARE_C_GET_ATTR(frame, size_t, func_offset, static, 0, , ) |
1610 | | WASM_DECLARE_C_GET_ATTR(frame, size_t, module_offset, static, 0, , ) |
1611 | | |
1612 | | // <<<<<<<< wasm_frame_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1613 | | |
1614 | | // >>>>>>>> wasm_trap_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1615 | | |
1616 | | WASM_DECLARE_REF_IMPL(trap, wasm::Trap) |
1617 | | |
1618 | | WASMEDGE_CAPI_EXPORT OWN wasm_trap_t * |
1619 | 0 | wasm_trap_new(wasm_store_t *store, const wasm_message_t *message) { |
1620 | 0 | if (store && message) { |
1621 | 0 | wasm_byte_vec_t v; |
1622 | 0 | wasm_byte_vec_copy(&v, message); |
1623 | 0 | return new (std::nothrow) |
1624 | 0 | wasm_trap_t(store, wasm::vec<byte_t>::adopt(v.size, v.data)); |
1625 | 0 | } |
1626 | 0 | return nullptr; |
1627 | 0 | } |
1628 | | |
1629 | | WASMEDGE_CAPI_EXPORT void wasm_trap_message(const wasm_trap_t *trap, |
1630 | 0 | OWN wasm_message_t *out) { |
1631 | 0 | if (out) { |
1632 | 0 | *out = {0, nullptr}; |
1633 | 0 | if (trap) { |
1634 | 0 | auto v = trap->message(); |
1635 | 0 | *out = {v.size(), reinterpret_cast<wasm_byte_t *>(v.release())}; |
1636 | 0 | } |
1637 | 0 | } |
1638 | 0 | } |
1639 | | |
1640 | | WASMEDGE_CAPI_EXPORT OWN wasm_frame_t * |
1641 | 0 | wasm_trap_origin(const wasm_trap_t *trap) { |
1642 | 0 | if (trap) { |
1643 | 0 | return static_cast<wasm_frame_t *>(trap->origin().release()); |
1644 | 0 | } |
1645 | 0 | return nullptr; |
1646 | 0 | } |
1647 | | |
1648 | | WASMEDGE_CAPI_EXPORT void wasm_trap_trace(const wasm_trap_t *trap, |
1649 | 0 | OWN wasm_frame_vec_t *out) { |
1650 | 0 | if (out) { |
1651 | 0 | *out = {0, nullptr}; |
1652 | 0 | if (trap) { |
1653 | 0 | auto v = trap->trace(); |
1654 | 0 | *out = {v.size(), reinterpret_cast<wasm_frame_t **>(v.release())}; |
1655 | 0 | } |
1656 | 0 | } |
1657 | 0 | } |
1658 | | |
1659 | | // <<<<<<<< wasm_trap_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1660 | | |
1661 | | // >>>>>>>> wasm_foreign_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1662 | | |
1663 | | WASM_DECLARE_REF_IMPL(foreign, wasm::Foreign) |
1664 | | |
1665 | 0 | WASMEDGE_CAPI_EXPORT OWN wasm_foreign_t *wasm_foreign_new(wasm_store_t *store) { |
1666 | 0 | return static_cast<wasm_foreign_t *>(wasm::Foreign::make(store).release()); |
1667 | 0 | } |
1668 | | |
1669 | | // <<<<<<<< wasm_foreign_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1670 | | |
1671 | | // >>>>>>>> wasm_module_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1672 | | |
1673 | | WASM_DECLARE_SHARABLE_REF_IMPL(module, wasm::Module) |
1674 | | |
1675 | | WASMEDGE_CAPI_EXPORT OWN wasm_module_t * |
1676 | 0 | wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) { |
1677 | 0 | if (store && binary) { |
1678 | 0 | wasm_byte_vec_t v; |
1679 | 0 | wasm_byte_vec_copy(&v, binary); |
1680 | 0 | auto mod = store->load.parseModule(WasmEdge::Span<const uint8_t>( |
1681 | 0 | reinterpret_cast<const uint8_t *>(v.data), v.size)); |
1682 | 0 | if (mod && store->valid.validate(*mod->get())) { |
1683 | 0 | return new (std::nothrow) wasm_module_t( |
1684 | 0 | store, std::move(*mod), wasm::vec<byte_t>::adopt(v.size, v.data)); |
1685 | 0 | } |
1686 | 0 | wasm_byte_vec_delete(&v); |
1687 | 0 | } |
1688 | 0 | return nullptr; |
1689 | 0 | } |
1690 | | |
1691 | | WASMEDGE_CAPI_EXPORT bool wasm_module_validate(wasm_store_t *store, |
1692 | 0 | const wasm_byte_vec_t *binary) { |
1693 | 0 | if (store && binary) { |
1694 | 0 | auto mod = store->load.parseModule(WasmEdge::Span<const uint8_t>( |
1695 | 0 | reinterpret_cast<const uint8_t *>(binary->data), binary->size)); |
1696 | 0 | if (!mod) { |
1697 | 0 | return false; |
1698 | 0 | } |
1699 | 0 | auto valid = store->valid.validate(*mod->get()); |
1700 | 0 | if (valid) { |
1701 | 0 | return true; |
1702 | 0 | } |
1703 | 0 | } |
1704 | 0 | return false; |
1705 | 0 | } |
1706 | | |
1707 | | WASMEDGE_CAPI_EXPORT void wasm_module_imports(const wasm_module_t *module, |
1708 | 0 | OWN wasm_importtype_vec_t *out) { |
1709 | 0 | if (out) { |
1710 | 0 | *out = {0, nullptr}; |
1711 | 0 | if (module) { |
1712 | 0 | auto v = module->imports(); |
1713 | 0 | *out = {v.size(), reinterpret_cast<wasm_importtype_t **>(v.release())}; |
1714 | 0 | } |
1715 | 0 | } |
1716 | 0 | } |
1717 | | |
1718 | | WASMEDGE_CAPI_EXPORT void wasm_module_exports(const wasm_module_t *module, |
1719 | 0 | OWN wasm_exporttype_vec_t *out) { |
1720 | 0 | if (out) { |
1721 | 0 | *out = {0, nullptr}; |
1722 | 0 | if (module) { |
1723 | 0 | auto v = module->exports(); |
1724 | 0 | *out = {v.size(), reinterpret_cast<wasm_exporttype_t **>(v.release())}; |
1725 | 0 | } |
1726 | 0 | } |
1727 | 0 | } |
1728 | | |
1729 | | WASMEDGE_CAPI_EXPORT void wasm_module_serialize(const wasm_module_t *module, |
1730 | 0 | OWN wasm_byte_vec_t *out) { |
1731 | 0 | if (out) { |
1732 | 0 | *out = {0, nullptr}; |
1733 | 0 | if (module) { |
1734 | 0 | auto v = module->serialize(); |
1735 | 0 | *out = {v.size(), reinterpret_cast<wasm_byte_t *>(v.release())}; |
1736 | 0 | } |
1737 | 0 | } |
1738 | 0 | } |
1739 | | |
1740 | | WASMEDGE_CAPI_EXPORT OWN wasm_module_t * |
1741 | 0 | wasm_module_deserialize(wasm_store_t *store, const wasm_byte_vec_t *binary) { |
1742 | 0 | return wasm_module_new(store, binary); |
1743 | 0 | } |
1744 | | |
1745 | | WASMEDGE_CAPI_EXPORT OWN wasm_shared_module_t * |
1746 | 0 | wasm_module_share(const wasm_module_t *module) { |
1747 | 0 | if (module) { |
1748 | 0 | return static_cast<wasm_shared_module_t *>(module->share().release()); |
1749 | 0 | } |
1750 | 0 | return nullptr; |
1751 | 0 | } |
1752 | | |
1753 | | WASMEDGE_CAPI_EXPORT OWN wasm_module_t * |
1754 | 0 | wasm_module_obtain(wasm_store_t *store, const wasm_shared_module_t *shared) { |
1755 | 0 | if (store && shared) { |
1756 | 0 | return static_cast<wasm_module_t *>( |
1757 | 0 | wasm::Module::obtain(store, shared).release()); |
1758 | 0 | } |
1759 | 0 | return nullptr; |
1760 | 0 | } |
1761 | | |
1762 | | // <<<<<<<< wasm_module_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1763 | | |
1764 | | // >>>>>>>> wasm_func_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1765 | | |
1766 | | WASM_DECLARE_REF_IMPL(func, wasm::Func) |
1767 | | |
1768 | | WASMEDGE_CAPI_EXPORT OWN wasm_func_t * |
1769 | | wasm_func_new(wasm_store_t *store, const wasm_functype_t *type, |
1770 | 0 | wasm_func_callback_t callback) { |
1771 | 0 | if (store && type && callback) { |
1772 | 0 | return new (std::nothrow) wasm_func_t(store, *type, callback); |
1773 | 0 | } |
1774 | 0 | return nullptr; |
1775 | 0 | } |
1776 | | |
1777 | | WASMEDGE_CAPI_EXPORT OWN wasm_func_t * |
1778 | | wasm_func_new_with_env(wasm_store_t *store, const wasm_functype_t *type, |
1779 | | wasm_func_callback_with_env_t callback, void *env, |
1780 | 0 | void (*finalizer)(void *)) { |
1781 | 0 | if (store && type && callback) { |
1782 | 0 | return new (std::nothrow) |
1783 | 0 | wasm_func_t(store, *type, callback, env, finalizer); |
1784 | 0 | } |
1785 | 0 | return nullptr; |
1786 | 0 | } |
1787 | | |
1788 | | WASMEDGE_CAPI_EXPORT OWN wasm_functype_t * |
1789 | 0 | wasm_func_type(const wasm_func_t *func) { |
1790 | 0 | if (func) { |
1791 | 0 | return static_cast<wasm_functype_t *>(func->type().release()); |
1792 | 0 | } |
1793 | 0 | return nullptr; |
1794 | 0 | } |
1795 | | |
1796 | | WASM_DECLARE_C_GET_ATTR(func, size_t, param_arity, static, 0, , ) |
1797 | | WASM_DECLARE_C_GET_ATTR(func, size_t, result_arity, static, 0, , ) |
1798 | | |
1799 | | WASMEDGE_CAPI_EXPORT OWN wasm_trap_t *wasm_func_call(const wasm_func_t *func, |
1800 | | const wasm_val_vec_t *args, |
1801 | 0 | wasm_val_vec_t *results) { |
1802 | 0 | if (!func || !func->inst) { |
1803 | 0 | return nullptr; |
1804 | 0 | } |
1805 | 0 | const auto &ftype = func->inst->getFuncType(); |
1806 | 0 | const auto &ptypes = ftype.getParamTypes(); |
1807 | 0 | const auto &rtypes = ftype.getReturnTypes(); |
1808 | |
|
1809 | 0 | std::vector<WasmEdge::ValVariant> params(ptypes.size()); |
1810 | 0 | if (args) { |
1811 | 0 | for (size_t i = 0; i < ptypes.size() && i < args->size; ++i) { |
1812 | 0 | params[i] = conv_cval_to_wasmedge(args->data[i]); |
1813 | 0 | } |
1814 | 0 | } |
1815 | |
|
1816 | 0 | auto res = func->store->engine->exec.invoke(func->inst, params, ptypes); |
1817 | 0 | if (!res) { |
1818 | 0 | return static_cast<wasm_trap_t *>( |
1819 | 0 | buildTrap(func->store, res.error(), lookupFuncIdx(func->inst)) |
1820 | 0 | .release()); |
1821 | 0 | } |
1822 | 0 | if (results) { |
1823 | 0 | for (size_t i = 0; i < rtypes.size() && i < results->size; ++i) { |
1824 | 0 | results->data[i] = conv_cval_from_wasmedge((*res)[i].first, rtypes[i]); |
1825 | | // Results from wasm_func_call are owning per the wasm-c-api spec: |
1826 | | // the caller is expected to wasm_val_delete (or wasm_ref_delete the |
1827 | | // payload). conv_cval_from_wasmedge returns a borrowed pointer, so |
1828 | | // increment the refcount here to transfer ownership. |
1829 | 0 | if (results->data[i].of.ref && |
1830 | 0 | wasm::is_ref(static_cast<wasm::ValKind>(results->data[i].kind))) { |
1831 | 0 | results->data[i].of.ref->copy_ref().release(); |
1832 | 0 | } |
1833 | 0 | } |
1834 | 0 | } |
1835 | 0 | return nullptr; |
1836 | 0 | } |
1837 | | |
1838 | | // <<<<<<<< wasm_func_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1839 | | |
1840 | | // >>>>>>>> wasm_global_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1841 | | |
1842 | | WASM_DECLARE_REF_IMPL(global, wasm::Global) |
1843 | | |
1844 | | WASMEDGE_CAPI_EXPORT OWN wasm_global_t * |
1845 | | wasm_global_new(wasm_store_t *store, const wasm_globaltype_t *type, |
1846 | 0 | const wasm_val_t *val) { |
1847 | 0 | if (store && type && val) { |
1848 | 0 | return static_cast<wasm_global_t *>( |
1849 | 0 | wasm::Global::make(store, type, conv_val_to_cpp(*val)).release()); |
1850 | 0 | } |
1851 | 0 | return nullptr; |
1852 | 0 | } |
1853 | | |
1854 | | WASMEDGE_CAPI_EXPORT OWN wasm_globaltype_t * |
1855 | 0 | wasm_global_type(const wasm_global_t *global) { |
1856 | 0 | if (global) { |
1857 | 0 | return static_cast<wasm_globaltype_t *>(global->type().release()); |
1858 | 0 | } |
1859 | 0 | return nullptr; |
1860 | 0 | } |
1861 | | |
1862 | | WASMEDGE_CAPI_EXPORT void wasm_global_get(const wasm_global_t *global, |
1863 | 0 | OWN wasm_val_t *out) { |
1864 | 0 | if (global && out) { |
1865 | 0 | auto val = global->get(); |
1866 | 0 | *out = conv_val_to_c(val); |
1867 | | // global_get returns an owning wasm_val_t (caller will wasm_val_delete). |
1868 | | // conv_val_to_c only exposes a borrowed pointer; bump the refcount while |
1869 | | // val still owns the ref so the net is +1 transferred to the caller. |
1870 | 0 | if (out->of.ref && wasm::is_ref(static_cast<wasm::ValKind>(out->kind))) { |
1871 | 0 | out->of.ref->copy_ref().release(); |
1872 | 0 | } |
1873 | 0 | } |
1874 | 0 | } |
1875 | | |
1876 | | WASMEDGE_CAPI_EXPORT void wasm_global_set(wasm_global_t *global, |
1877 | 0 | const wasm_val_t *val) { |
1878 | 0 | if (global && val) { |
1879 | 0 | global->set(conv_val_to_cpp(*val)); |
1880 | 0 | } |
1881 | 0 | } |
1882 | | |
1883 | | // <<<<<<<< wasm_global_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1884 | | |
1885 | | // >>>>>>>> wasm_table_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1886 | | |
1887 | | WASM_DECLARE_REF_IMPL(table, wasm::Table) |
1888 | | |
1889 | | WASMEDGE_CAPI_EXPORT OWN wasm_table_t * |
1890 | | wasm_table_new(wasm_store_t *store, const wasm_tabletype_t *type, |
1891 | 0 | wasm_ref_t *ref) { |
1892 | 0 | return static_cast<wasm_table_t *>( |
1893 | 0 | wasm::Table::make(store, type, ref).release()); |
1894 | 0 | } |
1895 | | |
1896 | | WASMEDGE_CAPI_EXPORT OWN wasm_tabletype_t * |
1897 | 0 | wasm_table_type(const wasm_table_t *table) { |
1898 | 0 | if (table) { |
1899 | 0 | return static_cast<wasm_tabletype_t *>(table->type().release()); |
1900 | 0 | } |
1901 | 0 | return nullptr; |
1902 | 0 | } |
1903 | | |
1904 | | WASMEDGE_CAPI_EXPORT OWN wasm_ref_t *wasm_table_get(const wasm_table_t *table, |
1905 | 0 | wasm_table_size_t index) { |
1906 | 0 | if (table) { |
1907 | 0 | return static_cast<wasm_ref_t *>(table->get(index).release()); |
1908 | 0 | } |
1909 | 0 | return nullptr; |
1910 | 0 | } |
1911 | | |
1912 | | WASMEDGE_CAPI_EXPORT bool |
1913 | 0 | wasm_table_set(wasm_table_t *table, wasm_table_size_t index, wasm_ref_t *ref) { |
1914 | 0 | if (table) { |
1915 | 0 | return table->set(index, ref); |
1916 | 0 | } |
1917 | 0 | return false; |
1918 | 0 | } |
1919 | | |
1920 | | WASM_DECLARE_C_GET_ATTR(table, wasm_table_size_t, size, static, 0, , ) |
1921 | | |
1922 | | WASMEDGE_CAPI_EXPORT bool |
1923 | 0 | wasm_table_grow(wasm_table_t *table, wasm_table_size_t delta, wasm_ref_t *ref) { |
1924 | 0 | if (table) { |
1925 | 0 | return table->grow(delta, ref); |
1926 | 0 | } |
1927 | 0 | return false; |
1928 | 0 | } |
1929 | | |
1930 | | // <<<<<<<< wasm_table_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1931 | | |
1932 | | // >>>>>>>> wasm_memory_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1933 | | |
1934 | | WASM_DECLARE_REF_IMPL(memory, wasm::Memory) |
1935 | | |
1936 | | WASMEDGE_CAPI_EXPORT OWN wasm_memory_t * |
1937 | 0 | wasm_memory_new(wasm_store_t *store, const wasm_memorytype_t *type) { |
1938 | 0 | return static_cast<wasm_memory_t *>( |
1939 | 0 | wasm::Memory::make(store, type).release()); |
1940 | 0 | } |
1941 | | |
1942 | | WASMEDGE_CAPI_EXPORT OWN wasm_memorytype_t * |
1943 | 0 | wasm_memory_type(const wasm_memory_t *memory) { |
1944 | 0 | if (memory) { |
1945 | 0 | return static_cast<wasm_memorytype_t *>(memory->type().release()); |
1946 | 0 | } |
1947 | 0 | return nullptr; |
1948 | 0 | } |
1949 | | |
1950 | 0 | WASMEDGE_CAPI_EXPORT byte_t *wasm_memory_data(wasm_memory_t *memory) { |
1951 | 0 | if (memory) { |
1952 | 0 | return static_cast<byte_t *>(memory->data()); |
1953 | 0 | } |
1954 | 0 | return nullptr; |
1955 | 0 | } |
1956 | | |
1957 | | WASM_DECLARE_C_GET_ATTR(memory, size_t, data_size, static, 0, , ) |
1958 | | WASM_DECLARE_C_GET_ATTR(memory, wasm_memory_pages_t, size, static, 0, , ) |
1959 | | |
1960 | | WASMEDGE_CAPI_EXPORT bool wasm_memory_grow(wasm_memory_t *memory, |
1961 | 0 | wasm_memory_pages_t delta) { |
1962 | 0 | if (memory) { |
1963 | 0 | return memory->grow(static_cast<wasm::Memory::pages_t>(delta)); |
1964 | 0 | } |
1965 | 0 | return false; |
1966 | 0 | } |
1967 | | |
1968 | | // <<<<<<<< wasm_memory_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
1969 | | |
1970 | | // >>>>>>>> wasm_extern_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
1971 | | |
1972 | | WASM_DECLARE_REF_IMPL(extern, wasm::Extern) |
1973 | 0 | WASM_DECLARE_VEC_PTR_IMPL(extern, wasm::Extern) Unexecuted instantiation: wasm_extern_vec_new_uninitialized Unexecuted instantiation: wasm_extern_vec_new Unexecuted instantiation: wasm_extern_vec_copy |
1974 | | |
1975 | | WASM_DECLARE_C_GET_ATTR(extern, wasm_externkind_t, kind, static, |
1976 | | WASM_EXTERN_FUNC, , ) |
1977 | | |
1978 | | WASMEDGE_CAPI_EXPORT OWN wasm_externtype_t * |
1979 | 0 | wasm_extern_type(const wasm_extern_t *external) { |
1980 | 0 | return reinterpret_cast<wasm_externtype_t *>(external->type().release()); |
1981 | 0 | } |
1982 | | |
1983 | | WASM_EXTERNTYPE_C_CONV(func, extern, , , , ) |
1984 | | WASM_EXTERNTYPE_C_CONV(func, extern, , , _, const) |
1985 | | WASM_EXTERNTYPE_C_CONV(global, extern, , , , ) |
1986 | | WASM_EXTERNTYPE_C_CONV(global, extern, , , _, const) |
1987 | | WASM_EXTERNTYPE_C_CONV(table, extern, , , , ) |
1988 | | WASM_EXTERNTYPE_C_CONV(table, extern, , , _, const) |
1989 | | WASM_EXTERNTYPE_C_CONV(memory, extern, , , , ) |
1990 | | WASM_EXTERNTYPE_C_CONV(memory, extern, , , _, const) |
1991 | | WASM_EXTERNTYPE_C_CONV(extern, func, , , , ) |
1992 | | WASM_EXTERNTYPE_C_CONV(extern, func, , , _, const) |
1993 | | WASM_EXTERNTYPE_C_CONV(extern, global, , , , ) |
1994 | | WASM_EXTERNTYPE_C_CONV(extern, global, , , _, const) |
1995 | | WASM_EXTERNTYPE_C_CONV(extern, table, , , , ) |
1996 | | WASM_EXTERNTYPE_C_CONV(extern, table, , , _, const) |
1997 | | WASM_EXTERNTYPE_C_CONV(extern, memory, , , , ) |
1998 | | WASM_EXTERNTYPE_C_CONV(extern, memory, , , _, const) |
1999 | | |
2000 | | // <<<<<<<< wasm_extern_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2001 | | |
2002 | | // >>>>>>>> wasm_instance_t functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2003 | | |
2004 | | WASM_DECLARE_REF_IMPL(instance, wasm::Instance) |
2005 | | |
2006 | | WASMEDGE_CAPI_EXPORT OWN wasm_instance_t * |
2007 | | wasm_instance_new(wasm_store_t *store, const wasm_module_t *module, |
2008 | 0 | const wasm_extern_vec_t *imports, OWN wasm_trap_t **trap) { |
2009 | | // Copy the C imports vec into a wasm::vec view; the pointed-to externs are |
2010 | | // borrowed. |
2011 | 0 | auto imports_vec = wasm::vec<wasm::Extern *>::make_uninitialized( |
2012 | 0 | imports ? imports->size : 0); |
2013 | 0 | if (imports) { |
2014 | 0 | for (size_t i = 0; i < imports->size; ++i) { |
2015 | 0 | imports_vec[i] = static_cast<wasm::Extern *>(imports->data[i]); |
2016 | 0 | } |
2017 | 0 | } |
2018 | 0 | wasm::own<wasm::Trap> error; |
2019 | 0 | auto *instance = static_cast<wasm_instance_t *>( |
2020 | 0 | wasm::Instance::make(store, module, imports_vec, &error).release()); |
2021 | 0 | if (trap) { |
2022 | 0 | *trap = static_cast<wasm_trap_t *>(error.release()); |
2023 | 0 | } |
2024 | 0 | return instance; |
2025 | 0 | } |
2026 | | |
2027 | | WASMEDGE_CAPI_EXPORT void wasm_instance_exports(const wasm_instance_t *instance, |
2028 | 0 | OWN wasm_extern_vec_t *out) { |
2029 | 0 | if (out) { |
2030 | 0 | auto exports = instance->exports(); |
2031 | 0 | *out = {exports.size(), |
2032 | 0 | reinterpret_cast<wasm_extern_t **>(exports.release())}; |
2033 | 0 | } |
2034 | 0 | } |
2035 | | |
2036 | | // <<<<<<<< wasm_instance_t functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2037 | | |
2038 | | #ifdef OWN |
2039 | | #undef OWN |
2040 | | #endif |
2041 | | |
2042 | | #ifdef __cplusplus |
2043 | | } // extern "C" |
2044 | | #endif |
2045 | | |
2046 | | // The following are the C++ API implementation. |
2047 | | |
2048 | | // >>>>>>>> wasm::Config functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2049 | | |
2050 | 0 | wasm::own<wasm::Config> wasm::Config::make() { |
2051 | 0 | return wasm::make_own(new (std::nothrow) wasm_config_t); |
2052 | 0 | } |
2053 | | |
2054 | 0 | void wasm::Config::destroy() { delete static_cast<wasm_config_t *>(this); } |
2055 | | |
2056 | | // <<<<<<<< wasm::Config functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2057 | | |
2058 | | // >>>>>>>> wasm::Engine functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2059 | | |
2060 | 0 | wasm::own<wasm::Engine> wasm::Engine::make(wasm::own<wasm::Config> &&config) { |
2061 | 0 | if (config.get()) { |
2062 | 0 | return wasm::make_own(new (std::nothrow) wasm_engine_t(std::move(config))); |
2063 | 0 | } |
2064 | 0 | return wasm::make_own(new (std::nothrow) wasm_engine_t()); |
2065 | 0 | } |
2066 | | |
2067 | 0 | void wasm::Engine::destroy() { delete static_cast<wasm_engine_t *>(this); } |
2068 | | |
2069 | | // <<<<<<<< wasm::Engine functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2070 | | |
2071 | | // >>>>>>>> wasm::Store functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2072 | | |
2073 | 0 | wasm::own<wasm::Store> wasm::Store::make(wasm::Engine *engine) { |
2074 | 0 | if (engine) { |
2075 | 0 | return wasm::make_own(new (std::nothrow) wasm_store_t(engine)); |
2076 | 0 | } |
2077 | 0 | return nullptr; |
2078 | 0 | } |
2079 | | |
2080 | 0 | void wasm::Store::destroy() { delete static_cast<wasm_store_t *>(this); } |
2081 | | |
2082 | | // <<<<<<<< wasm::Store functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2083 | | |
2084 | | // >>>>>>>> wasm::ValType functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2085 | | |
2086 | 0 | void wasm::ValType::destroy() { |
2087 | | // Not to delete the struct because the ValTypes are global variables. |
2088 | 0 | } |
2089 | | |
2090 | 0 | wasm::own<wasm::ValType> wasm::ValType::make(wasm::ValKind kind) { |
2091 | 0 | switch (kind) { |
2092 | 0 | case ValKind::I32: |
2093 | 0 | return own<ValType>(&wasm_valtype_i32); |
2094 | 0 | case ValKind::I64: |
2095 | 0 | return own<ValType>(&wasm_valtype_i64); |
2096 | 0 | case ValKind::F32: |
2097 | 0 | return own<ValType>(&wasm_valtype_f32); |
2098 | 0 | case ValKind::F64: |
2099 | 0 | return own<ValType>(&wasm_valtype_f64); |
2100 | 0 | case ValKind::EXTERNREF: |
2101 | 0 | return own<ValType>(&wasm_valtype_externref); |
2102 | 0 | case ValKind::FUNCREF: |
2103 | 0 | return own<ValType>(&wasm_valtype_funcref); |
2104 | 0 | default: |
2105 | 0 | assumingUnreachable(); |
2106 | 0 | } |
2107 | 0 | } |
2108 | | |
2109 | 0 | wasm::own<wasm::ValType> wasm::ValType::copy() const { return make(kind()); } |
2110 | | |
2111 | 0 | wasm::ValKind wasm::ValType::kind() const { |
2112 | 0 | return (static_cast<const wasm_valtype_t *>(this))->mkind; |
2113 | 0 | } |
2114 | | |
2115 | | // <<<<<<<< wasm::ValType functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2116 | | |
2117 | | // >>>>>>>> wasm::FuncType functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2118 | | |
2119 | 0 | void wasm::FuncType::destroy() { delete static_cast<wasm_functype_t *>(this); } |
2120 | | |
2121 | | wasm::own<wasm::FuncType> |
2122 | | wasm::FuncType::make(wasm::ownvec<wasm::ValType> &¶ms, |
2123 | 0 | wasm::ownvec<wasm::ValType> &&results) { |
2124 | | // Check the inputs are valid. |
2125 | 0 | if (params && results) { |
2126 | 0 | return wasm::make_own(new (std::nothrow) wasm_functype_t( |
2127 | 0 | std::move(params), std::move(results))); |
2128 | 0 | } |
2129 | 0 | return nullptr; |
2130 | 0 | } |
2131 | | |
2132 | 0 | wasm::own<wasm::FuncType> wasm::FuncType::copy() const { |
2133 | | // The `params` and `results` vectors here must be valid. |
2134 | 0 | return make(params().deep_copy(), results().deep_copy()); |
2135 | 0 | } |
2136 | | |
2137 | 0 | const wasm::ownvec<wasm::ValType> &wasm::FuncType::params() const { |
2138 | 0 | return (static_cast<const wasm_functype_t *>(this))->mparams; |
2139 | 0 | } |
2140 | | |
2141 | 0 | const wasm::ownvec<wasm::ValType> &wasm::FuncType::results() const { |
2142 | 0 | return (static_cast<const wasm_functype_t *>(this))->mresults; |
2143 | 0 | } |
2144 | | |
2145 | | // <<<<<<<< wasm::FuncType functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2146 | | |
2147 | | // >>>>>>>> wasm::GlobalType functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2148 | | |
2149 | 0 | void wasm::GlobalType::destroy() { |
2150 | 0 | delete static_cast<wasm_globaltype_t *>(this); |
2151 | 0 | } |
2152 | | |
2153 | | wasm::own<wasm::GlobalType> |
2154 | | wasm::GlobalType::make(wasm::own<wasm::ValType> &&content, |
2155 | 0 | wasm::Mutability mutability) { |
2156 | 0 | return wasm::make_own(new (std::nothrow) |
2157 | 0 | wasm_globaltype_t(std::move(content), mutability)); |
2158 | 0 | } |
2159 | | |
2160 | 0 | wasm::own<wasm::GlobalType> wasm::GlobalType::copy() const { |
2161 | 0 | return make(content()->copy(), mutability()); |
2162 | 0 | } |
2163 | | |
2164 | 0 | const wasm::ValType *wasm::GlobalType::content() const { |
2165 | 0 | return (static_cast<const wasm_globaltype_t *>(this))->mcontent.get(); |
2166 | 0 | } |
2167 | | |
2168 | 0 | wasm::Mutability wasm::GlobalType::mutability() const { |
2169 | 0 | return (static_cast<const wasm_globaltype_t *>(this))->mmutability; |
2170 | 0 | } |
2171 | | |
2172 | | // <<<<<<<< wasm::GlobalType functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2173 | | |
2174 | | // >>>>>>>> wasm::TableType functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2175 | | |
2176 | 0 | void wasm::TableType::destroy() { |
2177 | 0 | delete static_cast<wasm_tabletype_t *>(this); |
2178 | 0 | } |
2179 | | |
2180 | | wasm::own<wasm::TableType> |
2181 | 0 | wasm::TableType::make(wasm::own<wasm::ValType> &&element, wasm::Limits limits) { |
2182 | 0 | return wasm::make_own(new (std::nothrow) |
2183 | 0 | wasm_tabletype_t(std::move(element), limits)); |
2184 | 0 | } |
2185 | | |
2186 | 0 | wasm::own<wasm::TableType> wasm::TableType::copy() const { |
2187 | 0 | return make(element()->copy(), limits()); |
2188 | 0 | } |
2189 | | |
2190 | 0 | const wasm::ValType *wasm::TableType::element() const { |
2191 | 0 | return (static_cast<const wasm_tabletype_t *>(this))->mvaltype.get(); |
2192 | 0 | } |
2193 | | |
2194 | 0 | const wasm::Limits &wasm::TableType::limits() const { |
2195 | 0 | return (static_cast<const wasm_tabletype_t *>(this))->mlimits; |
2196 | 0 | } |
2197 | | |
2198 | | // <<<<<<<< wasm::TableType functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2199 | | |
2200 | | // >>>>>>>> wasm::MemoryType functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2201 | | |
2202 | 0 | void wasm::MemoryType::destroy() { |
2203 | 0 | delete static_cast<wasm_memorytype_t *>(this); |
2204 | 0 | } |
2205 | | |
2206 | 0 | wasm::own<wasm::MemoryType> wasm::MemoryType::make(wasm::Limits limits) { |
2207 | 0 | return wasm::make_own(new (std::nothrow) wasm_memorytype_t(limits)); |
2208 | 0 | } |
2209 | | |
2210 | 0 | wasm::own<wasm::MemoryType> wasm::MemoryType::copy() const { |
2211 | 0 | return make(limits()); |
2212 | 0 | } |
2213 | | |
2214 | 0 | const wasm::Limits &wasm::MemoryType::limits() const { |
2215 | 0 | return (static_cast<const wasm_memorytype_t *>(this))->mlimits; |
2216 | 0 | } |
2217 | | |
2218 | | // <<<<<<<< wasm::MemoryType functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2219 | | |
2220 | | // >>>>>>>> wasm::TagType functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2221 | | |
2222 | 0 | void wasm::TagType::destroy() { delete static_cast<wasm_tagtype_t *>(this); } |
2223 | | |
2224 | 0 | wasm::own<wasm::TagType> wasm::TagType::make(wasm::own<wasm::FuncType> &&ft) { |
2225 | 0 | if (!ft) { |
2226 | 0 | return nullptr; |
2227 | 0 | } |
2228 | 0 | return wasm::make_own(new (std::nothrow) wasm_tagtype_t(std::move(ft))); |
2229 | 0 | } |
2230 | | |
2231 | 0 | wasm::own<wasm::TagType> wasm::TagType::copy() const { |
2232 | 0 | auto *self = static_cast<const wasm_tagtype_t *>(this); |
2233 | 0 | return make(self->mfunctype->copy()); |
2234 | 0 | } |
2235 | | |
2236 | 0 | const wasm::FuncType *wasm::TagType::functype() const { |
2237 | 0 | return static_cast<const wasm_tagtype_t *>(this)->mfunctype.get(); |
2238 | 0 | } |
2239 | | |
2240 | | // <<<<<<<< wasm::TagType functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2241 | | |
2242 | | // >>>>>>>> wasm::ExternType functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2243 | | |
2244 | 0 | void wasm::ExternType::destroy() { |
2245 | 0 | switch (kind()) { |
2246 | 0 | case wasm::ExternKind::FUNC: |
2247 | 0 | delete static_cast<wasm_functype_t *>(this); |
2248 | 0 | break; |
2249 | 0 | case wasm::ExternKind::GLOBAL: |
2250 | 0 | delete static_cast<wasm_globaltype_t *>(this); |
2251 | 0 | break; |
2252 | 0 | case wasm::ExternKind::TABLE: |
2253 | 0 | delete static_cast<wasm_tabletype_t *>(this); |
2254 | 0 | break; |
2255 | 0 | case wasm::ExternKind::MEMORY: |
2256 | 0 | delete static_cast<wasm_memorytype_t *>(this); |
2257 | 0 | break; |
2258 | 0 | case wasm::ExternKind::TAG: |
2259 | 0 | delete static_cast<wasm_tagtype_t *>(this); |
2260 | 0 | break; |
2261 | 0 | default: |
2262 | 0 | assumingUnreachable(); |
2263 | 0 | } |
2264 | 0 | } |
2265 | | |
2266 | 0 | wasm::own<wasm::ExternType> wasm::ExternType::copy() const { |
2267 | 0 | switch (kind()) { |
2268 | 0 | case wasm::ExternKind::FUNC: |
2269 | 0 | return func()->copy(); |
2270 | 0 | case wasm::ExternKind::GLOBAL: |
2271 | 0 | return global()->copy(); |
2272 | 0 | case wasm::ExternKind::TABLE: |
2273 | 0 | return table()->copy(); |
2274 | 0 | case wasm::ExternKind::MEMORY: |
2275 | 0 | return memory()->copy(); |
2276 | 0 | case wasm::ExternKind::TAG: |
2277 | 0 | return tag()->copy(); |
2278 | 0 | default: |
2279 | 0 | assumingUnreachable(); |
2280 | 0 | } |
2281 | 0 | } |
2282 | | |
2283 | 0 | wasm::ExternKind wasm::ExternType::kind() const { |
2284 | 0 | return static_cast<const wasm_externtype_t *>(this)->mkind; |
2285 | 0 | } |
2286 | | |
2287 | | WASM_EXTERNTYPE_CPP_CONV(func, Func, Type, FUNC, ) |
2288 | | WASM_EXTERNTYPE_CPP_CONV(func, Func, Type, FUNC, const) |
2289 | | WASM_EXTERNTYPE_CPP_CONV(global, Global, Type, GLOBAL, ) |
2290 | | WASM_EXTERNTYPE_CPP_CONV(global, Global, Type, GLOBAL, const) |
2291 | | WASM_EXTERNTYPE_CPP_CONV(table, Table, Type, TABLE, ) |
2292 | | WASM_EXTERNTYPE_CPP_CONV(table, Table, Type, TABLE, const) |
2293 | | WASM_EXTERNTYPE_CPP_CONV(memory, Memory, Type, MEMORY, ) |
2294 | | WASM_EXTERNTYPE_CPP_CONV(memory, Memory, Type, MEMORY, const) |
2295 | | WASM_EXTERNTYPE_CPP_CONV(tag, Tag, Type, TAG, ) |
2296 | | WASM_EXTERNTYPE_CPP_CONV(tag, Tag, Type, TAG, const) |
2297 | | |
2298 | | // <<<<<<<< wasm::ExternType functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2299 | | |
2300 | | // >>>>>>>> wasm::ImportType functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2301 | | |
2302 | 0 | void wasm::ImportType::destroy() { |
2303 | 0 | delete static_cast<wasm_importtype_t *>(this); |
2304 | 0 | } |
2305 | | |
2306 | | wasm::own<wasm::ImportType> |
2307 | | wasm::ImportType::make(wasm::Name &&module, wasm::Name &&name, |
2308 | 0 | wasm::own<wasm::ExternType> &&type) { |
2309 | 0 | return wasm::make_own(new (std::nothrow) wasm_importtype_t( |
2310 | 0 | std::move(module), std::move(name), std::move(type))); |
2311 | 0 | } |
2312 | | |
2313 | 0 | wasm::own<wasm::ImportType> wasm::ImportType::copy() const { |
2314 | 0 | return make(module().copy(), name().copy(), type()->copy()); |
2315 | 0 | } |
2316 | | |
2317 | 0 | const wasm::Name &wasm::ImportType::module() const { |
2318 | 0 | return static_cast<const wasm_importtype_t *>(this)->mmodname; |
2319 | 0 | } |
2320 | | |
2321 | 0 | const wasm::Name &wasm::ImportType::name() const { |
2322 | 0 | return static_cast<const wasm_importtype_t *>(this)->mname; |
2323 | 0 | } |
2324 | | |
2325 | 0 | const wasm::ExternType *wasm::ImportType::type() const { |
2326 | 0 | return static_cast<const wasm_importtype_t *>(this)->mtype.get(); |
2327 | 0 | } |
2328 | | |
2329 | | // <<<<<<<< wasm::ImportType functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2330 | | |
2331 | | // >>>>>>>> wasm::ExportType functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2332 | | |
2333 | 0 | void wasm::ExportType::destroy() { |
2334 | 0 | delete static_cast<wasm_exporttype_t *>(this); |
2335 | 0 | } |
2336 | | |
2337 | | wasm::own<wasm::ExportType> |
2338 | 0 | wasm::ExportType::make(wasm::Name &&name, wasm::own<wasm::ExternType> &&type) { |
2339 | 0 | return wasm::make_own( |
2340 | 0 | new (std::nothrow) wasm_exporttype_t(std::move(name), std::move(type))); |
2341 | 0 | } |
2342 | | |
2343 | 0 | wasm::own<wasm::ExportType> wasm::ExportType::copy() const { |
2344 | 0 | return make(name().copy(), type()->copy()); |
2345 | 0 | } |
2346 | | |
2347 | 0 | const wasm::Name &wasm::ExportType::name() const { |
2348 | 0 | return static_cast<const wasm_exporttype_t *>(this)->mname; |
2349 | 0 | } |
2350 | | |
2351 | 0 | const wasm::ExternType *wasm::ExportType::type() const { |
2352 | 0 | return static_cast<const wasm_exporttype_t *>(this)->mtype.get(); |
2353 | 0 | } |
2354 | | |
2355 | | // <<<<<<<< wasm::ExportType functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2356 | | |
2357 | | //////////////////////////////////////////////////////////////////////////////// |
2358 | | |
2359 | | // Runtime Objects |
2360 | | |
2361 | | // >>>>>>>> wasm::Val functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2362 | | |
2363 | | // The `wasm::Val` class has been fully implemented in header. |
2364 | | |
2365 | | // <<<<<<<< wasm::Val functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2366 | | |
2367 | | // >>>>>>>> wasm::Ref functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2368 | | |
2369 | 0 | void wasm::Ref::destroy() { static_cast<wasm_ref_t *>(this)->decrease_ref(); } |
2370 | | |
2371 | 0 | wasm::own<wasm::Ref> wasm::Ref::copy() const { |
2372 | 0 | return static_cast<const wasm_ref_t *>(this)->copy_ref(); |
2373 | 0 | } |
2374 | | |
2375 | 0 | bool wasm::Ref::same(const wasm::Ref *that) const { |
2376 | 0 | return static_cast<const wasm_ref_t *>(this)->inner == |
2377 | 0 | static_cast<const wasm_ref_t *>(that)->inner; |
2378 | 0 | } |
2379 | | |
2380 | 0 | void *wasm::Ref::get_host_info() const { |
2381 | 0 | return static_cast<const wasm_ref_t *>(this)->info; |
2382 | 0 | } |
2383 | | |
2384 | 0 | void wasm::Ref::set_host_info(void *info, void (*finalizer)(void *)) { |
2385 | 0 | static_cast<wasm_ref_t *>(this)->info = info; |
2386 | 0 | static_cast<wasm_ref_t *>(this)->finalizer = finalizer; |
2387 | 0 | } |
2388 | | |
2389 | | // <<<<<<<< wasm::Ref functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2390 | | |
2391 | | // >>>>>>>> wasm::Frame functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2392 | | |
2393 | 0 | void wasm::Frame::destroy() { delete static_cast<wasm_frame_t *>(this); } |
2394 | | |
2395 | 0 | wasm::own<wasm::Frame> wasm::Frame::copy() const { |
2396 | 0 | return wasm::make_own(new (std::nothrow) wasm_frame_t( |
2397 | 0 | *static_cast<const wasm_frame_t *>(this))); |
2398 | 0 | } |
2399 | | |
2400 | 0 | wasm::Instance *wasm::Frame::instance() const { |
2401 | | // TODO: Not supported yet. |
2402 | 0 | return nullptr; |
2403 | 0 | } |
2404 | | |
2405 | 0 | uint32_t wasm::Frame::func_index() const { |
2406 | 0 | return static_cast<const wasm_frame_t *>(this)->funcidx; |
2407 | 0 | } |
2408 | | |
2409 | 0 | size_t wasm::Frame::func_offset() const { |
2410 | | // Not implemented yet: stored field is always 0. |
2411 | 0 | return static_cast<const wasm_frame_t *>(this)->funcoff; |
2412 | 0 | } |
2413 | | |
2414 | 0 | size_t wasm::Frame::module_offset() const { |
2415 | | // Not implemented yet: stored field is always 0. |
2416 | 0 | return static_cast<const wasm_frame_t *>(this)->moduleoff; |
2417 | 0 | } |
2418 | | |
2419 | | // <<<<<<<< wasm::Frame functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2420 | | |
2421 | | // >>>>>>>> wasm::Trap functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2422 | | |
2423 | 0 | void wasm::Trap::destroy() { static_cast<wasm_trap_t *>(this)->decrease_ref(); } |
2424 | | |
2425 | | wasm::own<wasm::Trap> wasm::Trap::make(wasm::Store *store, |
2426 | 0 | const wasm::Message &msg) { |
2427 | 0 | if (store) { |
2428 | 0 | return wasm::make_own(new (std::nothrow) wasm_trap_t(store, msg.copy())); |
2429 | 0 | } |
2430 | 0 | return nullptr; |
2431 | 0 | } |
2432 | | |
2433 | 0 | wasm::own<wasm::Trap> wasm::Trap::copy() const { |
2434 | 0 | return static_cast<const wasm_trap_t *>(this)->copy_ref(); |
2435 | 0 | } |
2436 | | |
2437 | 0 | wasm::Message wasm::Trap::message() const { |
2438 | 0 | return static_cast<const wasm_trap_t *>(this)->mmsg.copy(); |
2439 | 0 | } |
2440 | | |
2441 | 0 | wasm::own<wasm::Frame> wasm::Trap::origin() const { |
2442 | 0 | const auto &slot = static_cast<const wasm_trap_t *>(this)->morigin; |
2443 | 0 | return wasm::make_own(new (std::nothrow) wasm_frame_t(slot)); |
2444 | 0 | } |
2445 | | |
2446 | 0 | wasm::ownvec<wasm::Frame> wasm::Trap::trace() const { |
2447 | 0 | const auto &slot = static_cast<const wasm_trap_t *>(this)->morigin; |
2448 | 0 | auto v = wasm::ownvec<wasm::Frame>::make_uninitialized(1); |
2449 | 0 | v[0] = wasm::make_own(new (std::nothrow) wasm_frame_t(slot)); |
2450 | 0 | return v; |
2451 | 0 | } |
2452 | | |
2453 | | // <<<<<<<< wasm::Trap functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2454 | | |
2455 | | // >>>>>>>> wasm::Foreign functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2456 | | |
2457 | 0 | void wasm::Foreign::destroy() { |
2458 | 0 | static_cast<wasm_foreign_t *>(this)->decrease_ref(); |
2459 | 0 | } |
2460 | | |
2461 | 0 | wasm::own<wasm::Foreign> wasm::Foreign::make(wasm::Store *store) { |
2462 | 0 | if (store) { |
2463 | 0 | return wasm::make_own(new (std::nothrow) wasm_foreign_t(store)); |
2464 | 0 | } |
2465 | 0 | return nullptr; |
2466 | 0 | } |
2467 | | |
2468 | 0 | wasm::own<wasm::Foreign> wasm::Foreign::copy() const { |
2469 | 0 | return static_cast<const wasm_foreign_t *>(this)->copy_ref(); |
2470 | 0 | } |
2471 | | |
2472 | | // <<<<<<<< wasm::Foreign functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2473 | | |
2474 | | // >>>>>>>> wasm::Modules functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2475 | | |
2476 | 0 | void wasm::Module::destroy() { |
2477 | 0 | static_cast<wasm_module_t *>(this)->decrease_ref(); |
2478 | 0 | } |
2479 | | |
2480 | | bool wasm::Module::validate(wasm::Store *store, |
2481 | 0 | const wasm::vec<byte_t> &binary) { |
2482 | 0 | if (store) { |
2483 | 0 | auto mod = static_cast<wasm_store_t *>(store)->load.parseModule( |
2484 | 0 | WasmEdge::Span<const uint8_t>( |
2485 | 0 | reinterpret_cast<const uint8_t *>(binary.get()), binary.size())); |
2486 | 0 | if (!mod) { |
2487 | 0 | return false; |
2488 | 0 | } |
2489 | 0 | auto valid = |
2490 | 0 | static_cast<wasm_store_t *>(store)->valid.validate(*mod->get()); |
2491 | 0 | if (valid) { |
2492 | 0 | return true; |
2493 | 0 | } |
2494 | 0 | } |
2495 | 0 | return false; |
2496 | 0 | } |
2497 | | |
2498 | | wasm::own<wasm::Module> wasm::Module::make(wasm::Store *store, |
2499 | 0 | const wasm::vec<byte_t> &binary) { |
2500 | 0 | if (store) { |
2501 | 0 | auto *cstore = static_cast<wasm_store_t *>(store); |
2502 | 0 | auto mod = cstore->load.parseModule(WasmEdge::Span<const uint8_t>( |
2503 | 0 | reinterpret_cast<const uint8_t *>(binary.get()), binary.size())); |
2504 | 0 | if (mod) { |
2505 | | // The executor requires a validated module before instantiation. |
2506 | 0 | if (auto valid = cstore->valid.validate(*mod->get()); !valid) { |
2507 | 0 | return nullptr; |
2508 | 0 | } |
2509 | 0 | return wasm::make_own(new (std::nothrow) wasm_module_t( |
2510 | 0 | store, std::move(*mod), binary.copy())); |
2511 | 0 | } |
2512 | 0 | } |
2513 | 0 | return nullptr; |
2514 | 0 | } |
2515 | | |
2516 | 0 | wasm::own<wasm::Module> wasm::Module::copy() const { |
2517 | 0 | return static_cast<const wasm_module_t *>(this)->copy_ref(); |
2518 | 0 | } |
2519 | | |
2520 | 0 | wasm::ownvec<wasm::ImportType> wasm::Module::imports() const { |
2521 | 0 | const auto &importvec = static_cast<const wasm_module_t *>(this) |
2522 | 0 | ->ast->getImportSection() |
2523 | 0 | .getContent(); |
2524 | | // The size of std::vector is not necessary to be checked. |
2525 | 0 | auto v = wasm::ownvec<wasm::ImportType>::make_uninitialized(importvec.size()); |
2526 | 0 | for (size_t i = 0; i < v.size(); ++i) { |
2527 | 0 | auto modname = wasm::Name::make(std::string(importvec[i].getModuleName())); |
2528 | 0 | auto extname = |
2529 | 0 | wasm::Name::make(std::string(importvec[i].getExternalName())); |
2530 | 0 | wasm::own<wasm::ExternType> type; |
2531 | 0 | switch (importvec[i].getExternalType()) { |
2532 | 0 | case WasmEdge::ExternalType::Function: { |
2533 | 0 | auto typeidx = importvec[i].getExternalFuncTypeIdx(); |
2534 | 0 | const auto &functype = static_cast<const wasm_module_t *>(this) |
2535 | 0 | ->ast->getTypeSection() |
2536 | 0 | .getContent()[typeidx] |
2537 | 0 | .getCompositeType() |
2538 | 0 | .getFuncType(); |
2539 | 0 | type = make_functype_from_wasmedge(functype); |
2540 | 0 | break; |
2541 | 0 | } |
2542 | 0 | case WasmEdge::ExternalType::Table: { |
2543 | 0 | type = make_tabletype_from_wasmedge(importvec[i].getExternalTableType()); |
2544 | 0 | break; |
2545 | 0 | } |
2546 | 0 | case WasmEdge::ExternalType::Memory: { |
2547 | 0 | type = |
2548 | 0 | make_memorytype_from_wasmedge(importvec[i].getExternalMemoryType()); |
2549 | 0 | break; |
2550 | 0 | } |
2551 | 0 | case WasmEdge::ExternalType::Global: { |
2552 | 0 | type = |
2553 | 0 | make_globaltype_from_wasmedge(importvec[i].getExternalGlobalType()); |
2554 | 0 | break; |
2555 | 0 | } |
2556 | 0 | case WasmEdge::ExternalType::Tag: { |
2557 | 0 | type = make_tagtype_from_wasmedge( |
2558 | 0 | importvec[i].getExternalTagType().getDefType()); |
2559 | 0 | break; |
2560 | 0 | } |
2561 | 0 | default: |
2562 | 0 | assumingUnreachable(); |
2563 | 0 | } |
2564 | 0 | v[i] = wasm::make_own(new (std::nothrow) wasm_importtype_t( |
2565 | 0 | std::move(modname), std::move(extname), std::move(type))); |
2566 | 0 | } |
2567 | 0 | return v; |
2568 | 0 | } |
2569 | | |
2570 | 0 | wasm::ownvec<wasm::ExportType> wasm::Module::exports() const { |
2571 | | // Accumulate the imported instances. |
2572 | 0 | const auto &importvec = static_cast<const wasm_module_t *>(this) |
2573 | 0 | ->ast->getImportSection() |
2574 | 0 | .getContent(); |
2575 | 0 | size_t impfunc = 0; |
2576 | 0 | size_t imptable = 0; |
2577 | 0 | size_t impmemory = 0; |
2578 | 0 | size_t impglobal = 0; |
2579 | 0 | size_t imptag = 0; |
2580 | 0 | for (size_t i = 0; i < importvec.size(); ++i) { |
2581 | 0 | switch (importvec[i].getExternalType()) { |
2582 | 0 | case WasmEdge::ExternalType::Function: |
2583 | 0 | ++impfunc; |
2584 | 0 | break; |
2585 | 0 | case WasmEdge::ExternalType::Table: |
2586 | 0 | ++imptable; |
2587 | 0 | break; |
2588 | 0 | case WasmEdge::ExternalType::Memory: |
2589 | 0 | ++impmemory; |
2590 | 0 | break; |
2591 | 0 | case WasmEdge::ExternalType::Global: |
2592 | 0 | ++impglobal; |
2593 | 0 | break; |
2594 | 0 | case WasmEdge::ExternalType::Tag: |
2595 | 0 | ++imptag; |
2596 | 0 | break; |
2597 | 0 | default: |
2598 | 0 | assumingUnreachable(); |
2599 | 0 | } |
2600 | 0 | } |
2601 | | |
2602 | 0 | const auto &exportvec = static_cast<const wasm_module_t *>(this) |
2603 | 0 | ->ast->getExportSection() |
2604 | 0 | .getContent(); |
2605 | | // The size of std::vector is not necessary to be checked. |
2606 | 0 | auto v = wasm::ownvec<wasm::ExportType>::make_uninitialized(exportvec.size()); |
2607 | 0 | for (size_t i = 0; i < v.size(); ++i) { |
2608 | 0 | auto extname = |
2609 | 0 | wasm::Name::make(std::string(exportvec[i].getExternalName())); |
2610 | 0 | auto extidx = exportvec[i].getExternalIndex(); |
2611 | 0 | wasm::own<wasm::ExternType> type; |
2612 | 0 | switch (exportvec[i].getExternalType()) { |
2613 | | // The real index = external_index - import_num. |
2614 | 0 | case WasmEdge::ExternalType::Function: { |
2615 | 0 | auto typeidx = static_cast<const wasm_module_t *>(this) |
2616 | 0 | ->ast->getFunctionSection() |
2617 | 0 | .getContent()[extidx - impfunc]; |
2618 | 0 | const auto &functype = static_cast<const wasm_module_t *>(this) |
2619 | 0 | ->ast->getTypeSection() |
2620 | 0 | .getContent()[typeidx] |
2621 | 0 | .getCompositeType() |
2622 | 0 | .getFuncType(); |
2623 | 0 | type = make_functype_from_wasmedge(functype); |
2624 | 0 | break; |
2625 | 0 | } |
2626 | 0 | case WasmEdge::ExternalType::Table: { |
2627 | 0 | const auto &tabletype = static_cast<const wasm_module_t *>(this) |
2628 | 0 | ->ast->getTableSection() |
2629 | 0 | .getContent()[extidx - imptable] |
2630 | 0 | .getTableType(); |
2631 | 0 | type = make_tabletype_from_wasmedge(tabletype); |
2632 | 0 | break; |
2633 | 0 | } |
2634 | 0 | case WasmEdge::ExternalType::Memory: { |
2635 | 0 | const auto &memorytype = static_cast<const wasm_module_t *>(this) |
2636 | 0 | ->ast->getMemorySection() |
2637 | 0 | .getContent()[extidx - impmemory]; |
2638 | 0 | type = make_memorytype_from_wasmedge(memorytype); |
2639 | 0 | break; |
2640 | 0 | } |
2641 | 0 | case WasmEdge::ExternalType::Global: { |
2642 | 0 | const auto &globaltype = static_cast<const wasm_module_t *>(this) |
2643 | 0 | ->ast->getGlobalSection() |
2644 | 0 | .getContent()[extidx - impglobal] |
2645 | 0 | .getGlobalType(); |
2646 | 0 | type = make_globaltype_from_wasmedge(globaltype); |
2647 | 0 | break; |
2648 | 0 | } |
2649 | 0 | case WasmEdge::ExternalType::Tag: { |
2650 | 0 | const auto &tag = static_cast<const wasm_module_t *>(this) |
2651 | 0 | ->ast->getTagSection() |
2652 | 0 | .getContent()[extidx - imptag]; |
2653 | 0 | type = make_tagtype_from_wasmedge(tag.getDefType()); |
2654 | 0 | break; |
2655 | 0 | } |
2656 | 0 | default: |
2657 | 0 | assumingUnreachable(); |
2658 | 0 | } |
2659 | 0 | v[i] = wasm::make_own(new (std::nothrow) wasm_exporttype_t( |
2660 | 0 | std::move(extname), std::move(type))); |
2661 | 0 | } |
2662 | 0 | return v; |
2663 | 0 | } |
2664 | | |
2665 | 0 | wasm::own<wasm::Shared<wasm::Module>> wasm::Module::share() const { |
2666 | 0 | return wasm::make_own(new (std::nothrow) wasm_shared_module_t( |
2667 | 0 | static_cast<const wasm_module_t *>(this)->binary.copy())); |
2668 | 0 | } |
2669 | | |
2670 | | wasm::own<wasm::Module> |
2671 | | wasm::Module::obtain(wasm::Store *store, |
2672 | 0 | const wasm::Shared<wasm::Module> *module) { |
2673 | 0 | return wasm::Module::deserialize( |
2674 | 0 | store, static_cast<const wasm_shared_module_t *>(module)->binary); |
2675 | 0 | } |
2676 | | |
2677 | 0 | wasm::vec<byte_t> wasm::Module::serialize() const { |
2678 | | // Re-emit the AST as canonical wasm binary via WasmEdge's Serializer. On |
2679 | | // failure (e.g. unsupported AST feature) fall back to the original binary |
2680 | | // so the wasm-c-api round-trip contract (serialize → deserialize → equiv |
2681 | | // module) still holds. |
2682 | 0 | auto *self = static_cast<const wasm_module_t *>(this); |
2683 | 0 | if (self->ast && self->store) { |
2684 | 0 | if (auto bytes = self->store->load.serializeModule(*self->ast)) { |
2685 | 0 | auto out = wasm::vec<byte_t>::make_uninitialized(bytes->size()); |
2686 | 0 | std::copy(bytes->begin(), bytes->end(), out.get()); |
2687 | 0 | return out; |
2688 | 0 | } |
2689 | 0 | } |
2690 | 0 | return self->binary.copy(); |
2691 | 0 | } |
2692 | | |
2693 | | wasm::own<wasm::Module> |
2694 | | wasm::Module::deserialize(wasm::Store *store, |
2695 | 0 | const wasm::vec<byte_t> &vec_byte) { |
2696 | | // The serialized form is canonical wasm binary; re-parse via the regular |
2697 | | // module-loading path. |
2698 | 0 | return make(store, vec_byte); |
2699 | 0 | } |
2700 | | |
2701 | | // <<<<<<<< wasm::Modules functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2702 | | |
2703 | | // >>>>>>>> wasm::Shared functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2704 | | |
2705 | 0 | void wasm::Shared<wasm::Module>::destroy() { |
2706 | 0 | delete static_cast<wasm_shared_module_t *>(this); |
2707 | 0 | } |
2708 | | |
2709 | | // <<<<<<<< wasm::Shared functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2710 | | |
2711 | | // >>>>>>>> wasm::Func functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2712 | | |
2713 | 0 | void wasm::Func::destroy() { static_cast<wasm_func_t *>(this)->decrease_ref(); } |
2714 | | |
2715 | | wasm::own<wasm::Func> wasm::Func::make(wasm::Store *store, |
2716 | | const wasm::FuncType *type, |
2717 | 0 | wasm::Func::callback callback) { |
2718 | 0 | if (store && type && callback) { |
2719 | 0 | return wasm::make_own(new (std::nothrow) |
2720 | 0 | wasm_func_t(store, *type, callback)); |
2721 | 0 | } |
2722 | 0 | return nullptr; |
2723 | 0 | } |
2724 | | |
2725 | | wasm::own<wasm::Func> wasm::Func::make(wasm::Store *store, |
2726 | | const wasm::FuncType *type, |
2727 | | wasm::Func::callback_with_env callback, |
2728 | 0 | void *env, void (*finalizer)(void *)) { |
2729 | 0 | if (store && type && callback) { |
2730 | 0 | return wasm::make_own( |
2731 | 0 | new (std::nothrow) wasm_func_t(store, *type, callback, env, finalizer)); |
2732 | 0 | } |
2733 | 0 | return nullptr; |
2734 | 0 | } |
2735 | | |
2736 | 0 | wasm::own<wasm::Func> wasm::Func::copy() const { |
2737 | 0 | return static_cast<const wasm_func_t *>(this)->copy_ref(); |
2738 | 0 | } |
2739 | | |
2740 | 0 | wasm::own<wasm::FuncType> wasm::Func::type() const { |
2741 | 0 | if (static_cast<const wasm_func_t *>(this)->inst) { |
2742 | 0 | const auto &type = |
2743 | 0 | static_cast<const wasm_func_t *>(this)->inst->getFuncType(); |
2744 | 0 | auto vp = |
2745 | 0 | wasm::ownvec<ValType>::make_uninitialized(type.getParamTypes().size()); |
2746 | 0 | auto vr = |
2747 | 0 | wasm::ownvec<ValType>::make_uninitialized(type.getReturnTypes().size()); |
2748 | 0 | for (size_t i = 0; i < type.getParamTypes().size(); ++i) { |
2749 | 0 | vp[i] = wasm::ValType::make( |
2750 | 0 | conv_valtype_from_wasmedge(type.getParamTypes()[i])); |
2751 | 0 | } |
2752 | 0 | for (size_t i = 0; i < type.getReturnTypes().size(); ++i) { |
2753 | 0 | vr[i] = wasm::ValType::make( |
2754 | 0 | conv_valtype_from_wasmedge(type.getReturnTypes()[i])); |
2755 | 0 | } |
2756 | 0 | return wasm::FuncType::make(std::move(vp), std::move(vr)); |
2757 | 0 | } |
2758 | 0 | return wasm::FuncType::make(); |
2759 | 0 | } |
2760 | | |
2761 | 0 | size_t wasm::Func::param_arity() const { |
2762 | 0 | const auto *inst = static_cast<const wasm_func_t *>(this)->inst; |
2763 | 0 | if (inst) { |
2764 | 0 | return static_cast<size_t>(inst->getFuncType().getParamTypes().size()); |
2765 | 0 | } |
2766 | 0 | return 0; |
2767 | 0 | } |
2768 | | |
2769 | 0 | size_t wasm::Func::result_arity() const { |
2770 | 0 | const auto *inst = static_cast<const wasm_func_t *>(this)->inst; |
2771 | 0 | if (inst) { |
2772 | 0 | return static_cast<size_t>(inst->getFuncType().getReturnTypes().size()); |
2773 | 0 | } |
2774 | 0 | return 0; |
2775 | 0 | } |
2776 | | |
2777 | | wasm::own<wasm::Trap> wasm::Func::call(const wasm::vec<wasm::Val> &args, |
2778 | 0 | wasm::vec<wasm::Val> &results) const { |
2779 | 0 | auto *self = static_cast<const wasm_func_t *>(this); |
2780 | 0 | if (!self->inst) { |
2781 | 0 | return nullptr; |
2782 | 0 | } |
2783 | 0 | const auto &ftype = self->inst->getFuncType(); |
2784 | 0 | const auto &ptypes = ftype.getParamTypes(); |
2785 | 0 | const auto &rtypes = ftype.getReturnTypes(); |
2786 | |
|
2787 | 0 | std::vector<WasmEdge::ValVariant> params(ptypes.size()); |
2788 | 0 | for (size_t i = 0; i < ptypes.size() && i < args.size(); ++i) { |
2789 | 0 | params[i] = conv_cppval_to_wasmedge(args[i]); |
2790 | 0 | } |
2791 | |
|
2792 | 0 | auto res = self->store->engine->exec.invoke(self->inst, params, ptypes); |
2793 | 0 | if (!res) { |
2794 | 0 | return buildTrap(self->store, res.error(), lookupFuncIdx(self->inst)); |
2795 | 0 | } |
2796 | 0 | if (results.size() < rtypes.size()) { |
2797 | 0 | results = wasm::vec<wasm::Val>::make_uninitialized(rtypes.size()); |
2798 | 0 | } |
2799 | 0 | for (size_t i = 0; i < rtypes.size(); ++i) { |
2800 | 0 | results[i] = conv_cppval_from_wasmedge((*res)[i].first, rtypes[i]); |
2801 | 0 | } |
2802 | 0 | return nullptr; |
2803 | 0 | } |
2804 | | |
2805 | | // <<<<<<<< wasm::Func functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2806 | | |
2807 | | // >>>>>>>> wasm::Global functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2808 | | |
2809 | 0 | void wasm::Global::destroy() { |
2810 | 0 | static_cast<wasm_global_t *>(this)->decrease_ref(); |
2811 | 0 | } |
2812 | | |
2813 | | wasm::own<wasm::Global> wasm::Global::make(wasm::Store *store, |
2814 | | const wasm::GlobalType *type, |
2815 | 0 | const wasm::Val &val) { |
2816 | 0 | if (store && type) { |
2817 | 0 | return wasm::make_own(new (std::nothrow) wasm_global_t(store, *type, val)); |
2818 | 0 | } |
2819 | 0 | return nullptr; |
2820 | 0 | } |
2821 | | |
2822 | 0 | wasm::own<wasm::Global> wasm::Global::copy() const { |
2823 | 0 | return static_cast<const wasm_global_t *>(this)->copy_ref(); |
2824 | 0 | } |
2825 | | |
2826 | 0 | wasm::own<wasm::GlobalType> wasm::Global::type() const { |
2827 | 0 | const auto &type = |
2828 | 0 | static_cast<const wasm_global_t *>(this)->inst->getGlobalType(); |
2829 | 0 | return wasm::GlobalType::make( |
2830 | 0 | wasm::ValType::make(conv_valtype_from_wasmedge(type.getValType())), |
2831 | 0 | conv_valmut_from_wasmedge(type.getValMut())); |
2832 | 0 | } |
2833 | | |
2834 | 0 | wasm::Val wasm::Global::get() const { |
2835 | 0 | auto *inst = static_cast<const wasm_global_t *>(this)->inst; |
2836 | 0 | return conv_cppval_from_wasmedge(inst->getValue(), |
2837 | 0 | inst->getGlobalType().getValType()); |
2838 | 0 | } |
2839 | | |
2840 | 0 | void wasm::Global::set(const wasm::Val &val) { |
2841 | | // Replace the kept init value here. If the value type is a reference, this |
2842 | | // will help to keep the reference count. |
2843 | 0 | auto *global = static_cast<wasm_global_t *>(this); |
2844 | 0 | global->keepval = val.copy(); |
2845 | 0 | global->inst->getValue() = conv_cppval_to_wasmedge(val); |
2846 | 0 | } |
2847 | | |
2848 | | // <<<<<<<< wasm::Global functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2849 | | |
2850 | | // >>>>>>>> wasm::Table functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2851 | | |
2852 | 0 | void wasm::Table::destroy() { |
2853 | 0 | static_cast<wasm_table_t *>(this)->decrease_ref(); |
2854 | 0 | } |
2855 | | |
2856 | | wasm::own<wasm::Table> wasm::Table::make(wasm::Store *store, |
2857 | | const wasm::TableType *type, |
2858 | 0 | const wasm::Ref *init) { |
2859 | 0 | if (store && type) { |
2860 | 0 | return wasm::make_own(new (std::nothrow) wasm_table_t(store, *type, init)); |
2861 | 0 | } |
2862 | 0 | return nullptr; |
2863 | 0 | } |
2864 | | |
2865 | 0 | wasm::own<wasm::Table> wasm::Table::copy() const { |
2866 | 0 | return static_cast<const wasm_table_t *>(this)->copy_ref(); |
2867 | 0 | } |
2868 | | |
2869 | 0 | wasm::own<wasm::TableType> wasm::Table::type() const { |
2870 | 0 | const auto &type = |
2871 | 0 | static_cast<const wasm_table_t *>(this)->inst->getTableType(); |
2872 | 0 | return wasm::TableType::make( |
2873 | 0 | wasm::ValType::make(conv_reftype_from_wasmedge(type.getRefType())), |
2874 | 0 | type.getLimit().hasMax() |
2875 | 0 | ? wasm::Limits(static_cast<uint32_t>(type.getLimit().getMin()), |
2876 | 0 | static_cast<uint32_t>(type.getLimit().getMax())) |
2877 | 0 | : wasm::Limits(static_cast<uint32_t>(type.getLimit().getMin()))); |
2878 | 0 | } |
2879 | | |
2880 | 0 | wasm::own<wasm::Ref> wasm::Table::get(wasm::Table::size_t index) const { |
2881 | 0 | auto *self = static_cast<const wasm_table_t *>(this); |
2882 | 0 | auto *inst = self->inst; |
2883 | 0 | if (auto res = inst->getRefAddr(static_cast<uint32_t>(index)); |
2884 | 0 | res && !(*res).isNull()) { |
2885 | 0 | if (inst->getTableType().getRefType().isFuncRefType()) { |
2886 | | // Non-owning wrap; the FunctionInstance lives in the table's module. |
2887 | 0 | auto *fi = (*res).getPtr<WasmEdge::Runtime::Instance::FunctionInstance>(); |
2888 | 0 | if (!fi) { |
2889 | 0 | return nullptr; |
2890 | 0 | } |
2891 | 0 | auto *wf = new (std::nothrow) wasm_func_t(self->store, fi); |
2892 | 0 | return wasm::own<wasm::Ref>( |
2893 | 0 | static_cast<wasm::Ref *>(static_cast<wasm::Func *>(wf))); |
2894 | 0 | } else { |
2895 | 0 | auto *ref = (*res).getPtr<wasm_ref_t>(); |
2896 | 0 | return ref ? ref->copy_ref() : nullptr; |
2897 | 0 | } |
2898 | 0 | } |
2899 | 0 | return nullptr; |
2900 | 0 | } |
2901 | | |
2902 | 0 | bool wasm::Table::set(wasm::Table::size_t index, const wasm::Ref *ref) { |
2903 | 0 | auto *inst = static_cast<wasm_table_t *>(this)->inst; |
2904 | 0 | if (inst->getTableType().getRefType().isExternRefType()) { |
2905 | | // For the externref of the element type, set the ref. |
2906 | 0 | if (inst->setRefAddr(static_cast<uint32_t>(index), |
2907 | 0 | WasmEdge::RefVariant(const_cast<wasm::Ref *>(ref)))) { |
2908 | 0 | return true; |
2909 | 0 | } |
2910 | 0 | } else { |
2911 | | // Funcref slot: ref was produced via wasm_func_as_ref, so we can recover |
2912 | | // the wasm_func_t through the wasm::Func subobject. |
2913 | 0 | if (ref) { |
2914 | 0 | auto *cfunc = |
2915 | 0 | static_cast<const wasm_func_t *>(static_cast<const wasm::Func *>( |
2916 | 0 | static_cast<const wasm::Extern *>(ref))); |
2917 | 0 | if (cfunc->inst && |
2918 | 0 | inst->setRefAddr(index, WasmEdge::RefVariant(cfunc->inst))) { |
2919 | 0 | return true; |
2920 | 0 | } |
2921 | 0 | } else { |
2922 | 0 | if (inst->setRefAddr(index, WasmEdge::RefVariant(WasmEdge::ValType( |
2923 | 0 | WasmEdge::TypeCode::FuncRef)))) { |
2924 | 0 | return true; |
2925 | 0 | } |
2926 | 0 | } |
2927 | 0 | } |
2928 | 0 | return false; |
2929 | 0 | } |
2930 | | |
2931 | 0 | wasm::Table::size_t wasm::Table::size() const { |
2932 | 0 | return static_cast<wasm::Table::size_t>( |
2933 | 0 | static_cast<const wasm_table_t *>(this)->inst->getSize()); |
2934 | 0 | } |
2935 | | |
2936 | 0 | bool wasm::Table::grow(wasm::Table::size_t delta, const wasm::Ref *ref) { |
2937 | 0 | size_t orig = size(); |
2938 | 0 | if (static_cast<wasm_table_t *>(this)->inst->growTable( |
2939 | 0 | static_cast<uint32_t>(delta))) { |
2940 | 0 | for (size_t i = orig; i < orig + delta; ++i) { |
2941 | 0 | set(i, ref); |
2942 | 0 | } |
2943 | 0 | return true; |
2944 | 0 | } else { |
2945 | 0 | return false; |
2946 | 0 | } |
2947 | 0 | } |
2948 | | |
2949 | | // <<<<<<<< wasm::Table functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
2950 | | |
2951 | | // >>>>>>>> wasm::Memory functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
2952 | | |
2953 | 0 | void wasm::Memory::destroy() { |
2954 | 0 | static_cast<wasm_memory_t *>(this)->decrease_ref(); |
2955 | 0 | } |
2956 | | |
2957 | | wasm::own<wasm::Memory> wasm::Memory::make(wasm::Store *store, |
2958 | 0 | const wasm::MemoryType *type) { |
2959 | 0 | if (store && type) { |
2960 | 0 | return wasm::make_own(new (std::nothrow) wasm_memory_t(store, *type)); |
2961 | 0 | } |
2962 | 0 | return nullptr; |
2963 | 0 | } |
2964 | | |
2965 | 0 | wasm::own<wasm::Memory> wasm::Memory::copy() const { |
2966 | 0 | return static_cast<const wasm_memory_t *>(this)->copy_ref(); |
2967 | 0 | } |
2968 | | |
2969 | 0 | wasm::own<wasm::MemoryType> wasm::Memory::type() const { |
2970 | 0 | const auto &type = |
2971 | 0 | static_cast<const wasm_memory_t *>(this)->inst->getMemoryType(); |
2972 | 0 | return wasm::MemoryType::make( |
2973 | 0 | type.getLimit().hasMax() |
2974 | 0 | ? wasm::Limits(static_cast<uint32_t>(type.getLimit().getMin()), |
2975 | 0 | static_cast<uint32_t>(type.getLimit().getMax())) |
2976 | 0 | : wasm::Limits(static_cast<uint32_t>(type.getLimit().getMin()))); |
2977 | 0 | } |
2978 | | |
2979 | 0 | byte_t *wasm::Memory::data() const { |
2980 | 0 | return static_cast<const wasm_memory_t *>(this)->inst->getPointer<byte_t *>( |
2981 | 0 | 0); |
2982 | 0 | } |
2983 | | |
2984 | 0 | size_t wasm::Memory::data_size() const { |
2985 | 0 | return static_cast<size_t>( |
2986 | 0 | static_cast<const wasm_memory_t *>(this)->inst->getPageSize() * |
2987 | 0 | wasm::Memory::page_size); |
2988 | 0 | } |
2989 | | |
2990 | 0 | wasm::Memory::pages_t wasm::Memory::size() const { |
2991 | 0 | return static_cast<wasm::Memory::pages_t>( |
2992 | 0 | static_cast<const wasm_memory_t *>(this)->inst->getPageSize()); |
2993 | 0 | } |
2994 | | |
2995 | 0 | bool wasm::Memory::grow(wasm::Memory::pages_t delta) { |
2996 | 0 | if (static_cast<wasm_memory_t *>(this)->inst->growPage( |
2997 | 0 | static_cast<uint32_t>(delta))) { |
2998 | 0 | return true; |
2999 | 0 | } else { |
3000 | 0 | return false; |
3001 | 0 | } |
3002 | 0 | } |
3003 | | |
3004 | | // <<<<<<<< wasm::Memory functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
3005 | | |
3006 | | // >>>>>>>> wasm::Extern functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
3007 | | |
3008 | 0 | void wasm::Extern::destroy() { |
3009 | 0 | static_cast<wasm_extern_t *>(this)->decrease_ref(); |
3010 | 0 | } |
3011 | | |
3012 | 0 | wasm::own<wasm::Extern> wasm::Extern::copy() const { |
3013 | 0 | return static_cast<const wasm_extern_t *>(this)->copy_ref(); |
3014 | 0 | } |
3015 | | |
3016 | 0 | wasm::ExternKind wasm::Extern::kind() const { |
3017 | 0 | return static_cast<const wasm_extern_t *>(this)->mkind; |
3018 | 0 | } |
3019 | | |
3020 | 0 | wasm::own<wasm::ExternType> wasm::Extern::type() const { |
3021 | 0 | switch (kind()) { |
3022 | 0 | case wasm::ExternKind::FUNC: |
3023 | 0 | return func()->type(); |
3024 | 0 | case wasm::ExternKind::GLOBAL: |
3025 | 0 | return global()->type(); |
3026 | 0 | case wasm::ExternKind::TABLE: |
3027 | 0 | return table()->type(); |
3028 | 0 | case wasm::ExternKind::MEMORY: |
3029 | 0 | return memory()->type(); |
3030 | 0 | default: |
3031 | 0 | assumingUnreachable(); |
3032 | 0 | } |
3033 | 0 | } |
3034 | | |
3035 | | WASM_EXTERNTYPE_CPP_CONV(func, Func, , FUNC, ) |
3036 | | WASM_EXTERNTYPE_CPP_CONV(func, Func, , FUNC, const) |
3037 | | WASM_EXTERNTYPE_CPP_CONV(global, Global, , GLOBAL, ) |
3038 | | WASM_EXTERNTYPE_CPP_CONV(global, Global, , GLOBAL, const) |
3039 | | WASM_EXTERNTYPE_CPP_CONV(table, Table, , TABLE, ) |
3040 | | WASM_EXTERNTYPE_CPP_CONV(table, Table, , TABLE, const) |
3041 | | WASM_EXTERNTYPE_CPP_CONV(memory, Memory, , MEMORY, ) |
3042 | | WASM_EXTERNTYPE_CPP_CONV(memory, Memory, , MEMORY, const) |
3043 | | |
3044 | | // <<<<<<<< wasm::Extern functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
3045 | | |
3046 | | // >>>>>>>> wasm::Instance functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
3047 | | |
3048 | 0 | void wasm::Instance::destroy() { |
3049 | 0 | static_cast<wasm_instance_t *>(this)->decrease_ref(); |
3050 | 0 | } |
3051 | | |
3052 | | wasm::own<wasm::Instance> |
3053 | | wasm::Instance::make(wasm::Store *store, const wasm::Module *module, |
3054 | | const wasm::vec<wasm::Extern *> &imports, |
3055 | 0 | own<wasm::Trap> *trap_out) { |
3056 | 0 | if (trap_out) { |
3057 | 0 | *trap_out = nullptr; |
3058 | 0 | } |
3059 | 0 | if (!store || !module) { |
3060 | 0 | return nullptr; |
3061 | 0 | } |
3062 | 0 | auto *cstore = static_cast<wasm_store_t *>(store); |
3063 | 0 | auto *cmodule = static_cast<const wasm_module_t *>(module); |
3064 | | |
3065 | | // The user's imports vec must align positionally with the module's import |
3066 | | // declarations; reject up front if the sizes don't match. |
3067 | 0 | const auto &importsec = cmodule->ast->getImportSection().getContent(); |
3068 | 0 | if (imports.size() < importsec.size()) { |
3069 | 0 | return nullptr; |
3070 | 0 | } |
3071 | | |
3072 | | // One shim per distinct module-name (executor resolves by name). |
3073 | 0 | std::unordered_map<std::string, std::unique_ptr<wasm_import_module_t>> modmap; |
3074 | | // Retain each host-provided import for the instance's lifetime; the import |
3075 | | // shim only borrows the underlying runtime instance pointer. |
3076 | 0 | std::vector<wasm::own<wasm::Extern>> retainedImports; |
3077 | 0 | retainedImports.reserve(importsec.size()); |
3078 | 0 | for (size_t i = 0; i < importsec.size(); ++i) { |
3079 | 0 | auto *ext = imports[i]; |
3080 | 0 | if (!ext) { |
3081 | 0 | return nullptr; |
3082 | 0 | } |
3083 | 0 | retainedImports.push_back(ext->copy()); |
3084 | 0 | auto modname = std::string(importsec[i].getModuleName()); |
3085 | 0 | auto name = std::string(importsec[i].getExternalName()); |
3086 | 0 | auto it = modmap.find(modname); |
3087 | 0 | if (it == modmap.end()) { |
3088 | 0 | it = |
3089 | 0 | modmap |
3090 | 0 | .emplace(modname, std::make_unique<wasm_import_module_t>(modname)) |
3091 | 0 | .first; |
3092 | 0 | } |
3093 | 0 | auto *modinst = it->second.get(); |
3094 | 0 | switch (ext->kind()) { |
3095 | 0 | case wasm::ExternKind::FUNC: { |
3096 | 0 | auto *cfunc = static_cast<wasm_func_t *>(ext->func()); |
3097 | 0 | if (!cfunc || !cfunc->inst) { |
3098 | 0 | return nullptr; |
3099 | 0 | } |
3100 | 0 | modinst->aliasFunc(name, cfunc->inst); |
3101 | 0 | break; |
3102 | 0 | } |
3103 | 0 | case wasm::ExternKind::GLOBAL: { |
3104 | 0 | auto *cglob = static_cast<wasm_global_t *>(ext->global()); |
3105 | 0 | if (!cglob || !cglob->inst) { |
3106 | 0 | return nullptr; |
3107 | 0 | } |
3108 | 0 | modinst->aliasGlobal(name, cglob->inst); |
3109 | 0 | break; |
3110 | 0 | } |
3111 | 0 | case wasm::ExternKind::TABLE: { |
3112 | 0 | auto *ctab = static_cast<wasm_table_t *>(ext->table()); |
3113 | 0 | if (!ctab || !ctab->inst) { |
3114 | 0 | return nullptr; |
3115 | 0 | } |
3116 | 0 | modinst->aliasTable(name, ctab->inst); |
3117 | 0 | break; |
3118 | 0 | } |
3119 | 0 | case wasm::ExternKind::MEMORY: { |
3120 | 0 | auto *cmem = static_cast<wasm_memory_t *>(ext->memory()); |
3121 | 0 | if (!cmem || !cmem->inst) { |
3122 | 0 | return nullptr; |
3123 | 0 | } |
3124 | 0 | modinst->aliasMemory(name, cmem->inst); |
3125 | 0 | break; |
3126 | 0 | } |
3127 | 0 | default: |
3128 | 0 | return nullptr; |
3129 | 0 | } |
3130 | 0 | } |
3131 | | |
3132 | | // Temporarily register each shim so instantiateModule can resolve imports |
3133 | | // by name; unregister all after to avoid collisions on later calls. |
3134 | 0 | std::vector<std::unique_ptr<wasm_import_module_t>> importmods; |
3135 | 0 | std::vector<std::string> registered; |
3136 | 0 | for (auto &kv : modmap) { |
3137 | 0 | if (auto reg = |
3138 | 0 | cstore->engine->exec.registerModule(cstore->store, *(kv.second)); |
3139 | 0 | !reg) { |
3140 | 0 | for (const auto &n : registered) { |
3141 | 0 | cstore->store.unregisterModule(n); |
3142 | 0 | } |
3143 | 0 | return nullptr; |
3144 | 0 | } |
3145 | 0 | registered.push_back(kv.first); |
3146 | 0 | importmods.push_back(std::move(kv.second)); |
3147 | 0 | } |
3148 | | |
3149 | | // Capture export order, since ModuleInstance's export maps are alphabetical. |
3150 | 0 | std::vector<wasm_instance_t::export_entry_t> exportorder; |
3151 | 0 | for (const auto &exp : cmodule->ast->getExportSection().getContent()) { |
3152 | 0 | exportorder.push_back( |
3153 | 0 | {std::string(exp.getExternalName()), exp.getExternalType()}); |
3154 | 0 | } |
3155 | | |
3156 | | // Instantiate, then unregister regardless of outcome. |
3157 | 0 | auto res = |
3158 | 0 | cstore->engine->exec.instantiateModule(cstore->store, *cmodule->ast); |
3159 | 0 | for (const auto &n : registered) { |
3160 | 0 | cstore->store.unregisterModule(n); |
3161 | 0 | } |
3162 | 0 | if (!res) { |
3163 | 0 | if (trap_out) { |
3164 | 0 | *trap_out = |
3165 | 0 | buildTrap(store, res.error(), |
3166 | 0 | cmodule->ast->getStartSection().getContent().value_or(0)); |
3167 | 0 | } |
3168 | 0 | return nullptr; |
3169 | 0 | } |
3170 | | |
3171 | 0 | return wasm::make_own(new (std::nothrow) wasm_instance_t( |
3172 | 0 | store, std::move(*res), std::move(importmods), std::move(retainedImports), |
3173 | 0 | std::move(exportorder))); |
3174 | 0 | } |
3175 | | |
3176 | 0 | wasm::own<wasm::Instance> wasm::Instance::copy() const { |
3177 | 0 | return static_cast<const wasm_instance_t *>(this)->copy_ref(); |
3178 | 0 | } |
3179 | | |
3180 | 0 | wasm::ownvec<wasm::Extern> wasm::Instance::exports() const { |
3181 | 0 | auto *self = static_cast<const wasm_instance_t *>(this); |
3182 | 0 | if (!self->modinst) { |
3183 | 0 | return wasm::ownvec<wasm::Extern>::make(); |
3184 | 0 | } |
3185 | 0 | auto v = |
3186 | 0 | wasm::ownvec<wasm::Extern>::make_uninitialized(self->exportorder.size()); |
3187 | 0 | for (size_t i = 0; i < self->exportorder.size(); ++i) { |
3188 | 0 | const auto &entry = self->exportorder[i]; |
3189 | 0 | switch (entry.kind) { |
3190 | 0 | case WasmEdge::ExternalType::Function: { |
3191 | 0 | auto *fi = self->modinst->findFuncExports(entry.name); |
3192 | 0 | if (!fi) { |
3193 | 0 | return wasm::ownvec<wasm::Extern>::make(); |
3194 | 0 | } |
3195 | 0 | v[i] = wasm::own<wasm::Extern>( |
3196 | 0 | static_cast<wasm::Extern *>(static_cast<wasm::Func *>( |
3197 | 0 | new (std::nothrow) wasm_func_t(self->store, fi)))); |
3198 | 0 | break; |
3199 | 0 | } |
3200 | 0 | case WasmEdge::ExternalType::Global: { |
3201 | 0 | auto *gi = self->modinst->findGlobalExports(entry.name); |
3202 | 0 | if (!gi) { |
3203 | 0 | return wasm::ownvec<wasm::Extern>::make(); |
3204 | 0 | } |
3205 | 0 | v[i] = wasm::own<wasm::Extern>( |
3206 | 0 | static_cast<wasm::Extern *>(static_cast<wasm::Global *>( |
3207 | 0 | new (std::nothrow) wasm_global_t(self->store, gi)))); |
3208 | 0 | break; |
3209 | 0 | } |
3210 | 0 | case WasmEdge::ExternalType::Table: { |
3211 | 0 | auto *ti = self->modinst->findTableExports(entry.name); |
3212 | 0 | if (!ti) { |
3213 | 0 | return wasm::ownvec<wasm::Extern>::make(); |
3214 | 0 | } |
3215 | 0 | v[i] = wasm::own<wasm::Extern>( |
3216 | 0 | static_cast<wasm::Extern *>(static_cast<wasm::Table *>( |
3217 | 0 | new (std::nothrow) wasm_table_t(self->store, ti)))); |
3218 | 0 | break; |
3219 | 0 | } |
3220 | 0 | case WasmEdge::ExternalType::Memory: { |
3221 | 0 | auto *mi = self->modinst->findMemoryExports(entry.name); |
3222 | 0 | if (!mi) { |
3223 | 0 | return wasm::ownvec<wasm::Extern>::make(); |
3224 | 0 | } |
3225 | 0 | v[i] = wasm::own<wasm::Extern>( |
3226 | 0 | static_cast<wasm::Extern *>(static_cast<wasm::Memory *>( |
3227 | 0 | new (std::nothrow) wasm_memory_t(self->store, mi)))); |
3228 | 0 | break; |
3229 | 0 | } |
3230 | 0 | default: |
3231 | 0 | return wasm::ownvec<wasm::Extern>::make(); |
3232 | 0 | } |
3233 | 0 | } |
3234 | 0 | return v; |
3235 | 0 | } |
3236 | | |
3237 | | // <<<<<<<< wasm::Instance functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |