Coverage Report

Created: 2026-06-30 06:10

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