Coverage Report

Created: 2026-07-16 07:09

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