Coverage Report

Created: 2026-08-14 06:41

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::ExecutionContextStruct Executor::ExecutionContext;
15
thread_local Executor::PendingExnStruct Executor::PendingExn;
16
thread_local std::array<uint32_t, 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&, 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>(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&, 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*, 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>(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*, 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::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::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&, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyRefFunc>(unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<WasmEdge::RefVariant, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, 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>(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, 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::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::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::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&, 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>(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&, unsigned int, unsigned int, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyArrayNewData>(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&, unsigned int, unsigned int, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyArrayNewElem>(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::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::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::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::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::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::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::RefVariant, unsigned int, unsigned int, WasmEdge::RefVariant, unsigned int, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyArrayCopy>(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::RefVariant, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyArrayInitData>(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::RefVariant, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyArrayInitElem>(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::RefVariant, WasmEdge::ValType) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyRefTest>(WasmEdge::RefVariant, WasmEdge::ValType)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<WasmEdge::RefVariant, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, WasmEdge::RefVariant, WasmEdge::ValType) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyRefCast>(WasmEdge::RefVariant, WasmEdge::ValType)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, unsigned long, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyTableInit>(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&, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyElemDrop>(unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, unsigned long, unsigned long, unsigned long) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyTableCopy>(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&, unsigned int, WasmEdge::RefVariant, unsigned long) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyTableGrow>(unsigned int, WasmEdge::RefVariant, unsigned long)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, unsigned int, unsigned long, WasmEdge::RefVariant, unsigned long) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyTableFill>(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&, unsigned int, unsigned long) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyMemGrow>(unsigned int, unsigned long)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, unsigned long, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyMemInit>(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&, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyDataDrop>(unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, unsigned long, unsigned long, unsigned long) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyMemCopy>(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&, unsigned int, unsigned long, unsigned char, unsigned long) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyMemFill>(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&, unsigned int, unsigned long, unsigned long) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyMemAtomicNotify>(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&, unsigned int, unsigned long, unsigned long, long, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyMemAtomicWait>(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&, unsigned int, unsigned int, unsigned int) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyTableGetFuncSymbol>(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::RefVariant) noexcept>::proxy<&WasmEdge::Executor::Executor::proxyRefGetFuncSymbol>(WasmEdge::RefVariant)
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::proxyFuncGetFuncSymbol>(unsigned int)
Unexecuted instantiation: auto WasmEdge::Executor::Executor::ProxyHelper<cxx20::expected<void, WasmEdge::ErrCode> (WasmEdge::Executor::Executor::*)(WasmEdge::Runtime::StackManager&, 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>(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::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::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> Executor::proxyCall(Runtime::StackManager &StackMgr,
147
                                 const uint32_t FuncIdx, const ValVariant *Args,
148
0
                                 ValVariant *Rets) noexcept {
149
0
  const auto *FuncInst = getFuncInstByIdx(StackMgr, FuncIdx);
150
0
  assuming(FuncInst);
151
0
  EXPECTED_TRY(checkLazyCompilation(FuncInst));
152
0
  const auto &FuncType = FuncInst->getFuncType();
153
0
  const uint32_t ParamsSize =
154
0
      static_cast<uint32_t>(FuncType.getParamTypes().size());
155
156
0
  for (uint32_t I = 0; I < ParamsSize; ++I) {
157
0
    StackMgr.push(Args[I]);
158
0
  }
159
160
0
  auto Instrs = FuncInst->getInstrs();
161
0
  auto Res = enterFunction(StackMgr, *FuncInst, Instrs.end(), false, true)
162
0
                 .and_then([&](AST::InstrView::iterator StartIt) {
163
0
                   return execute(StackMgr, StartIt, Instrs.end());
164
0
                 });
165
0
  return callFromCompiled(StackMgr, *FuncInst, Rets, std::move(Res));
166
0
}
167
168
Expect<void> Executor::proxyCallIndirect(Runtime::StackManager &StackMgr,
169
                                         const uint32_t TableIdx,
170
                                         const uint32_t FuncTypeIdx,
171
                                         const uint32_t FuncIdx,
172
                                         const ValVariant *Args,
173
0
                                         ValVariant *Rets) noexcept {
174
0
  const auto *TabInst = getTabInstByIdx(StackMgr, TableIdx);
175
0
  assuming(TabInst);
176
177
0
  if (unlikely(FuncIdx >= TabInst->getSize())) {
178
0
    return Unexpect(ErrCode::Value::UndefinedElement);
179
0
  }
180
181
0
  auto Ref = TabInst->getRefAddr(FuncIdx);
182
0
  assuming(Ref);
183
0
  if (unlikely(Ref->isNull())) {
184
0
    return Unexpect(ErrCode::Value::UninitializedElement);
185
0
  }
186
187
0
  const auto *ModInst = StackMgr.getModule();
188
0
  assuming(ModInst);
189
0
  const auto &ExpDefType = *ModInst->unsafeGetType(FuncTypeIdx);
190
0
  const auto *FuncInst = retrieveFuncRef(*Ref);
191
0
  assuming(FuncInst);
192
193
0
  EXPECTED_TRY(checkLazyCompilation(FuncInst));
194
195
0
  bool IsMatch = false;
196
0
  if (FuncInst->getModule()) {
197
0
    IsMatch = AST::TypeMatcher::matchType(
198
0
        ModInst->getTypeList(), *ExpDefType.getTypeIndex(),
199
0
        FuncInst->getModule()->getTypeList(), FuncInst->getTypeIndex());
200
0
  } else {
201
    // Independent host module instance case. Matching the composite type
202
    // directly.
203
0
    IsMatch = AST::TypeMatcher::matchType(
204
0
        ModInst->getTypeList(), ExpDefType.getCompositeType(),
205
0
        FuncInst->getHostFunc().getDefinedType().getCompositeType());
206
0
  }
207
0
  if (!IsMatch) {
208
0
    return Unexpect(ErrCode::Value::IndirectCallTypeMismatch);
209
0
  }
210
211
0
  const auto &FuncType = FuncInst->getFuncType();
212
0
  const uint32_t ParamsSize =
213
0
      static_cast<uint32_t>(FuncType.getParamTypes().size());
214
215
0
  for (uint32_t I = 0; I < ParamsSize; ++I) {
216
0
    StackMgr.push(Args[I]);
217
0
  }
218
219
0
  auto Instrs = FuncInst->getInstrs();
220
0
  auto Res = enterFunction(StackMgr, *FuncInst, Instrs.end(), false, true)
221
0
                 .and_then([&](AST::InstrView::iterator StartIt) {
222
0
                   return execute(StackMgr, StartIt, Instrs.end());
223
0
                 });
224
0
  return callFromCompiled(StackMgr, *FuncInst, Rets, std::move(Res));
225
0
}
226
227
Expect<void> Executor::proxyCallRef(Runtime::StackManager &StackMgr,
228
                                    const RefVariant Ref,
229
                                    const ValVariant *Args,
230
0
                                    ValVariant *Rets) noexcept {
231
0
  const auto *FuncInst = retrieveFuncRef(Ref);
232
0
  if (unlikely(!FuncInst)) {
233
0
    return Unexpect(ErrCode::Value::AccessNullFunc);
234
0
  }
235
236
0
  EXPECTED_TRY(checkLazyCompilation(FuncInst));
237
238
0
  const auto &FuncType = FuncInst->getFuncType();
239
0
  const uint32_t ParamsSize =
240
0
      static_cast<uint32_t>(FuncType.getParamTypes().size());
241
242
0
  for (uint32_t I = 0; I < ParamsSize; ++I) {
243
0
    StackMgr.push(Args[I]);
244
0
  }
245
246
0
  auto Instrs = FuncInst->getInstrs();
247
0
  auto Res = enterFunction(StackMgr, *FuncInst, Instrs.end(), false, true)
248
0
                 .and_then([&](AST::InstrView::iterator StartIt) {
249
0
                   return execute(StackMgr, StartIt, Instrs.end());
250
0
                 });
251
0
  return callFromCompiled(StackMgr, *FuncInst, Rets, std::move(Res));
252
0
}
253
254
Expect<RefVariant> Executor::proxyRefFunc(Runtime::StackManager &StackMgr,
255
0
                                          const uint32_t FuncIdx) noexcept {
256
0
  auto *FuncInst = getFuncInstByIdx(StackMgr, FuncIdx);
257
0
  assuming(FuncInst);
258
0
  return RefVariant(FuncInst->getDefType(), FuncInst);
259
0
}
260
261
Expect<RefVariant> Executor::proxyStructNew(Runtime::StackManager &StackMgr,
262
                                            const uint32_t TypeIdx,
263
                                            const ValVariant *Args,
264
0
                                            const uint32_t ArgSize) noexcept {
265
0
  if (Args == nullptr) {
266
0
    return structNew(StackMgr, TypeIdx);
267
0
  } else {
268
0
    return structNew(StackMgr, TypeIdx, Span<const ValVariant>(Args, ArgSize));
269
0
  }
270
0
}
271
272
Expect<void> Executor::proxyStructGet(Runtime::StackManager &StackMgr,
273
                                      const RefVariant Ref,
274
                                      const uint32_t TypeIdx,
275
                                      const uint32_t Off, const bool IsSigned,
276
0
                                      ValVariant *Ret) noexcept {
277
0
  EXPECTED_TRY(auto Val, structGet(StackMgr, Ref, TypeIdx, Off, IsSigned));
278
0
  *Ret = Val;
279
0
  return {};
280
0
}
281
282
Expect<void> Executor::proxyStructSet(Runtime::StackManager &StackMgr,
283
                                      const RefVariant Ref,
284
                                      const uint32_t TypeIdx,
285
                                      const uint32_t Off,
286
0
                                      const ValVariant *Val) noexcept {
287
0
  return structSet(StackMgr, Ref, *Val, TypeIdx, Off);
288
0
}
289
290
Expect<RefVariant> Executor::proxyArrayNew(Runtime::StackManager &StackMgr,
291
                                           const uint32_t TypeIdx,
292
                                           const uint32_t Length,
293
                                           const ValVariant *Args,
294
0
                                           const uint32_t ArgSize) noexcept {
295
0
  assuming(ArgSize == 0 || ArgSize == 1 || ArgSize == Length);
296
0
  if (ArgSize == 0) {
297
0
    return arrayNew(StackMgr, TypeIdx, Length);
298
0
  } else if (ArgSize == 1) {
299
0
    return arrayNew(StackMgr, TypeIdx, Length, {Args[0]});
300
0
  } else {
301
0
    return arrayNew(StackMgr, TypeIdx, Length,
302
0
                    Span<const ValVariant>(Args, ArgSize));
303
0
  }
304
0
}
305
306
Expect<RefVariant> Executor::proxyArrayNewData(Runtime::StackManager &StackMgr,
307
                                               const uint32_t TypeIdx,
308
                                               const uint32_t DataIdx,
309
                                               const uint32_t Start,
310
0
                                               const uint32_t Length) noexcept {
311
0
  return arrayNewData(StackMgr, TypeIdx, DataIdx, Start, Length);
312
0
}
313
314
Expect<RefVariant> Executor::proxyArrayNewElem(Runtime::StackManager &StackMgr,
315
                                               const uint32_t TypeIdx,
316
                                               const uint32_t ElemIdx,
317
                                               const uint32_t Start,
318
0
                                               const uint32_t Length) noexcept {
319
0
  return arrayNewElem(StackMgr, TypeIdx, ElemIdx, Start, Length);
320
0
}
321
322
Expect<void> Executor::proxyArrayGet(Runtime::StackManager &StackMgr,
323
                                     const RefVariant Ref,
324
                                     const uint32_t TypeIdx, const uint32_t Idx,
325
                                     const bool IsSigned,
326
0
                                     ValVariant *Ret) noexcept {
327
0
  EXPECTED_TRY(auto Val, arrayGet(StackMgr, Ref, TypeIdx, Idx, IsSigned));
328
0
  *Ret = Val;
329
0
  return {};
330
0
}
331
332
Expect<void> Executor::proxyArraySet(Runtime::StackManager &StackMgr,
333
                                     const RefVariant Ref,
334
                                     const uint32_t TypeIdx, const uint32_t Idx,
335
0
                                     const ValVariant *Val) noexcept {
336
0
  return arraySet(StackMgr, Ref, *Val, TypeIdx, Idx);
337
0
}
338
339
Expect<uint32_t> Executor::proxyArrayLen(Runtime::StackManager &,
340
0
                                         const RefVariant Ref) noexcept {
341
0
  auto *Inst = Ref.getPtr<Runtime::Instance::ArrayInstance>();
342
0
  if (Inst == nullptr) {
343
0
    return Unexpect(ErrCode::Value::AccessNullArray);
344
0
  }
345
0
  return Inst->getLength();
346
0
}
347
348
Expect<void> Executor::proxyArrayFill(Runtime::StackManager &StackMgr,
349
                                      const RefVariant Ref,
350
                                      const uint32_t TypeIdx,
351
                                      const uint32_t Idx, const uint32_t Cnt,
352
0
                                      const ValVariant *Val) noexcept {
353
0
  return arrayFill(StackMgr, Ref, *Val, TypeIdx, Idx, Cnt);
354
0
}
355
356
Expect<void>
357
Executor::proxyArrayCopy(Runtime::StackManager &StackMgr,
358
                         const RefVariant DstRef, const uint32_t DstTypeIdx,
359
                         const uint32_t DstIdx, const RefVariant SrcRef,
360
                         const uint32_t SrcTypeIdx, const uint32_t SrcIdx,
361
0
                         const uint32_t Cnt) noexcept {
362
0
  return arrayCopy(StackMgr, DstRef, DstTypeIdx, DstIdx, SrcRef, SrcTypeIdx,
363
0
                   SrcIdx, Cnt);
364
0
}
365
366
Expect<void> Executor::proxyArrayInitData(
367
    Runtime::StackManager &StackMgr, const RefVariant Ref,
368
    const uint32_t TypeIdx, const uint32_t DataIdx, const uint32_t DstIdx,
369
0
    const uint32_t SrcIdx, const uint32_t Cnt) noexcept {
370
0
  return arrayInitData(StackMgr, Ref, TypeIdx, DataIdx, DstIdx, SrcIdx, Cnt);
371
0
}
372
373
Expect<void> Executor::proxyArrayInitElem(
374
    Runtime::StackManager &StackMgr, const RefVariant Ref,
375
    const uint32_t TypeIdx, const uint32_t ElemIdx, const uint32_t DstIdx,
376
0
    const uint32_t SrcIdx, const uint32_t Cnt) noexcept {
377
0
  return arrayInitElem(StackMgr, Ref, TypeIdx, ElemIdx, DstIdx, SrcIdx, Cnt);
378
0
}
379
380
Expect<uint32_t> Executor::proxyRefTest(Runtime::StackManager &StackMgr,
381
                                        const RefVariant Ref,
382
0
                                        ValType VTTest) noexcept {
383
  // Copy the value type here due to handling the externalized case.
384
0
  auto VT = Ref.getType();
385
0
  if (VT.isExternalized()) {
386
0
    VT = ValType(TypeCode::Ref, TypeCode::ExternRef);
387
0
  }
388
0
  const auto *ModInst = StackMgr.getModule();
389
0
  assuming(ModInst);
390
0
  Span<const AST::SubType *const> GotTypeList = ModInst->getTypeList();
391
0
  if (!VT.isAbsHeapType()) {
392
0
    auto *Inst = Ref.getPtr<Runtime::Instance::CompositeBase>();
393
    // Reference must not be nullptr here because the null references are typed
394
    // with the least abstract heap type.
395
0
    if (Inst->getModule()) {
396
0
      GotTypeList = Inst->getModule()->getTypeList();
397
0
    }
398
0
  }
399
400
0
  if (AST::TypeMatcher::matchType(ModInst->getTypeList(), VTTest, GotTypeList,
401
0
                                  VT)) {
402
0
    return static_cast<uint32_t>(1);
403
0
  } else {
404
0
    return static_cast<uint32_t>(0);
405
0
  }
406
0
}
407
408
Expect<RefVariant> Executor::proxyRefCast(Runtime::StackManager &StackMgr,
409
                                          const RefVariant Ref,
410
0
                                          ValType VTCast) noexcept {
411
  // Copy the value type here due to handling the externalized case.
412
0
  auto VT = Ref.getType();
413
0
  if (VT.isExternalized()) {
414
0
    VT = ValType(TypeCode::Ref, TypeCode::ExternRef);
415
0
  }
416
0
  const auto *ModInst = StackMgr.getModule();
417
0
  assuming(ModInst);
418
0
  Span<const AST::SubType *const> GotTypeList = ModInst->getTypeList();
419
0
  if (!VT.isAbsHeapType()) {
420
0
    auto *Inst = Ref.getPtr<Runtime::Instance::CompositeBase>();
421
    // Reference must not be nullptr here because the null references are typed
422
    // with the least abstract heap type.
423
0
    if (Inst->getModule()) {
424
0
      GotTypeList = Inst->getModule()->getTypeList();
425
0
    }
426
0
  }
427
428
0
  if (!AST::TypeMatcher::matchType(ModInst->getTypeList(), VTCast, GotTypeList,
429
0
                                   VT)) {
430
0
    return Unexpect(ErrCode::Value::CastFailed);
431
0
  }
432
0
  return Ref;
433
0
}
434
435
// For the runtime value of `uint64_t`, arguments are expected to be extended
436
// to 64-bit width in the LLVM compiler regardless of whether the address type
437
// is 32 or 64 bits. On the other hand, a `uint64_t` return should handle the
438
// conversion to a 32- or 64-bit value according to the address type in the LLVM
439
// compiler.
440
441
Expect<void> Executor::proxyTableInit(Runtime::StackManager &StackMgr,
442
                                      const uint32_t TableIdx,
443
                                      const uint32_t ElemIdx,
444
                                      const uint64_t DstOff,
445
                                      const uint32_t SrcOff,
446
0
                                      const uint32_t Len) noexcept {
447
0
  auto *TabInst = getTabInstByIdx(StackMgr, TableIdx);
448
0
  assuming(TabInst);
449
0
  auto *ElemInst = getElemInstByIdx(StackMgr, ElemIdx);
450
0
  assuming(ElemInst);
451
0
  return TabInst->setRefs(ElemInst->getRefs(), DstOff, SrcOff, Len);
452
0
}
453
454
Expect<void> Executor::proxyElemDrop(Runtime::StackManager &StackMgr,
455
0
                                     const uint32_t ElemIdx) noexcept {
456
0
  auto *ElemInst = getElemInstByIdx(StackMgr, ElemIdx);
457
0
  assuming(ElemInst);
458
0
  ElemInst->clear();
459
0
  return {};
460
0
}
461
462
Expect<void> Executor::proxyTableCopy(Runtime::StackManager &StackMgr,
463
                                      const uint32_t TableIdxDst,
464
                                      const uint32_t TableIdxSrc,
465
                                      const uint64_t DstOff,
466
                                      const uint64_t SrcOff,
467
0
                                      const uint64_t Len) noexcept {
468
0
  auto *TabInstDst = getTabInstByIdx(StackMgr, TableIdxDst);
469
0
  assuming(TabInstDst);
470
0
  auto *TabInstSrc = getTabInstByIdx(StackMgr, 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> Executor::proxyTableGrow(Runtime::StackManager &StackMgr,
478
                                          const uint32_t TableIdx,
479
                                          const RefVariant Val,
480
0
                                          const uint64_t NewSize) noexcept {
481
0
  auto *TabInst = getTabInstByIdx(StackMgr, TableIdx);
482
0
  assuming(TabInst);
483
0
  const auto AddrType = TabInst->getTableType().getLimit().getAddrType();
484
0
  const uint64_t CurrTableSize = TabInst->getSize();
485
0
  if (likely(TabInst->growTable(NewSize, Val))) {
486
0
    return CurrTableSize;
487
0
  } else {
488
0
    switch (AddrType) {
489
0
    case AddressType::I32:
490
0
      return static_cast<uint32_t>(-1);
491
0
    case AddressType::I64:
492
0
      return static_cast<uint64_t>(-1);
493
0
    default:
494
0
      assumingUnreachable();
495
0
    }
496
0
  }
497
0
}
498
499
Expect<void> Executor::proxyTableFill(Runtime::StackManager &StackMgr,
500
                                      const uint32_t TableIdx,
501
                                      const uint64_t Off, const RefVariant Ref,
502
0
                                      const uint64_t Len) noexcept {
503
0
  auto *TabInst = getTabInstByIdx(StackMgr, TableIdx);
504
0
  assuming(TabInst);
505
0
  return TabInst->fillRefs(Ref, Off, Len);
506
0
}
507
508
Expect<uint64_t> Executor::proxyMemGrow(Runtime::StackManager &StackMgr,
509
                                        const uint32_t MemIdx,
510
0
                                        const uint64_t NewSize) noexcept {
511
0
  auto *MemInst = getMemInstByIdx(StackMgr, MemIdx);
512
0
  assuming(MemInst);
513
0
  const auto AddrType = MemInst->getMemoryType().getLimit().getAddrType();
514
0
  const uint64_t CurrPageSize = MemInst->getPageSize();
515
0
  if (MemInst->growPage(NewSize)) {
516
0
    return CurrPageSize;
517
0
  } else {
518
0
    switch (AddrType) {
519
0
    case AddressType::I32:
520
0
      return static_cast<uint32_t>(-1);
521
0
    case AddressType::I64:
522
0
      return static_cast<uint64_t>(-1);
523
0
    default:
524
0
      assumingUnreachable();
525
0
    }
526
0
  }
527
0
}
528
529
Expect<void>
530
Executor::proxyMemInit(Runtime::StackManager &StackMgr, const uint32_t MemIdx,
531
                       const uint32_t DataIdx, const uint64_t DstOff,
532
0
                       const uint32_t SrcOff, const uint32_t Len) noexcept {
533
0
  auto *MemInst = getMemInstByIdx(StackMgr, MemIdx);
534
0
  assuming(MemInst);
535
0
  auto *DataInst = getDataInstByIdx(StackMgr, DataIdx);
536
0
  assuming(DataInst);
537
0
  return MemInst->setBytes(DataInst->getData(), DstOff, SrcOff, Len);
538
0
}
539
540
Expect<void> Executor::proxyDataDrop(Runtime::StackManager &StackMgr,
541
0
                                     const uint32_t DataIdx) noexcept {
542
0
  auto *DataInst = getDataInstByIdx(StackMgr, DataIdx);
543
0
  assuming(DataInst);
544
0
  DataInst->clear();
545
0
  return {};
546
0
}
547
548
Expect<void> Executor::proxyMemCopy(Runtime::StackManager &StackMgr,
549
                                    const uint32_t DstMemIdx,
550
                                    const uint32_t SrcMemIdx,
551
                                    const uint64_t DstOff,
552
                                    const uint64_t SrcOff,
553
0
                                    const uint64_t Len) noexcept {
554
0
  auto *MemInstDst = getMemInstByIdx(StackMgr, DstMemIdx);
555
0
  assuming(MemInstDst);
556
0
  auto *MemInstSrc = getMemInstByIdx(StackMgr, SrcMemIdx);
557
0
  assuming(MemInstSrc);
558
559
0
  EXPECTED_TRY(auto Data, MemInstSrc->getBytes(SrcOff, Len));
560
0
  return MemInstDst->setBytes(Data, DstOff, 0, Len);
561
0
}
562
563
Expect<void> Executor::proxyMemFill(Runtime::StackManager &StackMgr,
564
                                    const uint32_t MemIdx, const uint64_t Off,
565
                                    const uint8_t Val,
566
0
                                    const uint64_t Len) noexcept {
567
0
  auto *MemInst = getMemInstByIdx(StackMgr, MemIdx);
568
0
  assuming(MemInst);
569
0
  return MemInst->fillBytes(Val, Off, Len);
570
0
}
571
572
Expect<uint64_t> Executor::proxyMemAtomicNotify(Runtime::StackManager &StackMgr,
573
                                                const uint32_t MemIdx,
574
                                                const uint64_t Offset,
575
0
                                                const uint64_t Count) noexcept {
576
0
  auto *MemInst = getMemInstByIdx(StackMgr, MemIdx);
577
0
  assuming(MemInst);
578
0
  return atomicNotify(*MemInst, Offset, Count);
579
0
}
580
581
Expect<uint64_t>
582
Executor::proxyMemAtomicWait(Runtime::StackManager &StackMgr,
583
                             const uint32_t MemIdx, const uint64_t Offset,
584
                             const uint64_t Expected, const int64_t Timeout,
585
0
                             const uint32_t BitWidth) noexcept {
586
0
  auto *MemInst = getMemInstByIdx(StackMgr, MemIdx);
587
0
  assuming(MemInst);
588
589
0
  if (BitWidth == 64) {
590
0
    return atomicWait<uint64_t>(*MemInst, Offset, Expected, Timeout);
591
0
  } else if (BitWidth == 32) {
592
0
    return atomicWait<uint32_t>(*MemInst, Offset,
593
0
                                static_cast<uint32_t>(Expected), Timeout);
594
0
  }
595
0
  assumingUnreachable();
596
0
}
597
598
Expect<void *> Executor::proxyTableGetFuncSymbol(
599
    Runtime::StackManager &StackMgr, const uint32_t TableIdx,
600
0
    const uint32_t FuncTypeIdx, const uint32_t FuncIdx) noexcept {
601
0
  const auto *TabInst = getTabInstByIdx(StackMgr, TableIdx);
602
0
  assuming(TabInst);
603
604
0
  if (unlikely(FuncIdx >= TabInst->getSize())) {
605
0
    return Unexpect(ErrCode::Value::UndefinedElement);
606
0
  }
607
608
0
  auto Ref = TabInst->getRefAddr(FuncIdx);
609
0
  assuming(Ref);
610
0
  if (unlikely(Ref->isNull())) {
611
0
    return Unexpect(ErrCode::Value::UninitializedElement);
612
0
  }
613
614
0
  const auto *ModInst = StackMgr.getModule();
615
0
  assuming(ModInst);
616
0
  const auto &ExpDefType = *ModInst->unsafeGetType(FuncTypeIdx);
617
0
  const auto *FuncInst = retrieveFuncRef(*Ref);
618
0
  assuming(FuncInst);
619
0
  bool IsMatch = false;
620
  // Check if the function type matches the expected type.
621
0
  if (FuncInst->getModule() == ModInst &&
622
0
      *ExpDefType.getTypeIndex() == FuncInst->getTypeIndex()) {
623
    // Fast path: If the function instance is in the same module instance, we
624
    // can bypass the expensive structural type matching (O(N)) by checking the
625
    // type index directly (O(1)).
626
0
    IsMatch = true;
627
0
  } else if (FuncInst->getModule()) {
628
    // If the type index is not the same, we still need to check the type
629
    // structure. This is because the type alias may have different type
630
    // indices but the same type structure.
631
0
    IsMatch = AST::TypeMatcher::matchType(
632
0
        ModInst->getTypeList(), *ExpDefType.getTypeIndex(),
633
0
        FuncInst->getModule()->getTypeList(), FuncInst->getTypeIndex());
634
0
  } else {
635
    // Independent host module instance case. Matching the composite type
636
    // directly.
637
0
    IsMatch = AST::TypeMatcher::matchType(
638
0
        ModInst->getTypeList(), ExpDefType.getCompositeType(),
639
0
        FuncInst->getHostFunc().getDefinedType().getCompositeType());
640
0
  }
641
0
  if (!IsMatch) {
642
0
    return Unexpect(ErrCode::Value::IndirectCallTypeMismatch);
643
0
  }
644
645
0
  EXPECTED_TRY(checkLazyCompilation(FuncInst));
646
647
0
  if (unlikely(!FuncInst->isCompiledFunction())) {
648
0
    return nullptr;
649
0
  }
650
0
  return FuncInst->getSymbol().get();
651
0
}
652
653
Expect<void *> Executor::proxyRefGetFuncSymbol(Runtime::StackManager &,
654
0
                                               const RefVariant Ref) noexcept {
655
0
  const auto *FuncInst = retrieveFuncRef(Ref);
656
0
  assuming(FuncInst);
657
0
  if (likely(FuncInst->isCompiledFunction())) {
658
0
    return FuncInst->getSymbol().get();
659
0
  }
660
0
  EXPECTED_TRY(checkLazyCompilation(FuncInst));
661
662
0
  if (unlikely(!FuncInst->isCompiledFunction())) {
663
0
    return nullptr;
664
0
  }
665
0
  return FuncInst->getSymbol().get();
666
0
}
667
668
Expect<void *>
669
Executor::proxyFuncGetFuncSymbol(Runtime::StackManager &StackMgr,
670
0
                                 const uint32_t FuncIdx) noexcept {
671
0
  const auto *FuncInst = getFuncInstByIdx(StackMgr, FuncIdx);
672
0
  assuming(FuncInst);
673
0
  if (likely(FuncInst->isCompiledFunction())) {
674
0
    return FuncInst->getSymbol().get();
675
0
  }
676
0
  EXPECTED_TRY(checkLazyCompilation(FuncInst));
677
678
0
  if (unlikely(!FuncInst->isCompiledFunction())) {
679
0
    return nullptr;
680
0
  }
681
0
  return FuncInst->getSymbol().get();
682
0
}
683
684
Expect<void> Executor::proxyThrow(Runtime::StackManager &StackMgr,
685
                                  const uint32_t TagIdx, const ValVariant *Vals,
686
0
                                  const uint32_t Num) noexcept {
687
0
  auto *TagInst = getTagInstByIdx(StackMgr, TagIdx);
688
0
  assuming(TagInst);
689
0
  assuming(TagInst->getTagType().getAssocValSize() == Num);
690
0
  PendingExn.TagInst = TagInst;
691
0
  PendingExn.Inst = nullptr;
692
0
  PendingExn.setPayload(Span<const ValVariant>(Vals, Num));
693
0
  return {};
694
0
}
695
696
Expect<void> Executor::proxyThrowRef(Runtime::StackManager &,
697
0
                                     const RefVariant Ref) noexcept {
698
0
  const auto *ExnInst = Ref.getPtr<Runtime::Instance::ExceptionInstance>();
699
0
  if (unlikely(ExnInst == nullptr)) {
700
0
    return Unexpect(ErrCode::Value::AccessNullException);
701
0
  }
702
0
  PendingExn.TagInst = ExnInst->getTag();
703
0
  PendingExn.Inst = ExnInst;
704
0
  PendingExn.setPayload(ExnInst->getPayload());
705
0
  return {};
706
0
}
707
708
Expect<void> Executor::proxyCatchPop(Runtime::StackManager &StackMgr,
709
                                     ValVariant *Out, const uint32_t PopPayload,
710
0
                                     const uint32_t NeedRef) noexcept {
711
0
  auto *TagInst = PendingExn.TagInst;
712
0
  assuming(TagInst);
713
0
  uint32_t Idx = 0;
714
0
  if (PopPayload != 0) {
715
0
    Idx = TagInst->getTagType().getAssocValSize();
716
0
    std::copy_n(PendingExn.getPayload().begin(), Idx, Out);
717
0
  }
718
0
  if (NeedRef != 0) {
719
0
    const auto *Inst = PendingExn.Inst;
720
0
    if (Inst == nullptr) {
721
0
      auto *ModInst =
722
0
          const_cast<Runtime::Instance::ModuleInstance *>(StackMgr.getModule());
723
0
      assuming(ModInst);
724
0
      Inst = ModInst->newException(
725
0
          TagInst, std::vector<ValVariant>(PendingExn.getPayload()));
726
0
    }
727
0
    Out[Idx] = RefVariant(ValType(TypeCode::Ref, TypeCode::ExnRef), Inst);
728
0
  }
729
0
  PendingExn = {};
730
0
  return {};
731
0
}
732
733
} // namespace Executor
734
} // namespace WasmEdge