Coverage Report

Created: 2026-11-12 06:35

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