Coverage Report

Created: 2026-09-28 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/WasmEdge/lib/executor/engine/proxy.cpp
Line
Count
Source
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright The WasmEdge Authors
3
4
#include "executor/executor.h"
5
#include "system/fault.h"
6
7
#include <cstdint>
8
9
namespace WasmEdge {
10
namespace Executor {
11
12
thread_local Executor *Executor::This = nullptr;
13
thread_local Runtime::StackManager *Executor::CurrentStack = nullptr;
14
thread_local Executor::ExecutorContext Executor::ExecutionContext;
15
thread_local Executor::PendingExnStruct Executor::PendingExn;
16
thread_local std::array<StackTraceEntry, 256> Executor::StackTrace;
17
thread_local size_t Executor::StackTraceSize = 0;
18
19
namespace {
20
21
/// Helper for the call proxies: keep an escaped exception pending for the
22
/// post-call check in the compiled caller and skip the results.
23
Expect<void> callFromCompiled(Runtime::StackManager &StackMgr,
24
                              const Runtime::Instance::FunctionInstance &Func,
25
0
                              ValVariant *Rets, Expect<void> Res) noexcept {
26
0
  if (unlikely(!Res)) {
27
0
    if (Res.error() == ErrCode::Value::PendingException) {
28
0
      return {};
29
0
    }
30
0
    return Unexpect(Res.error());
31
0
  }
32
0
  const uint32_t ReturnsSize =
33
0
      static_cast<uint32_t>(Func.getFuncType().getReturnTypes().size());
34
0
  for (uint32_t I = 0; I < ReturnsSize; ++I) {
35
0
    Rets[ReturnsSize - 1 - I] = StackMgr.pop();
36
0
  }
37
0
  return {};
38
0
}
39
40
} // namespace
41
42
template <typename RetT, typename... ArgsT>
43
struct Executor::ProxyHelper<Expect<RetT> (Executor::*)(Runtime::StackManager &,
44
                                                        ArgsT...) noexcept> {
45
  template <Expect<RetT> (Executor::*Func)(Runtime::StackManager &,
46
                                           ArgsT...) noexcept>
47
0
  static auto proxy(ArgsT... Args) {
48
#if defined(__s390x__)
49
    // Required on s390x: materializing args prevents runtime failures in
50
    // release builds.
51
    auto Materialize = [](auto &&A) -> decltype(auto) {
52
      using T = std::decay_t<decltype(A)>;
53
      if constexpr (std::is_integral_v<T>) {
54
        volatile T Tmp = A;
55
        return Tmp;
56
      } else {
57
        return std::forward<decltype(A)>(A);
58
      }
59
    };
60
    Expect<RetT> Res = (This->*Func)(*CurrentStack, Materialize(Args)...);
61
#else
62
0
    Expect<RetT> Res = (This->*Func)(*CurrentStack, Args...);
63
0
#endif
64
0
    if (unlikely(!Res)) {
65
0
      Fault::emitFault(Res.error());
66
0
    }
67
0
    if constexpr (std::is_same_v<RetT, RefVariant>) {
68
#if defined(_MSC_VER) && !defined(__clang__) // MSVC
69
      return *reinterpret_cast<__m128 *>((*Res).getRawData().data());
70
#else
71
0
      return (*Res).getRawData();
72
0
#endif // MSVC
73
0
    } else if constexpr (!std::is_void_v<RetT>) {
74
0
      return *Res;
75
0
    }
76
0
  }
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyTrap>(unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>*) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyCall>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>*)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned long, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>*) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyCallIndirect>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned long, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>*)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>*) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyCallRef>(WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>*)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<WasmEdge::RefVariant, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyRefFunc>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<WasmEdge::RefVariant, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyStructNew>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*, unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, bool, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>*) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyStructGet>(WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, bool, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>*)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyStructSet>(WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<WasmEdge::RefVariant, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyArrayNew>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*, unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<WasmEdge::RefVariant, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyArrayNewData>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<WasmEdge::RefVariant, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyArrayNewElem>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, bool, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>*) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyArrayGet>(WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, bool, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>*)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyArraySet>(WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<unsigned int, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::RefVariant) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyArrayLen>(WasmEdge::RefVariant)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyArrayFill>(WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, WasmEdge::RefVariant, unsigned int, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyArrayCopy>(WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, WasmEdge::RefVariant, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyArrayInitData>(WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyArrayInitElem>(WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<unsigned int, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, WasmEdge::ValType) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyRefTest>(WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, WasmEdge::ValType)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<WasmEdge::RefVariant, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, WasmEdge::ValType) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyRefCast>(WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, WasmEdge::ValType)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned long, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyTableInit>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned long, unsigned int, unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyElemDrop>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned long, unsigned long, unsigned long) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyTableCopy>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<unsigned long, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, WasmEdge::RefVariant, unsigned long) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyTableGrow>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, WasmEdge::RefVariant, unsigned long)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned long, WasmEdge::RefVariant, unsigned long) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyTableFill>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned long, WasmEdge::RefVariant, unsigned long)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<unsigned long, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned long) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyMemGrow>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned long)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned long, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyMemInit>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned long, unsigned int, unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyDataDrop>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned long, unsigned long, unsigned long) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyMemCopy>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned long, unsigned char, unsigned long) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyMemFill>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned long, unsigned char, unsigned long)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<unsigned long, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned long, unsigned long) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyMemAtomicNotify>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned long, unsigned long)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<unsigned long, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned long, unsigned long, long, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyMemAtomicWait>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned long, unsigned long, long, unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void*, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned long, WasmEdge::Runtime::Instance::ModuleInstance::ModuleContext**) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyTableGetFuncSymbol>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, unsigned int, unsigned long, WasmEdge::Runtime::Instance::ModuleInstance::ModuleContext**)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void*, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, WasmEdge::Runtime::Instance::ModuleInstance::ModuleContext**) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyRefGetFuncSymbol>(WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::RefVariant, WasmEdge::Runtime::Instance::ModuleInstance::ModuleContext**)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void*, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyFuncGetFuncSymbol>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyThrow>(WasmEdge::Runtime::Instance::ModuleInstance const*, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant> const*, unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::RefVariant) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyThrowRef>(WasmEdge::RefVariant)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>*, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyCatchPop>(WasmEdge::Runtime::Instance::ModuleInstance const*, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, unsigned long __vector(2), long __vector(2), unsigned int __vector(4), int __vector(4), unsigned short __vector(8), short __vector(8), unsigned char __vector(16), signed char __vector(16), float __vector(4), double __vector(2), WasmEdge::RefVariant>*, unsigned int, unsigned int)
77
};
78
79
#if defined(__clang_major__) && __clang_major__ >= 10
80
#pragma clang diagnostic push
81
#pragma clang diagnostic ignored "-Wc99-designator"
82
#endif
83
84
// Intrinsics table
85
const Executable::IntrinsicsTable Executor::Intrinsics = {
86
#if defined(_MSC_VER) && !defined(__clang__)
87
#define ENTRY(NAME, FUNC)                                                      \
88
  reinterpret_cast<void *>(&Executor::ProxyHelper<                             \
89
                           decltype(&Executor::FUNC)>::proxy<&Executor::FUNC>)
90
#else
91
#define ENTRY(NAME, FUNC)                                                      \
92
  [uint8_t(Executable::Intrinsics::NAME)] = reinterpret_cast<void *>(          \
93
      &Executor::ProxyHelper<decltype(&Executor::FUNC)>::proxy<                \
94
          &Executor::FUNC>)
95
#endif
96
    ENTRY(kTrap, proxyTrap),
97
    ENTRY(kCall, proxyCall),
98
    ENTRY(kCallIndirect, proxyCallIndirect),
99
    ENTRY(kCallRef, proxyCallRef),
100
    ENTRY(kRefFunc, proxyRefFunc),
101
    ENTRY(kStructNew, proxyStructNew),
102
    ENTRY(kStructGet, proxyStructGet),
103
    ENTRY(kStructSet, proxyStructSet),
104
    ENTRY(kArrayNew, proxyArrayNew),
105
    ENTRY(kArrayNewData, proxyArrayNewData),
106
    ENTRY(kArrayNewElem, proxyArrayNewElem),
107
    ENTRY(kArrayGet, proxyArrayGet),
108
    ENTRY(kArraySet, proxyArraySet),
109
    ENTRY(kArrayLen, proxyArrayLen),
110
    ENTRY(kArrayFill, proxyArrayFill),
111
    ENTRY(kArrayCopy, proxyArrayCopy),
112
    ENTRY(kArrayInitData, proxyArrayInitData),
113
    ENTRY(kArrayInitElem, proxyArrayInitElem),
114
    ENTRY(kRefTest, proxyRefTest),
115
    ENTRY(kRefCast, proxyRefCast),
116
    ENTRY(kTableInit, proxyTableInit),
117
    ENTRY(kElemDrop, proxyElemDrop),
118
    ENTRY(kTableCopy, proxyTableCopy),
119
    ENTRY(kTableGrow, proxyTableGrow),
120
    ENTRY(kTableFill, proxyTableFill),
121
    ENTRY(kMemGrow, proxyMemGrow),
122
    ENTRY(kMemInit, proxyMemInit),
123
    ENTRY(kDataDrop, proxyDataDrop),
124
    ENTRY(kMemCopy, proxyMemCopy),
125
    ENTRY(kMemFill, proxyMemFill),
126
    ENTRY(kMemAtomicNotify, proxyMemAtomicNotify),
127
    ENTRY(kMemAtomicWait, proxyMemAtomicWait),
128
    ENTRY(kTableGetFuncSymbol, proxyTableGetFuncSymbol),
129
    ENTRY(kRefGetFuncSymbol, proxyRefGetFuncSymbol),
130
    ENTRY(kFuncGetFuncSymbol, proxyFuncGetFuncSymbol),
131
    ENTRY(kThrow, proxyThrow),
132
    ENTRY(kThrowRef, proxyThrowRef),
133
    ENTRY(kCatchPop, proxyCatchPop),
134
#undef ENTRY
135
};
136
137
#if defined(__clang_major__) && __clang_major__ >= 10
138
#pragma clang diagnostic pop
139
#endif
140
141
Expect<void> Executor::proxyTrap(Runtime::StackManager &,
142
0
                                 const uint32_t Code) noexcept {
143
0
  return Unexpect(static_cast<ErrCategory>(Code >> 24), Code);
144
0
}
145
146
Expect<void>
147
Executor::proxyCall(Runtime::StackManager &StackMgr,
148
                    const Runtime::Instance::ModuleInstance *ModInst,
149
                    const uint32_t FuncIdx, const ValVariant *Args,
150
0
                    ValVariant *Rets) noexcept {
151
0
  const auto *FuncInst = getFuncInstByIdx(ModInst, FuncIdx);
152
0
  assuming(FuncInst);
153
0
  EXPECTED_TRY(checkLazyCompilation(FuncInst));
154
0
  const auto &FuncType = FuncInst->getFuncType();
155
0
  const uint32_t ParamsSize =
156
0
      static_cast<uint32_t>(FuncType.getParamTypes().size());
157
158
0
  for (uint32_t I = 0; I < ParamsSize; ++I) {
159
0
    StackMgr.push(Args[I]);
160
0
  }
161
162
0
  auto Instrs = FuncInst->getInstrs();
163
0
  auto Res =
164
0
      enterFunction(StackMgr, *FuncInst, Instrs.end(), false, true, ModInst)
165
0
          .and_then([&](AST::InstrView::iterator StartIt) {
166
0
            return execute(StackMgr, StartIt, Instrs.end());
167
0
          });
168
0
  return callFromCompiled(StackMgr, *FuncInst, Rets, std::move(Res));
169
0
}
170
171
Expect<void>
172
Executor::proxyCallIndirect(Runtime::StackManager &StackMgr,
173
                            const Runtime::Instance::ModuleInstance *ModInst,
174
                            const uint32_t TableIdx, const uint32_t FuncTypeIdx,
175
                            const uint64_t FuncIdx, const ValVariant *Args,
176
0
                            ValVariant *Rets) noexcept {
177
0
  const auto *TabInst = getTabInstByIdx(ModInst, TableIdx);
178
0
  assuming(TabInst);
179
180
0
  if (unlikely(FuncIdx >= TabInst->getSize())) {
181
0
    return Unexpect(ErrCode::Value::UndefinedElement);
182
0
  }
183
184
0
  auto Ref = TabInst->getRefAddr(FuncIdx);
185
0
  assuming(Ref);
186
0
  if (unlikely(Ref->isNull())) {
187
0
    return Unexpect(ErrCode::Value::UninitializedElement);
188
0
  }
189
190
0
  assuming(ModInst);
191
0
  const auto &ExpDefType = *ModInst->unsafeGetType(FuncTypeIdx);
192
0
  const auto *FuncInst = retrieveFuncRef(*Ref);
193
0
  assuming(FuncInst);
194
195
0
  EXPECTED_TRY(checkLazyCompilation(FuncInst));
196
197
0
  bool IsMatch = false;
198
0
  if (FuncInst->getModule()) {
199
0
    IsMatch = AST::TypeMatcher::matchType(
200
0
        ModInst->getTypeList(), *ExpDefType.getTypeIndex(),
201
0
        FuncInst->getModule()->getTypeList(), FuncInst->getTypeIndex());
202
0
  } else {
203
    // Independent host module instance case. Matching the composite type
204
    // directly.
205
0
    IsMatch = AST::TypeMatcher::matchType(
206
0
        ModInst->getTypeList(), ExpDefType.getCompositeType(),
207
0
        FuncInst->getHostFunc().getDefinedType().getCompositeType());
208
0
  }
209
0
  if (!IsMatch) {
210
0
    return Unexpect(ErrCode::Value::IndirectCallTypeMismatch);
211
0
  }
212
213
0
  const auto &FuncType = FuncInst->getFuncType();
214
0
  const uint32_t ParamsSize =
215
0
      static_cast<uint32_t>(FuncType.getParamTypes().size());
216
217
0
  for (uint32_t I = 0; I < ParamsSize; ++I) {
218
0
    StackMgr.push(Args[I]);
219
0
  }
220
221
0
  auto Instrs = FuncInst->getInstrs();
222
0
  auto Res =
223
0
      enterFunction(StackMgr, *FuncInst, Instrs.end(), false, true, ModInst)
224
0
          .and_then([&](AST::InstrView::iterator StartIt) {
225
0
            return execute(StackMgr, StartIt, Instrs.end());
226
0
          });
227
0
  return callFromCompiled(StackMgr, *FuncInst, Rets, std::move(Res));
228
0
}
229
230
Expect<void>
231
Executor::proxyCallRef(Runtime::StackManager &StackMgr,
232
                       const Runtime::Instance::ModuleInstance *ModInst,
233
                       const RefVariant Ref, const ValVariant *Args,
234
0
                       ValVariant *Rets) noexcept {
235
0
  const auto *FuncInst = retrieveFuncRef(Ref);
236
0
  if (unlikely(!FuncInst)) {
237
0
    return Unexpect(ErrCode::Value::AccessNullFunc);
238
0
  }
239
240
0
  EXPECTED_TRY(checkLazyCompilation(FuncInst));
241
242
0
  const auto &FuncType = FuncInst->getFuncType();
243
0
  const uint32_t ParamsSize =
244
0
      static_cast<uint32_t>(FuncType.getParamTypes().size());
245
246
0
  for (uint32_t I = 0; I < ParamsSize; ++I) {
247
0
    StackMgr.push(Args[I]);
248
0
  }
249
250
0
  auto Instrs = FuncInst->getInstrs();
251
0
  auto Res =
252
0
      enterFunction(StackMgr, *FuncInst, Instrs.end(), false, true, ModInst)
253
0
          .and_then([&](AST::InstrView::iterator StartIt) {
254
0
            return execute(StackMgr, StartIt, Instrs.end());
255
0
          });
256
0
  return callFromCompiled(StackMgr, *FuncInst, Rets, std::move(Res));
257
0
}
258
259
Expect<RefVariant>
260
Executor::proxyRefFunc(Runtime::StackManager &,
261
                       const Runtime::Instance::ModuleInstance *ModInst,
262
0
                       const uint32_t FuncIdx) noexcept {
263
0
  auto *FuncInst = getFuncInstByIdx(ModInst, FuncIdx);
264
0
  assuming(FuncInst);
265
0
  return RefVariant(FuncInst->getDefType(), FuncInst);
266
0
}
267
268
Expect<RefVariant>
269
Executor::proxyStructNew(Runtime::StackManager &,
270
                         const Runtime::Instance::ModuleInstance *ModInst,
271
                         const uint32_t TypeIdx, const ValVariant *Args,
272
0
                         const uint32_t ArgSize) noexcept {
273
0
  if (Args == nullptr) {
274
0
    return structNew(ModInst, TypeIdx);
275
0
  } else {
276
0
    return structNew(ModInst, TypeIdx, Span<const ValVariant>(Args, ArgSize));
277
0
  }
278
0
}
279
280
Expect<void> Executor::proxyStructGet(
281
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
282
    const RefVariant Ref, const uint32_t TypeIdx, const uint32_t Off,
283
0
    const bool IsSigned, ValVariant *Ret) noexcept {
284
0
  EXPECTED_TRY(auto Val, structGet(ModInst, Ref, TypeIdx, Off, IsSigned));
285
0
  *Ret = Val;
286
0
  return {};
287
0
}
288
289
Expect<void>
290
Executor::proxyStructSet(Runtime::StackManager &,
291
                         const Runtime::Instance::ModuleInstance *ModInst,
292
                         const RefVariant Ref, const uint32_t TypeIdx,
293
0
                         const uint32_t Off, const ValVariant *Val) noexcept {
294
0
  return structSet(ModInst, Ref, *Val, TypeIdx, Off);
295
0
}
296
297
Expect<RefVariant> Executor::proxyArrayNew(
298
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
299
    const uint32_t TypeIdx, const uint32_t Length, const ValVariant *Args,
300
0
    const uint32_t ArgSize) noexcept {
301
0
  assuming(ArgSize == 0 || ArgSize == 1 || ArgSize == Length);
302
0
  if (ArgSize == 0) {
303
0
    return arrayNew(ModInst, TypeIdx, Length);
304
0
  } else if (ArgSize == 1) {
305
0
    return arrayNew(ModInst, TypeIdx, Length, {Args[0]});
306
0
  } else {
307
0
    return arrayNew(ModInst, TypeIdx, Length,
308
0
                    Span<const ValVariant>(Args, ArgSize));
309
0
  }
310
0
}
311
312
Expect<RefVariant> Executor::proxyArrayNewData(
313
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
314
    const uint32_t TypeIdx, const uint32_t DataIdx, const uint32_t Start,
315
0
    const uint32_t Length) noexcept {
316
0
  return arrayNewData(ModInst, TypeIdx, DataIdx, Start, Length);
317
0
}
318
319
Expect<RefVariant> Executor::proxyArrayNewElem(
320
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
321
    const uint32_t TypeIdx, const uint32_t ElemIdx, const uint32_t Start,
322
0
    const uint32_t Length) noexcept {
323
0
  return arrayNewElem(ModInst, TypeIdx, ElemIdx, Start, Length);
324
0
}
325
326
Expect<void> Executor::proxyArrayGet(
327
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
328
    const RefVariant Ref, const uint32_t TypeIdx, const uint32_t Idx,
329
0
    const bool IsSigned, ValVariant *Ret) noexcept {
330
0
  EXPECTED_TRY(auto Val, arrayGet(ModInst, Ref, TypeIdx, Idx, IsSigned));
331
0
  *Ret = Val;
332
0
  return {};
333
0
}
334
335
Expect<void>
336
Executor::proxyArraySet(Runtime::StackManager &,
337
                        const Runtime::Instance::ModuleInstance *ModInst,
338
                        const RefVariant Ref, const uint32_t TypeIdx,
339
0
                        const uint32_t Idx, const ValVariant *Val) noexcept {
340
0
  return arraySet(ModInst, Ref, *Val, TypeIdx, Idx);
341
0
}
342
343
Expect<uint32_t> Executor::proxyArrayLen(Runtime::StackManager &,
344
0
                                         const RefVariant Ref) noexcept {
345
0
  auto *Inst = Ref.getPtr<Runtime::Instance::ArrayInstance>();
346
0
  if (Inst == nullptr) {
347
0
    return Unexpect(ErrCode::Value::AccessNullArray);
348
0
  }
349
0
  return Inst->getLength();
350
0
}
351
352
Expect<void> Executor::proxyArrayFill(
353
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
354
    const RefVariant Ref, const uint32_t TypeIdx, const uint32_t Idx,
355
0
    const uint32_t Cnt, const ValVariant *Val) noexcept {
356
0
  return arrayFill(ModInst, Ref, *Val, TypeIdx, Idx, Cnt);
357
0
}
358
359
Expect<void> Executor::proxyArrayCopy(
360
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
361
    const RefVariant DstRef, const uint32_t DstTypeIdx, const uint32_t DstIdx,
362
    const RefVariant SrcRef, const uint32_t SrcTypeIdx, const uint32_t SrcIdx,
363
0
    const uint32_t Cnt) noexcept {
364
0
  return arrayCopy(ModInst, DstRef, DstTypeIdx, DstIdx, SrcRef, SrcTypeIdx,
365
0
                   SrcIdx, Cnt);
366
0
}
367
368
Expect<void> Executor::proxyArrayInitData(
369
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
370
    const RefVariant Ref, const uint32_t TypeIdx, const uint32_t DataIdx,
371
0
    const uint32_t DstIdx, const uint32_t SrcIdx, const uint32_t Cnt) noexcept {
372
0
  return arrayInitData(ModInst, Ref, TypeIdx, DataIdx, DstIdx, SrcIdx, Cnt);
373
0
}
374
375
Expect<void> Executor::proxyArrayInitElem(
376
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
377
    const RefVariant Ref, const uint32_t TypeIdx, const uint32_t ElemIdx,
378
0
    const uint32_t DstIdx, const uint32_t SrcIdx, const uint32_t Cnt) noexcept {
379
0
  return arrayInitElem(ModInst, Ref, TypeIdx, ElemIdx, DstIdx, SrcIdx, Cnt);
380
0
}
381
382
Expect<uint32_t>
383
Executor::proxyRefTest(Runtime::StackManager &,
384
                       const Runtime::Instance::ModuleInstance *ModInst,
385
0
                       const RefVariant Ref, ValType VTTest) noexcept {
386
  // Copy the value type here due to handling the externalized case.
387
0
  auto VT = Ref.getType();
388
0
  if (VT.isExternalized()) {
389
0
    VT = ValType(TypeCode::Ref, TypeCode::ExternRef);
390
0
  }
391
0
  assuming(ModInst);
392
0
  Span<const AST::SubType *const> GotTypeList = ModInst->getTypeList();
393
0
  if (!VT.isAbsHeapType()) {
394
0
    auto *Inst = Ref.getPtr<Runtime::Instance::CompositeBase>();
395
    // Reference must not be nullptr here because the null references are typed
396
    // with the least abstract heap type.
397
0
    if (Inst->getModule()) {
398
0
      GotTypeList = Inst->getModule()->getTypeList();
399
0
    }
400
0
  }
401
402
0
  if (AST::TypeMatcher::matchType(ModInst->getTypeList(), VTTest, GotTypeList,
403
0
                                  VT)) {
404
0
    return static_cast<uint32_t>(1);
405
0
  } else {
406
0
    return static_cast<uint32_t>(0);
407
0
  }
408
0
}
409
410
Expect<RefVariant>
411
Executor::proxyRefCast(Runtime::StackManager &,
412
                       const Runtime::Instance::ModuleInstance *ModInst,
413
0
                       const RefVariant Ref, ValType VTCast) noexcept {
414
  // Copy the value type here due to handling the externalized case.
415
0
  auto VT = Ref.getType();
416
0
  if (VT.isExternalized()) {
417
0
    VT = ValType(TypeCode::Ref, TypeCode::ExternRef);
418
0
  }
419
0
  assuming(ModInst);
420
0
  Span<const AST::SubType *const> GotTypeList = ModInst->getTypeList();
421
0
  if (!VT.isAbsHeapType()) {
422
0
    auto *Inst = Ref.getPtr<Runtime::Instance::CompositeBase>();
423
    // Reference must not be nullptr here because the null references are typed
424
    // with the least abstract heap type.
425
0
    if (Inst->getModule()) {
426
0
      GotTypeList = Inst->getModule()->getTypeList();
427
0
    }
428
0
  }
429
430
0
  if (!AST::TypeMatcher::matchType(ModInst->getTypeList(), VTCast, GotTypeList,
431
0
                                   VT)) {
432
0
    return Unexpect(ErrCode::Value::CastFailed);
433
0
  }
434
0
  return Ref;
435
0
}
436
437
// For the runtime value of `uint64_t`, arguments are expected to be extended
438
// to 64-bit width in the LLVM compiler regardless of whether the address type
439
// is 32 or 64 bits. On the other hand, a `uint64_t` return should handle the
440
// conversion to a 32- or 64-bit value according to the address type in the LLVM
441
// compiler.
442
443
Expect<void> Executor::proxyTableInit(
444
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
445
    const uint32_t TableIdx, const uint32_t ElemIdx, const uint64_t DstOff,
446
0
    const uint32_t SrcOff, const uint32_t Len) noexcept {
447
0
  auto *TabInst = getTabInstByIdx(ModInst, TableIdx);
448
0
  assuming(TabInst);
449
0
  auto *ElemInst = getElemInstByIdx(ModInst, ElemIdx);
450
0
  assuming(ElemInst);
451
0
  return TabInst->setRefs(ElemInst->getRefs(), DstOff, SrcOff, Len);
452
0
}
453
454
Expect<void>
455
Executor::proxyElemDrop(Runtime::StackManager &,
456
                        const Runtime::Instance::ModuleInstance *ModInst,
457
0
                        const uint32_t ElemIdx) noexcept {
458
0
  auto *ElemInst = getElemInstByIdx(ModInst, ElemIdx);
459
0
  assuming(ElemInst);
460
0
  ElemInst->clear();
461
0
  return {};
462
0
}
463
464
Expect<void> Executor::proxyTableCopy(
465
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
466
    const uint32_t TableIdxDst, const uint32_t TableIdxSrc,
467
0
    const uint64_t DstOff, const uint64_t SrcOff, const uint64_t Len) noexcept {
468
0
  auto *TabInstDst = getTabInstByIdx(ModInst, TableIdxDst);
469
0
  assuming(TabInstDst);
470
0
  auto *TabInstSrc = getTabInstByIdx(ModInst, TableIdxSrc);
471
0
  assuming(TabInstSrc);
472
473
0
  EXPECTED_TRY(auto Refs, TabInstSrc->getRefs(0, SrcOff + Len));
474
0
  return TabInstDst->setRefs(Refs, DstOff, SrcOff, Len);
475
0
}
476
477
Expect<uint64_t>
478
Executor::proxyTableGrow(Runtime::StackManager &,
479
                         const Runtime::Instance::ModuleInstance *ModInst,
480
                         const uint32_t TableIdx, const RefVariant Val,
481
0
                         const uint64_t NewSize) noexcept {
482
0
  auto *TabInst = getTabInstByIdx(ModInst, TableIdx);
483
0
  assuming(TabInst);
484
0
  const auto AddrType = TabInst->getTableType().getLimit().getAddrType();
485
0
  const uint64_t CurrTableSize = TabInst->getSize();
486
0
  if (likely(TabInst->growTable(NewSize, Val))) {
487
0
    return CurrTableSize;
488
0
  } else {
489
0
    switch (AddrType) {
490
0
    case AddressType::I32:
491
0
      return static_cast<uint32_t>(-1);
492
0
    case AddressType::I64:
493
0
      return static_cast<uint64_t>(-1);
494
0
    default:
495
0
      assumingUnreachable();
496
0
    }
497
0
  }
498
0
}
499
500
Expect<void>
501
Executor::proxyTableFill(Runtime::StackManager &,
502
                         const Runtime::Instance::ModuleInstance *ModInst,
503
                         const uint32_t TableIdx, const uint64_t Off,
504
0
                         const RefVariant Ref, const uint64_t Len) noexcept {
505
0
  auto *TabInst = getTabInstByIdx(ModInst, TableIdx);
506
0
  assuming(TabInst);
507
0
  return TabInst->fillRefs(Ref, Off, Len);
508
0
}
509
510
Expect<uint64_t>
511
Executor::proxyMemGrow(Runtime::StackManager &,
512
                       const Runtime::Instance::ModuleInstance *ModInst,
513
0
                       const uint32_t MemIdx, const uint64_t NewSize) noexcept {
514
0
  auto *MemInst = getMemInstByIdx(ModInst, MemIdx);
515
0
  assuming(MemInst);
516
0
  const auto AddrType = MemInst->getMemoryType().getLimit().getAddrType();
517
0
  const uint64_t CurrPageSize = MemInst->getPageSize();
518
0
  if (MemInst->growPage(NewSize)) {
519
0
    return CurrPageSize;
520
0
  } else {
521
0
    switch (AddrType) {
522
0
    case AddressType::I32:
523
0
      return static_cast<uint32_t>(-1);
524
0
    case AddressType::I64:
525
0
      return static_cast<uint64_t>(-1);
526
0
    default:
527
0
      assumingUnreachable();
528
0
    }
529
0
  }
530
0
}
531
532
Expect<void> Executor::proxyMemInit(
533
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
534
    const uint32_t MemIdx, const uint32_t DataIdx, const uint64_t DstOff,
535
0
    const uint32_t SrcOff, const uint32_t Len) noexcept {
536
0
  auto *MemInst = getMemInstByIdx(ModInst, MemIdx);
537
0
  assuming(MemInst);
538
0
  auto *DataInst = getDataInstByIdx(ModInst, DataIdx);
539
0
  assuming(DataInst);
540
0
  return MemInst->setBytes(DataInst->getData(), DstOff, SrcOff, Len);
541
0
}
542
543
Expect<void>
544
Executor::proxyDataDrop(Runtime::StackManager &,
545
                        const Runtime::Instance::ModuleInstance *ModInst,
546
0
                        const uint32_t DataIdx) noexcept {
547
0
  auto *DataInst = getDataInstByIdx(ModInst, DataIdx);
548
0
  assuming(DataInst);
549
0
  DataInst->clear();
550
0
  return {};
551
0
}
552
553
Expect<void> Executor::proxyMemCopy(
554
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
555
    const uint32_t DstMemIdx, const uint32_t SrcMemIdx, const uint64_t DstOff,
556
0
    const uint64_t SrcOff, const uint64_t Len) noexcept {
557
0
  auto *MemInstDst = getMemInstByIdx(ModInst, DstMemIdx);
558
0
  assuming(MemInstDst);
559
0
  auto *MemInstSrc = getMemInstByIdx(ModInst, SrcMemIdx);
560
0
  assuming(MemInstSrc);
561
562
0
  EXPECTED_TRY(auto Data, MemInstSrc->getBytes(SrcOff, Len));
563
0
  return MemInstDst->setBytes(Data, DstOff, 0, Len);
564
0
}
565
566
Expect<void>
567
Executor::proxyMemFill(Runtime::StackManager &,
568
                       const Runtime::Instance::ModuleInstance *ModInst,
569
                       const uint32_t MemIdx, const uint64_t Off,
570
0
                       const uint8_t Val, const uint64_t Len) noexcept {
571
0
  auto *MemInst = getMemInstByIdx(ModInst, MemIdx);
572
0
  assuming(MemInst);
573
0
  return MemInst->fillBytes(Val, Off, Len);
574
0
}
575
576
Expect<uint64_t>
577
Executor::proxyMemAtomicNotify(Runtime::StackManager &,
578
                               const Runtime::Instance::ModuleInstance *ModInst,
579
                               const uint32_t MemIdx, const uint64_t Offset,
580
0
                               const uint64_t Count) noexcept {
581
0
  auto *MemInst = getMemInstByIdx(ModInst, MemIdx);
582
0
  assuming(MemInst);
583
0
  return atomicNotify(*MemInst, Offset, Count);
584
0
}
585
586
Expect<uint64_t> Executor::proxyMemAtomicWait(
587
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
588
    const uint32_t MemIdx, const uint64_t Offset, const uint64_t Expected,
589
0
    const int64_t Timeout, const uint32_t BitWidth) noexcept {
590
0
  auto *MemInst = getMemInstByIdx(ModInst, MemIdx);
591
0
  assuming(MemInst);
592
593
0
  if (BitWidth == 64) {
594
0
    return atomicWait<uint64_t>(*MemInst, Offset, Expected, Timeout);
595
0
  } else if (BitWidth == 32) {
596
0
    return atomicWait<uint32_t>(*MemInst, Offset,
597
0
                                static_cast<uint32_t>(Expected), Timeout);
598
0
  }
599
0
  assumingUnreachable();
600
0
}
601
602
Expect<void *> Executor::proxyTableGetFuncSymbol(
603
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
604
    const uint32_t TableIdx, const uint32_t FuncTypeIdx, const uint64_t FuncIdx,
605
0
    Runtime::Instance::ModuleInstance::ModuleContext **CalleeCtxOut) noexcept {
606
0
  *CalleeCtxOut = nullptr;
607
0
  const auto *TabInst = getTabInstByIdx(ModInst, TableIdx);
608
0
  assuming(TabInst);
609
610
0
  if (unlikely(FuncIdx >= TabInst->getSize())) {
611
0
    return Unexpect(ErrCode::Value::UndefinedElement);
612
0
  }
613
614
0
  auto Ref = TabInst->getRefAddr(FuncIdx);
615
0
  assuming(Ref);
616
0
  if (unlikely(Ref->isNull())) {
617
0
    return Unexpect(ErrCode::Value::UninitializedElement);
618
0
  }
619
620
0
  const auto &ExpDefType = *ModInst->unsafeGetType(FuncTypeIdx);
621
0
  const auto *FuncInst = retrieveFuncRef(*Ref);
622
0
  assuming(FuncInst);
623
0
  bool IsMatch = false;
624
  // Check if the function type matches the expected type.
625
0
  if (FuncInst->getModule() == ModInst &&
626
0
      *ExpDefType.getTypeIndex() == FuncInst->getTypeIndex()) {
627
    // Fast path: If the function instance is in the same module instance, we
628
    // can bypass the expensive structural type matching (O(N)) by checking the
629
    // type index directly (O(1)).
630
0
    IsMatch = true;
631
0
  } else if (FuncInst->getModule()) {
632
    // If the type index is not the same, we still need to check the type
633
    // structure. This is because the type alias may have different type
634
    // indices but the same type structure.
635
0
    IsMatch = AST::TypeMatcher::matchType(
636
0
        ModInst->getTypeList(), *ExpDefType.getTypeIndex(),
637
0
        FuncInst->getModule()->getTypeList(), FuncInst->getTypeIndex());
638
0
  } else {
639
    // Independent host module instance case. Matching the composite type
640
    // directly.
641
0
    IsMatch = AST::TypeMatcher::matchType(
642
0
        ModInst->getTypeList(), ExpDefType.getCompositeType(),
643
0
        FuncInst->getHostFunc().getDefinedType().getCompositeType());
644
0
  }
645
0
  if (!IsMatch) {
646
0
    return Unexpect(ErrCode::Value::IndirectCallTypeMismatch);
647
0
  }
648
649
0
  EXPECTED_TRY(checkLazyCompilation(FuncInst));
650
651
0
  if (unlikely(!FuncInst->isCompiledFunction())) {
652
0
    return nullptr;
653
0
  }
654
0
  if (FuncInst->getModule() != ModInst) {
655
0
    *CalleeCtxOut =
656
0
        &const_cast<Runtime::Instance::ModuleInstance *>(FuncInst->getModule())
657
0
             ->ModCtx;
658
0
  }
659
0
  return FuncInst->getSymbol().get();
660
0
}
661
662
Expect<void *> Executor::proxyRefGetFuncSymbol(
663
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
664
    const RefVariant Ref,
665
0
    Runtime::Instance::ModuleInstance::ModuleContext **CalleeCtxOut) noexcept {
666
0
  *CalleeCtxOut = nullptr;
667
0
  const auto *FuncInst = retrieveFuncRef(Ref);
668
0
  assuming(FuncInst);
669
0
  if (likely(FuncInst->isCompiledFunction())) {
670
0
    if (FuncInst->getModule() != ModInst) {
671
0
      *CalleeCtxOut = &const_cast<Runtime::Instance::ModuleInstance *>(
672
0
                           FuncInst->getModule())
673
0
                           ->ModCtx;
674
0
    }
675
0
    return FuncInst->getSymbol().get();
676
0
  }
677
0
  EXPECTED_TRY(checkLazyCompilation(FuncInst));
678
679
0
  if (unlikely(!FuncInst->isCompiledFunction())) {
680
0
    return nullptr;
681
0
  }
682
0
  if (FuncInst->getModule() != ModInst) {
683
0
    *CalleeCtxOut =
684
0
        &const_cast<Runtime::Instance::ModuleInstance *>(FuncInst->getModule())
685
0
             ->ModCtx;
686
0
  }
687
0
  return FuncInst->getSymbol().get();
688
0
}
689
690
Expect<void *> Executor::proxyFuncGetFuncSymbol(
691
    Runtime::StackManager &, const Runtime::Instance::ModuleInstance *ModInst,
692
0
    const uint32_t FuncIdx) noexcept {
693
0
  const auto *FuncInst = getFuncInstByIdx(ModInst, FuncIdx);
694
0
  assuming(FuncInst);
695
0
  if (likely(FuncInst->isCompiledFunction())) {
696
0
    return FuncInst->getSymbol().get();
697
0
  }
698
0
  EXPECTED_TRY(checkLazyCompilation(FuncInst));
699
700
0
  if (unlikely(!FuncInst->isCompiledFunction())) {
701
0
    return nullptr;
702
0
  }
703
0
  return FuncInst->getSymbol().get();
704
0
}
705
706
Expect<void>
707
Executor::proxyThrow(Runtime::StackManager &,
708
                     const Runtime::Instance::ModuleInstance *ModInst,
709
                     const uint32_t TagIdx, const ValVariant *Vals,
710
0
                     const uint32_t Num) noexcept {
711
0
  auto *TagInst = getTagInstByIdx(ModInst, TagIdx);
712
0
  assuming(TagInst);
713
0
  assuming(TagInst->getTagType().getAssocValSize() == Num);
714
0
  PendingExn.TagInst = TagInst;
715
0
  PendingExn.Inst = nullptr;
716
0
  PendingExn.setPayload(Span<const ValVariant>(Vals, Num));
717
0
  return {};
718
0
}
719
720
Expect<void> Executor::proxyThrowRef(Runtime::StackManager &,
721
0
                                     const RefVariant Ref) noexcept {
722
0
  const auto *ExnInst = Ref.getPtr<Runtime::Instance::ExceptionInstance>();
723
0
  if (unlikely(ExnInst == nullptr)) {
724
0
    return Unexpect(ErrCode::Value::AccessNullException);
725
0
  }
726
0
  PendingExn.TagInst = ExnInst->getTag();
727
0
  PendingExn.Inst = ExnInst;
728
0
  PendingExn.setPayload(ExnInst->getPayload());
729
0
  return {};
730
0
}
731
732
Expect<void>
733
Executor::proxyCatchPop(Runtime::StackManager &,
734
                        const Runtime::Instance::ModuleInstance *ModInst,
735
                        ValVariant *Out, const uint32_t PopPayload,
736
0
                        const uint32_t NeedRef) noexcept {
737
0
  auto *TagInst = PendingExn.TagInst;
738
0
  assuming(TagInst);
739
0
  uint32_t Idx = 0;
740
0
  if (PopPayload != 0) {
741
0
    Idx = TagInst->getTagType().getAssocValSize();
742
0
    std::copy_n(PendingExn.getPayload().begin(), Idx, Out);
743
0
  }
744
0
  if (NeedRef != 0) {
745
0
    const auto *Inst = PendingExn.Inst;
746
0
    if (Inst == nullptr) {
747
0
      assuming(ModInst);
748
0
      Inst = const_cast<Runtime::Instance::ModuleInstance *>(ModInst)
749
0
                 ->newException(
750
0
                     TagInst, std::vector<ValVariant>(PendingExn.getPayload()));
751
0
    }
752
0
    Out[Idx] = RefVariant(ValType(TypeCode::Ref, TypeCode::ExnRef), Inst);
753
0
  }
754
0
  PendingExn = {};
755
0
  return {};
756
0
}
757
758
} // namespace Executor
759
} // namespace WasmEdge