Coverage Report

Created: 2026-11-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/WasmEdge/lib/executor/engine/refInstr.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
6
namespace WasmEdge {
7
namespace Executor {
8
9
namespace {
10
11
template <typename... T>
12
ErrCode logError(const ErrCode &Code, const AST::Instruction &Instr,
13
0
                 T &&...F) noexcept {
14
0
  spdlog::error(Code);
15
0
  (F(), ...);
16
0
  spdlog::error(ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
17
0
  return Code;
18
0
}
Unexecuted instantiation: refInstr.cpp:WasmEdge::ErrCode WasmEdge::Executor::(anonymous namespace)::logError<WasmEdge::Executor::Executor::runArrayNewDataOp(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}>(WasmEdge::ErrCode const&, WasmEdge::AST::Instruction const&, WasmEdge::Executor::Executor::runArrayNewDataOp(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}&&)
Unexecuted instantiation: refInstr.cpp:WasmEdge::ErrCode WasmEdge::Executor::(anonymous namespace)::logError<WasmEdge::Executor::Executor::runArrayNewElemOp(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}>(WasmEdge::ErrCode const&, WasmEdge::AST::Instruction const&, WasmEdge::Executor::Executor::runArrayNewElemOp(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}&&)
Unexecuted instantiation: refInstr.cpp:WasmEdge::ErrCode WasmEdge::Executor::(anonymous namespace)::logError<WasmEdge::Executor::Executor::runArrayGetOp(WasmEdge::Runtime::StackManager&, unsigned int, WasmEdge::AST::Instruction const&, bool) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}>(WasmEdge::ErrCode const&, WasmEdge::AST::Instruction const&, WasmEdge::Executor::Executor::runArrayGetOp(WasmEdge::Runtime::StackManager&, unsigned int, WasmEdge::AST::Instruction const&, bool) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}&&)
Unexecuted instantiation: refInstr.cpp:WasmEdge::ErrCode WasmEdge::Executor::(anonymous namespace)::logError<WasmEdge::Executor::Executor::runArraySetOp(WasmEdge::Runtime::StackManager&, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, cxx26::simd::basic_vec<unsigned long, cxx26::simd::detail::vector_ext_abi<2> >, cxx26::simd::basic_vec<long, cxx26::simd::detail::vector_ext_abi<2> >, cxx26::simd::basic_vec<unsigned int, cxx26::simd::detail::vector_ext_abi<4> >, cxx26::simd::basic_vec<int, cxx26::simd::detail::vector_ext_abi<4> >, cxx26::simd::basic_vec<unsigned short, cxx26::simd::detail::vector_ext_abi<8> >, cxx26::simd::basic_vec<short, cxx26::simd::detail::vector_ext_abi<8> >, cxx26::simd::basic_vec<unsigned char, cxx26::simd::detail::vector_ext_abi<16> >, cxx26::simd::basic_vec<signed char, cxx26::simd::detail::vector_ext_abi<16> >, cxx26::simd::basic_vec<float, cxx26::simd::detail::vector_ext_abi<4> >, cxx26::simd::basic_vec<double, cxx26::simd::detail::vector_ext_abi<2> >, WasmEdge::RefVariant> const&, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}>(WasmEdge::ErrCode const&, WasmEdge::AST::Instruction const&, WasmEdge::Executor::Executor::runArraySetOp(WasmEdge::Runtime::StackManager&, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, cxx26::simd::basic_vec<unsigned long, cxx26::simd::detail::vector_ext_abi<2> >, cxx26::simd::basic_vec<long, cxx26::simd::detail::vector_ext_abi<2> >, cxx26::simd::basic_vec<unsigned int, cxx26::simd::detail::vector_ext_abi<4> >, cxx26::simd::basic_vec<int, cxx26::simd::detail::vector_ext_abi<4> >, cxx26::simd::basic_vec<unsigned short, cxx26::simd::detail::vector_ext_abi<8> >, cxx26::simd::basic_vec<short, cxx26::simd::detail::vector_ext_abi<8> >, cxx26::simd::basic_vec<unsigned char, cxx26::simd::detail::vector_ext_abi<16> >, cxx26::simd::basic_vec<signed char, cxx26::simd::detail::vector_ext_abi<16> >, cxx26::simd::basic_vec<float, cxx26::simd::detail::vector_ext_abi<4> >, cxx26::simd::basic_vec<double, cxx26::simd::detail::vector_ext_abi<2> >, WasmEdge::RefVariant> const&, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}&&)
Unexecuted instantiation: refInstr.cpp:WasmEdge::ErrCode WasmEdge::Executor::(anonymous namespace)::logError<WasmEdge::Executor::Executor::runArrayFillOp(WasmEdge::Runtime::StackManager&, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, cxx26::simd::basic_vec<unsigned long, cxx26::simd::detail::vector_ext_abi<2> >, cxx26::simd::basic_vec<long, cxx26::simd::detail::vector_ext_abi<2> >, cxx26::simd::basic_vec<unsigned int, cxx26::simd::detail::vector_ext_abi<4> >, cxx26::simd::basic_vec<int, cxx26::simd::detail::vector_ext_abi<4> >, cxx26::simd::basic_vec<unsigned short, cxx26::simd::detail::vector_ext_abi<8> >, cxx26::simd::basic_vec<short, cxx26::simd::detail::vector_ext_abi<8> >, cxx26::simd::basic_vec<unsigned char, cxx26::simd::detail::vector_ext_abi<16> >, cxx26::simd::basic_vec<signed char, cxx26::simd::detail::vector_ext_abi<16> >, cxx26::simd::basic_vec<float, cxx26::simd::detail::vector_ext_abi<4> >, cxx26::simd::basic_vec<double, cxx26::simd::detail::vector_ext_abi<2> >, WasmEdge::RefVariant> const&, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}>(WasmEdge::ErrCode const&, WasmEdge::AST::Instruction const&, WasmEdge::Executor::Executor::runArrayFillOp(WasmEdge::Runtime::StackManager&, unsigned int, WasmEdge::Variant<unsigned int, int, unsigned long, long, float, double, unsigned __int128, __int128, cxx26::simd::basic_vec<unsigned long, cxx26::simd::detail::vector_ext_abi<2> >, cxx26::simd::basic_vec<long, cxx26::simd::detail::vector_ext_abi<2> >, cxx26::simd::basic_vec<unsigned int, cxx26::simd::detail::vector_ext_abi<4> >, cxx26::simd::basic_vec<int, cxx26::simd::detail::vector_ext_abi<4> >, cxx26::simd::basic_vec<unsigned short, cxx26::simd::detail::vector_ext_abi<8> >, cxx26::simd::basic_vec<short, cxx26::simd::detail::vector_ext_abi<8> >, cxx26::simd::basic_vec<unsigned char, cxx26::simd::detail::vector_ext_abi<16> >, cxx26::simd::basic_vec<signed char, cxx26::simd::detail::vector_ext_abi<16> >, cxx26::simd::basic_vec<float, cxx26::simd::detail::vector_ext_abi<4> >, cxx26::simd::basic_vec<double, cxx26::simd::detail::vector_ext_abi<2> >, WasmEdge::RefVariant> const&, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}&&)
Unexecuted instantiation: refInstr.cpp:WasmEdge::ErrCode WasmEdge::Executor::(anonymous namespace)::logError<WasmEdge::Executor::Executor::runArrayCopyOp(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}>(WasmEdge::ErrCode const&, WasmEdge::AST::Instruction const&, WasmEdge::Executor::Executor::runArrayCopyOp(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}&&)
Unexecuted instantiation: refInstr.cpp:WasmEdge::ErrCode WasmEdge::Executor::(anonymous namespace)::logError<WasmEdge::Executor::Executor::runArrayInitDataOp(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}, WasmEdge::Executor::Executor::runArrayInitDataOp(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#2}>(WasmEdge::ErrCode const&, WasmEdge::AST::Instruction const&, WasmEdge::Executor::Executor::runArrayInitDataOp(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}&&, WasmEdge::Executor::Executor::runArrayInitDataOp(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#2}&&)
Unexecuted instantiation: refInstr.cpp:WasmEdge::ErrCode WasmEdge::Executor::(anonymous namespace)::logError<WasmEdge::Executor::Executor::runArrayInitElemOp(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}, WasmEdge::Executor::Executor::runArrayInitElemOp(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#2}>(WasmEdge::ErrCode const&, WasmEdge::AST::Instruction const&, WasmEdge::Executor::Executor::runArrayInitElemOp(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#1}&&, WasmEdge::Executor::Executor::runArrayInitElemOp(WasmEdge::Runtime::StackManager&, unsigned int, unsigned int, unsigned int, WasmEdge::AST::Instruction const&) const::$_0::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const::{lambda()#2}&&)
19
20
0
ErrCode logError(const ErrCode &Code, const AST::Instruction &Instr) noexcept {
21
0
  spdlog::error(Code);
22
0
  spdlog::error(ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
23
0
  return Code;
24
0
}
25
26
void logArrayOOB(const ErrCode &Code, const uint32_t Idx, const uint32_t Cnt,
27
0
                 const RefVariant &Ref) noexcept {
28
0
  if (Code == ErrCode::Value::ArrayOutOfBounds) {
29
0
    const auto *Inst = Ref.getPtr<Runtime::Instance::ArrayInstance>();
30
0
    spdlog::error(ErrInfo::InfoBoundary(static_cast<uint64_t>(Idx), Cnt,
31
0
                                        Inst->getLength()));
32
0
  }
33
0
}
34
35
void logDoubleArrayOOB(const ErrCode &Code, const uint32_t Idx1,
36
                       const uint32_t Cnt1, const RefVariant &Ref1,
37
                       const uint32_t Idx2, const uint32_t Cnt2,
38
0
                       const RefVariant &Ref2) noexcept {
39
0
  if (Code == ErrCode::Value::ArrayOutOfBounds) {
40
0
    const auto *Inst1 = Ref1.getPtr<Runtime::Instance::ArrayInstance>();
41
0
    const auto *Inst2 = Ref2.getPtr<Runtime::Instance::ArrayInstance>();
42
0
    if (static_cast<uint64_t>(Idx1) + static_cast<uint64_t>(Cnt1) >
43
0
        Inst1->getLength()) {
44
0
      spdlog::error(ErrInfo::InfoBoundary(static_cast<uint64_t>(Idx1), Cnt1,
45
0
                                          Inst1->getLength()));
46
0
    } else if (static_cast<uint64_t>(Idx2) + static_cast<uint64_t>(Cnt2) >
47
0
               Inst2->getLength()) {
48
0
      spdlog::error(ErrInfo::InfoBoundary(static_cast<uint64_t>(Idx2), Cnt2,
49
0
                                          Inst2->getLength()));
50
0
    }
51
0
  }
52
0
}
53
54
void logMemoryOOB(const ErrCode &Code,
55
                  const Runtime::Instance::DataInstance &DataInst,
56
0
                  const uint32_t Idx, const uint32_t Length) noexcept {
57
0
  if (Code == ErrCode::Value::MemoryOutOfBounds) {
58
0
    spdlog::error(ErrInfo::InfoBoundary(
59
0
        static_cast<uint64_t>(Idx), Length,
60
0
        static_cast<uint32_t>(DataInst.getData().size())));
61
0
  }
62
0
}
63
64
void logTableOOB(const ErrCode &Code,
65
                 const Runtime::Instance::ElementInstance &ElemInst,
66
0
                 const uint32_t Idx, const uint32_t Length) noexcept {
67
0
  if (Code == ErrCode::Value::TableOutOfBounds) {
68
0
    auto ElemSrc = ElemInst.getRefs();
69
0
    spdlog::error(ErrInfo::InfoBoundary(static_cast<uint64_t>(Idx), Length,
70
0
                                        static_cast<uint32_t>(ElemSrc.size())));
71
0
  }
72
0
}
73
74
} // namespace
75
76
Expect<void> Executor::runRefNullOp(Runtime::StackManager &StackMgr,
77
0
                                    const ValType &Type) const noexcept {
78
  // A null reference is typed with the least type in its respective hierarchy.
79
0
  StackMgr.push(RefVariant(toBottomType(StackMgr.getModule(), Type)));
80
0
  return {};
81
0
}
82
83
0
Expect<void> Executor::runRefIsNullOp(ValVariant &Val) const noexcept {
84
0
  Val.emplace<uint32_t>(Val.get<RefVariant>().isNull() ? 1U : 0U);
85
0
  return {};
86
0
}
87
88
Expect<void> Executor::runRefFuncOp(Runtime::StackManager &StackMgr,
89
0
                                    uint32_t Idx) const noexcept {
90
0
  const auto *FuncInst = getFuncInstByIdx(StackMgr.getModule(), Idx);
91
0
  StackMgr.push(RefVariant(FuncInst->getDefType(), FuncInst));
92
0
  return {};
93
0
}
94
95
Expect<void> Executor::runRefEqOp(ValVariant &Val1,
96
0
                                  const ValVariant &Val2) const noexcept {
97
0
  Val1.emplace<uint32_t>(Val1.get<RefVariant>().getPtr<void>() ==
98
0
                                 Val2.get<RefVariant>().getPtr<void>()
99
0
                             ? 1U
100
0
                             : 0U);
101
0
  return {};
102
0
}
103
104
Expect<void>
105
Executor::runRefAsNonNullOp(RefVariant &Ref,
106
0
                            const AST::Instruction &Instr) const noexcept {
107
0
  if (Ref.isNull()) {
108
0
    return Unexpect(logError(ErrCode::Value::CastNullToNonNull, Instr));
109
0
  }
110
0
  ValType Type = Ref.getType();
111
0
  Ref.setType(Type.toNonNullableRef());
112
0
  return {};
113
0
}
114
115
Expect<void> Executor::runStructNewOp(Runtime::StackManager &StackMgr,
116
                                      const uint32_t TypeIdx,
117
0
                                      const bool IsDefault) const noexcept {
118
0
  if (IsDefault) {
119
0
    StackMgr.push(*structNew(StackMgr.getModule(), TypeIdx));
120
0
  } else {
121
0
    const auto &CompType = getCompositeTypeByIdx(StackMgr.getModule(), TypeIdx);
122
0
    const uint32_t N = static_cast<uint32_t>(CompType.getFieldTypes().size());
123
0
    std::vector<ValVariant> Vals = StackMgr.pop(N);
124
0
    StackMgr.push(*structNew(StackMgr.getModule(), TypeIdx, Vals));
125
0
  }
126
0
  return {};
127
0
}
128
129
Expect<void> Executor::runStructGetOp(Runtime::StackManager &StackMgr,
130
                                      const uint32_t TypeIdx,
131
                                      const uint32_t Off,
132
                                      const AST::Instruction &Instr,
133
0
                                      const bool IsSigned) const noexcept {
134
0
  const RefVariant Ref = StackMgr.getTop().get<RefVariant>();
135
0
  EXPECTED_TRY(auto Val,
136
0
               structGet(StackMgr.getModule(), Ref, TypeIdx, Off, IsSigned)
137
0
                   .map_error([&](auto E) { return logError(E, Instr); }));
138
0
  StackMgr.getTop() = Val;
139
0
  return {};
140
0
}
141
142
Expect<void>
143
Executor::runStructSetOp(Runtime::StackManager &StackMgr, const ValVariant &Val,
144
                         const uint32_t TypeIdx, const uint32_t Off,
145
0
                         const AST::Instruction &Instr) const noexcept {
146
0
  const RefVariant Ref = StackMgr.pop().get<RefVariant>();
147
0
  EXPECTED_TRY(structSet(StackMgr.getModule(), Ref, Val, TypeIdx, Off)
148
0
                   .map_error([&](auto E) { return logError(E, Instr); }));
149
0
  return {};
150
0
}
151
152
Expect<void> Executor::runArrayNewOp(Runtime::StackManager &StackMgr,
153
                                     const uint32_t TypeIdx,
154
                                     const uint32_t InitCnt,
155
0
                                     uint32_t Length) const noexcept {
156
0
  assuming(InitCnt == 0 || InitCnt == 1 || InitCnt == Length);
157
0
  if (InitCnt == 0) {
158
0
    StackMgr.push(*arrayNew(StackMgr.getModule(), TypeIdx, Length));
159
0
  } else if (InitCnt == 1) {
160
0
    StackMgr.getTop().emplace<RefVariant>(
161
0
        *arrayNew(StackMgr.getModule(), TypeIdx, Length, {StackMgr.getTop()}));
162
0
  } else {
163
0
    StackMgr.push(
164
0
        *arrayNew(StackMgr.getModule(), TypeIdx, Length, StackMgr.pop(Length)));
165
0
  }
166
0
  return {};
167
0
}
168
169
Expect<void>
170
Executor::runArrayNewDataOp(Runtime::StackManager &StackMgr,
171
                            const uint32_t TypeIdx, const uint32_t DataIdx,
172
0
                            const AST::Instruction &Instr) const noexcept {
173
0
  const uint32_t Length = StackMgr.pop().get<uint32_t>();
174
0
  const uint32_t Start = StackMgr.getTop().get<uint32_t>();
175
0
  EXPECTED_TRY(
176
0
      auto InstRef,
177
0
      arrayNewData(StackMgr.getModule(), TypeIdx, DataIdx, Start, Length)
178
0
          .map_error([&](auto E) {
179
0
            auto *DataInst = getDataInstByIdx(StackMgr.getModule(), DataIdx);
180
0
            const uint32_t BSize =
181
0
                getArrayStorageTypeByIdx(StackMgr.getModule(), TypeIdx)
182
0
                    .getBitWidth() /
183
0
                8;
184
0
            return logError(E, Instr, [&]() {
185
0
              return logMemoryOOB(E, *DataInst, Start, BSize * Length);
186
0
            });
187
0
          }));
188
0
  StackMgr.getTop().emplace<RefVariant>(InstRef);
189
0
  return {};
190
0
}
191
192
Expect<void>
193
Executor::runArrayNewElemOp(Runtime::StackManager &StackMgr,
194
                            const uint32_t TypeIdx, const uint32_t ElemIdx,
195
0
                            const AST::Instruction &Instr) const noexcept {
196
0
  const uint32_t Length = StackMgr.pop().get<uint32_t>();
197
0
  const uint32_t Start = StackMgr.getTop().get<uint32_t>();
198
0
  EXPECTED_TRY(
199
0
      auto InstRef,
200
0
      arrayNewElem(StackMgr.getModule(), TypeIdx, ElemIdx, Start, Length)
201
0
          .map_error([&](auto E) {
202
0
            auto *ElemInst = getElemInstByIdx(StackMgr.getModule(), ElemIdx);
203
0
            return logError(E, Instr, [&]() {
204
0
              return logTableOOB(E, *ElemInst, Start, Length);
205
0
            });
206
0
          }));
207
0
  StackMgr.getTop().emplace<RefVariant>(InstRef);
208
0
  return {};
209
0
}
210
211
Expect<void> Executor::runArrayGetOp(Runtime::StackManager &StackMgr,
212
                                     const uint32_t TypeIdx,
213
                                     const AST::Instruction &Instr,
214
0
                                     const bool IsSigned) const noexcept {
215
0
  const uint32_t Idx = StackMgr.pop().get<uint32_t>();
216
0
  const RefVariant Ref = StackMgr.getTop().get<RefVariant>();
217
0
  EXPECTED_TRY(auto Val,
218
0
               arrayGet(StackMgr.getModule(), Ref, TypeIdx, Idx, IsSigned)
219
0
                   .map_error([&](auto E) {
220
0
                     return logError(E, Instr, [&]() {
221
0
                       return logArrayOOB(E, Idx, 1, Ref);
222
0
                     });
223
0
                   }));
224
0
  StackMgr.getTop() = Val;
225
0
  return {};
226
0
}
227
228
Expect<void>
229
Executor::runArraySetOp(Runtime::StackManager &StackMgr, const ValVariant &Val,
230
                        const uint32_t TypeIdx,
231
0
                        const AST::Instruction &Instr) const noexcept {
232
0
  const uint32_t Idx = StackMgr.pop().get<uint32_t>();
233
0
  const RefVariant Ref = StackMgr.pop().get<RefVariant>();
234
0
  EXPECTED_TRY(arraySet(StackMgr.getModule(), Ref, Val, TypeIdx, Idx)
235
0
                   .map_error([&](auto E) {
236
0
                     return logError(E, Instr, [&]() {
237
0
                       return logArrayOOB(E, Idx, 1, Ref);
238
0
                     });
239
0
                   }));
240
0
  return {};
241
0
}
242
243
Expect<void>
244
Executor::runArrayLenOp(ValVariant &Val,
245
0
                        const AST::Instruction &Instr) const noexcept {
246
0
  const auto *Inst =
247
0
      Val.get<RefVariant>().getPtr<Runtime::Instance::ArrayInstance>();
248
0
  if (Inst == nullptr) {
249
0
    return Unexpect(logError(ErrCode::Value::AccessNullArray, Instr));
250
0
  }
251
0
  Val.emplace<uint32_t>(Inst->getLength());
252
0
  return {};
253
0
}
254
255
Expect<void>
256
Executor::runArrayFillOp(Runtime::StackManager &StackMgr, const uint32_t Cnt,
257
                         const ValVariant &Val, const uint32_t TypeIdx,
258
0
                         const AST::Instruction &Instr) const noexcept {
259
0
  const uint32_t Idx = StackMgr.pop().get<uint32_t>();
260
0
  const RefVariant Ref = StackMgr.pop().get<RefVariant>();
261
0
  EXPECTED_TRY(arrayFill(StackMgr.getModule(), Ref, Val, TypeIdx, Idx, Cnt)
262
0
                   .map_error([&](auto E) {
263
0
                     return logError(E, Instr, [&]() {
264
0
                       return logArrayOOB(E, Idx, Cnt, Ref);
265
0
                     });
266
0
                   }));
267
0
  return {};
268
0
}
269
270
Expect<void>
271
Executor::runArrayCopyOp(Runtime::StackManager &StackMgr, const uint32_t Cnt,
272
                         const uint32_t DstTypeIdx, const uint32_t SrcTypeIdx,
273
0
                         const AST::Instruction &Instr) const noexcept {
274
0
  const uint32_t SrcIdx = StackMgr.pop().get<uint32_t>();
275
0
  const RefVariant SrcRef = StackMgr.pop().get<RefVariant>();
276
0
  const uint32_t DstIdx = StackMgr.pop().get<uint32_t>();
277
0
  const RefVariant DstRef = StackMgr.pop().get<RefVariant>();
278
0
  EXPECTED_TRY(arrayCopy(StackMgr.getModule(), DstRef, DstTypeIdx, DstIdx,
279
0
                         SrcRef, SrcTypeIdx, SrcIdx, Cnt)
280
0
                   .map_error([&](auto E) {
281
0
                     return logError(E, Instr, [&]() {
282
0
                       return logDoubleArrayOOB(E, SrcIdx, Cnt, SrcRef, DstIdx,
283
0
                                                Cnt, DstRef);
284
0
                     });
285
0
                   }));
286
0
  return {};
287
0
}
288
289
Expect<void> Executor::runArrayInitDataOp(
290
    Runtime::StackManager &StackMgr, const uint32_t Cnt, const uint32_t TypeIdx,
291
0
    const uint32_t DataIdx, const AST::Instruction &Instr) const noexcept {
292
0
  const uint32_t SrcIdx = StackMgr.pop().get<uint32_t>();
293
0
  const uint32_t DstIdx = StackMgr.pop().get<uint32_t>();
294
0
  const RefVariant Ref = StackMgr.pop().get<RefVariant>();
295
0
  EXPECTED_TRY(
296
0
      arrayInitData(StackMgr.getModule(), Ref, TypeIdx, DataIdx, DstIdx, SrcIdx,
297
0
                    Cnt)
298
0
          .map_error([&](auto E) {
299
0
            auto *DataInst = getDataInstByIdx(StackMgr.getModule(), DataIdx);
300
0
            const uint32_t BSize =
301
0
                getArrayStorageTypeByIdx(StackMgr.getModule(), TypeIdx)
302
0
                    .getBitWidth() /
303
0
                8;
304
0
            return logError(
305
0
                E, Instr, [&]() { return logArrayOOB(E, DstIdx, Cnt, Ref); },
306
0
                [&]() {
307
0
                  return logMemoryOOB(E, *DataInst, SrcIdx, Cnt * BSize);
308
0
                });
309
0
          }));
310
0
  return {};
311
0
}
312
313
Expect<void> Executor::runArrayInitElemOp(
314
    Runtime::StackManager &StackMgr, const uint32_t Cnt, const uint32_t TypeIdx,
315
0
    const uint32_t ElemIdx, const AST::Instruction &Instr) const noexcept {
316
0
  const uint32_t SrcIdx = StackMgr.pop().get<uint32_t>();
317
0
  const uint32_t DstIdx = StackMgr.pop().get<uint32_t>();
318
0
  const RefVariant Ref = StackMgr.pop().get<RefVariant>();
319
0
  EXPECTED_TRY(
320
0
      arrayInitElem(StackMgr.getModule(), Ref, TypeIdx, ElemIdx, DstIdx, SrcIdx,
321
0
                    Cnt)
322
0
          .map_error([&](auto E) {
323
0
            auto *ElemInst = getElemInstByIdx(StackMgr.getModule(), ElemIdx);
324
0
            return logError(
325
0
                E, Instr, [&]() { return logArrayOOB(E, DstIdx, Cnt, Ref); },
326
0
                [&]() { return logTableOOB(E, *ElemInst, SrcIdx, Cnt); });
327
0
          }));
328
0
  return {};
329
0
}
330
331
Expect<void>
332
Executor::runRefTestOp(const Runtime::Instance::ModuleInstance *ModInst,
333
                       ValVariant &Val, const AST::Instruction &Instr,
334
0
                       const bool IsCast) const noexcept {
335
0
  if (matchRef(ModInst, Instr.getValType(), Val.get<RefVariant>())) {
336
0
    if (!IsCast) {
337
0
      Val.emplace<uint32_t>(1U);
338
0
    }
339
0
  } else {
340
0
    if (IsCast) {
341
0
      spdlog::error(ErrCode::Value::CastFailed);
342
0
      spdlog::error(ErrInfo::InfoMismatch(Instr.getValType(),
343
0
                                          Val.get<RefVariant>().getType()));
344
0
      spdlog::error(
345
0
          ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
346
0
      return Unexpect(ErrCode::Value::CastFailed);
347
0
    } else {
348
0
      Val.emplace<uint32_t>(0U);
349
0
    }
350
0
  }
351
0
  return {};
352
0
}
353
354
Expect<void> Executor::runRefConvOp(RefVariant &Ref,
355
0
                                    TypeCode TCode) const noexcept {
356
0
  if (TCode == TypeCode::AnyRef) {
357
    // Internalize.
358
0
    if (Ref.isNull()) {
359
0
      Ref = RefVariant(ValType(TypeCode::RefNull, TypeCode::NullRef));
360
0
    } else {
361
0
      ValType VT = Ref.getType();
362
0
      VT.setInternalized();
363
0
      if (VT.isExternRefType()) {
364
0
        VT = ValType(TypeCode::Ref, TypeCode::AnyRef);
365
0
      }
366
0
      Ref.setType(VT);
367
0
    }
368
0
  } else {
369
    // Externalize.
370
0
    if (Ref.isNull()) {
371
0
      Ref = RefVariant(ValType(TypeCode::RefNull, TypeCode::NullExternRef));
372
0
    } else {
373
      // Use the externalize flag because the value type information should be
374
      // reserved when a reference being externalized and internalized.
375
0
      ValType VT = Ref.getType();
376
0
      VT.setExternalized();
377
0
      Ref.setType(VT);
378
0
    }
379
0
  }
380
0
  return {};
381
0
}
382
383
0
Expect<void> Executor::runRefI31Op(ValVariant &Val) const noexcept {
384
0
  uint32_t RefNum = (Val.get<uint32_t>() & 0x7FFFFFFFU) | 0x80000000U;
385
0
  Val = RefVariant(ValType(TypeCode::Ref, TypeCode::I31Ref),
386
0
                   reinterpret_cast<void *>(static_cast<uint64_t>(RefNum)));
387
0
  return {};
388
0
}
389
390
Expect<void> Executor::runI31GetOp(ValVariant &Val,
391
                                   const AST::Instruction &Instr,
392
0
                                   const bool IsSigned) const noexcept {
393
0
  uint32_t RefNum = static_cast<uint32_t>(
394
0
      reinterpret_cast<uintptr_t>(Val.get<RefVariant>().getPtr<void>()));
395
0
  if ((RefNum & 0x80000000U) == 0) {
396
0
    return Unexpect(logError(ErrCode::Value::AccessNullI31, Instr));
397
0
  }
398
0
  RefNum &= 0x7FFFFFFFU;
399
0
  if (IsSigned) {
400
0
    RefNum |= ((RefNum & 0x40000000U) << 1);
401
0
  }
402
0
  Val.emplace<uint32_t>(RefNum);
403
0
  return {};
404
0
}
405
406
Expect<RefVariant>
407
Executor::structNew(const Runtime::Instance::ModuleInstance *ModInstArg,
408
                    const uint32_t TypeIdx,
409
0
                    Span<const ValVariant> Args) const noexcept {
410
  /// TODO: The array and struct instances are currently owned by the module
411
  /// instance because they refer to the defined types of the module instances.
412
  /// This may be changed after applying the garbage collection mechanism.
413
0
  const auto &CompType = getCompositeTypeByIdx(ModInstArg, TypeIdx);
414
0
  uint32_t N = static_cast<uint32_t>(CompType.getFieldTypes().size());
415
0
  auto *ModInst = const_cast<Runtime::Instance::ModuleInstance *>(ModInstArg);
416
0
  std::vector<ValVariant> Vals(N);
417
0
  for (uint32_t I = 0; I < N; I++) {
418
0
    const auto &VType = CompType.getFieldTypes()[I].getStorageType();
419
0
    if (Args.size() > 0) {
420
0
      Vals[I] = packVal(VType, Args[I]);
421
0
    } else {
422
0
      Vals[I] = VType.isRefType()
423
0
                    ? ValVariant(RefVariant(toBottomType(ModInstArg, VType)))
424
0
                    : ValVariant(static_cast<uint128_t>(0U));
425
0
    }
426
0
  }
427
0
  WasmEdge::Runtime::Instance::StructInstance *Inst =
428
0
      ModInst->newStruct(TypeIdx, std::move(Vals));
429
0
  return RefVariant(Inst->getDefType(), Inst);
430
0
}
431
432
Expect<ValVariant>
433
Executor::structGet(const Runtime::Instance::ModuleInstance *ModInst,
434
                    const RefVariant Ref, const uint32_t TypeIdx,
435
0
                    const uint32_t Off, const bool IsSigned) const noexcept {
436
0
  const auto *Inst = Ref.getPtr<Runtime::Instance::StructInstance>();
437
0
  if (Inst == nullptr) {
438
0
    return Unexpect(ErrCode::Value::AccessNullStruct);
439
0
  }
440
0
  const auto &VType = getStructStorageTypeByIdx(ModInst, TypeIdx, Off);
441
0
  return unpackVal(VType, Inst->getField(Off), IsSigned);
442
0
}
443
444
Expect<void>
445
Executor::structSet(const Runtime::Instance::ModuleInstance *ModInst,
446
                    const RefVariant Ref, const ValVariant Val,
447
0
                    const uint32_t TypeIdx, const uint32_t Off) const noexcept {
448
0
  auto *Inst = Ref.getPtr<Runtime::Instance::StructInstance>();
449
0
  if (Inst == nullptr) {
450
0
    return Unexpect(ErrCode::Value::AccessNullStruct);
451
0
  }
452
0
  const auto &VType = getStructStorageTypeByIdx(ModInst, TypeIdx, Off);
453
0
  Inst->getField(Off) = packVal(VType, Val);
454
0
  return {};
455
0
}
456
457
Expect<RefVariant>
458
Executor::arrayNew(const Runtime::Instance::ModuleInstance *ModInstArg,
459
                   const uint32_t TypeIdx, const uint32_t Length,
460
0
                   Span<const ValVariant> Args) const noexcept {
461
  /// TODO: The array and struct instances are currently owned by the module
462
  /// instance because they refer to the defined types of the module instances.
463
  /// This may be changed after applying the garbage collection mechanism.
464
0
  const auto &VType = getArrayStorageTypeByIdx(ModInstArg, TypeIdx);
465
0
  WasmEdge::Runtime::Instance::ArrayInstance *Inst = nullptr;
466
0
  auto *ModInst = const_cast<Runtime::Instance::ModuleInstance *>(ModInstArg);
467
0
  if (Args.size() == 0) {
468
    // New and fill with default values.
469
0
    auto InitVal = VType.isRefType()
470
0
                       ? ValVariant(RefVariant(toBottomType(ModInstArg, VType)))
471
0
                       : ValVariant(static_cast<uint128_t>(0U));
472
0
    Inst = ModInst->newArray(TypeIdx, Length, InitVal);
473
0
  } else if (Args.size() == 1) {
474
    // Create and fill with the argument value.
475
0
    Inst = ModInst->newArray(TypeIdx, Length, packVal(VType, Args[0]));
476
0
  } else {
477
    // Create with arguments.
478
0
    Inst = ModInst->newArray(
479
0
        TypeIdx,
480
0
        packVals(VType, std::vector<ValVariant>(Args.begin(), Args.end())));
481
0
  }
482
0
  return RefVariant(Inst->getDefType(), Inst);
483
0
}
484
485
Expect<RefVariant>
486
Executor::arrayNewData(const Runtime::Instance::ModuleInstance *ModInstArg,
487
                       const uint32_t TypeIdx, const uint32_t DataIdx,
488
                       const uint32_t Start,
489
0
                       const uint32_t Length) const noexcept {
490
0
  const auto &VType = getArrayStorageTypeByIdx(ModInstArg, TypeIdx);
491
0
  const uint32_t BSize = VType.getBitWidth() / 8;
492
0
  auto *DataInst = getDataInstByIdx(ModInstArg, DataIdx);
493
0
  assuming(DataInst);
494
0
  if (static_cast<uint64_t>(Start) + static_cast<uint64_t>(Length) * BSize >
495
0
      DataInst->getData().size()) {
496
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
497
0
  }
498
0
  auto *ModInst = const_cast<Runtime::Instance::ModuleInstance *>(ModInstArg);
499
0
  std::vector<ValVariant> Args;
500
0
  Args.reserve(Length);
501
0
  for (uint32_t Idx = 0; Idx < Length; Idx++) {
502
    // The value has been packed.
503
0
    Args.push_back(DataInst->loadValue(Start + Idx * BSize, BSize));
504
0
  }
505
0
  WasmEdge::Runtime::Instance::ArrayInstance *Inst =
506
0
      ModInst->newArray(TypeIdx, std::move(Args));
507
0
  return RefVariant(Inst->getDefType(), Inst);
508
0
}
509
510
Expect<RefVariant>
511
Executor::arrayNewElem(const Runtime::Instance::ModuleInstance *ModInstArg,
512
                       const uint32_t TypeIdx, const uint32_t ElemIdx,
513
                       const uint32_t Start,
514
0
                       const uint32_t Length) const noexcept {
515
0
  const auto &VType = getArrayStorageTypeByIdx(ModInstArg, TypeIdx);
516
0
  auto *ElemInst = getElemInstByIdx(ModInstArg, ElemIdx);
517
0
  assuming(ElemInst);
518
0
  auto ElemSrc = ElemInst->getRefs();
519
0
  if (static_cast<uint64_t>(Start) + static_cast<uint64_t>(Length) >
520
0
      ElemSrc.size()) {
521
0
    return Unexpect(ErrCode::Value::TableOutOfBounds);
522
0
  }
523
0
  std::vector<ValVariant> Refs(ElemSrc.begin() + Start,
524
0
                               ElemSrc.begin() + Start + Length);
525
0
  auto *ModInst = const_cast<Runtime::Instance::ModuleInstance *>(ModInstArg);
526
0
  WasmEdge::Runtime::Instance::ArrayInstance *Inst =
527
0
      ModInst->newArray(TypeIdx, packVals(VType, std::move(Refs)));
528
0
  return RefVariant(Inst->getDefType(), Inst);
529
0
}
530
531
Expect<ValVariant>
532
Executor::arrayGet(const Runtime::Instance::ModuleInstance *ModInst,
533
                   const RefVariant &Ref, const uint32_t TypeIdx,
534
0
                   const uint32_t Idx, const bool IsSigned) const noexcept {
535
0
  const auto *Inst = Ref.getPtr<Runtime::Instance::ArrayInstance>();
536
0
  if (Inst == nullptr) {
537
0
    return Unexpect(ErrCode::Value::AccessNullArray);
538
0
  }
539
0
  if (Idx >= Inst->getLength()) {
540
0
    return Unexpect(ErrCode::Value::ArrayOutOfBounds);
541
0
  }
542
0
  const auto &VType = getArrayStorageTypeByIdx(ModInst, TypeIdx);
543
0
  return unpackVal(VType, Inst->getData(Idx), IsSigned);
544
0
}
545
546
Expect<void>
547
Executor::arraySet(const Runtime::Instance::ModuleInstance *ModInst,
548
                   const RefVariant &Ref, const ValVariant &Val,
549
0
                   const uint32_t TypeIdx, const uint32_t Idx) const noexcept {
550
0
  auto *Inst = Ref.getPtr<Runtime::Instance::ArrayInstance>();
551
0
  if (Inst == nullptr) {
552
0
    return Unexpect(ErrCode::Value::AccessNullArray);
553
0
  }
554
0
  if (Idx >= Inst->getLength()) {
555
0
    return Unexpect(ErrCode::Value::ArrayOutOfBounds);
556
0
  }
557
0
  const auto &VType = getArrayStorageTypeByIdx(ModInst, TypeIdx);
558
0
  Inst->getData(Idx) = packVal(VType, Val);
559
0
  return {};
560
0
}
561
562
Expect<void>
563
Executor::arrayFill(const Runtime::Instance::ModuleInstance *ModInst,
564
                    const RefVariant &Ref, const ValVariant &Val,
565
                    const uint32_t TypeIdx, const uint32_t Idx,
566
0
                    const uint32_t Cnt) const noexcept {
567
0
  auto *Inst = Ref.getPtr<Runtime::Instance::ArrayInstance>();
568
0
  if (Inst == nullptr) {
569
0
    return Unexpect(ErrCode::Value::AccessNullArray);
570
0
  }
571
0
  if (static_cast<uint64_t>(Idx) + static_cast<uint64_t>(Cnt) >
572
0
      Inst->getLength()) {
573
0
    return Unexpect(ErrCode::Value::ArrayOutOfBounds);
574
0
  }
575
0
  const auto &VType = getArrayStorageTypeByIdx(ModInst, TypeIdx);
576
0
  auto Arr = Inst->getArray();
577
0
  std::fill(Arr.begin() + Idx, Arr.begin() + Idx + Cnt, packVal(VType, Val));
578
0
  return {};
579
0
}
580
581
Expect<void> Executor::arrayInitData(
582
    const Runtime::Instance::ModuleInstance *ModInst, const RefVariant &Ref,
583
    const uint32_t TypeIdx, const uint32_t DataIdx, const uint32_t DstIdx,
584
0
    const uint32_t SrcIdx, const uint32_t Cnt) const noexcept {
585
0
  auto *Inst = Ref.getPtr<Runtime::Instance::ArrayInstance>();
586
0
  if (Inst == nullptr) {
587
0
    return Unexpect(ErrCode::Value::AccessNullArray);
588
0
  }
589
0
  if (static_cast<uint64_t>(DstIdx) + static_cast<uint64_t>(Cnt) >
590
0
      Inst->getLength()) {
591
0
    return Unexpect(ErrCode::Value::ArrayOutOfBounds);
592
0
  }
593
0
  const auto &VType = getArrayStorageTypeByIdx(ModInst, TypeIdx);
594
0
  const uint32_t BSize = VType.getBitWidth() / 8;
595
0
  auto *DataInst = getDataInstByIdx(ModInst, DataIdx);
596
0
  assuming(DataInst);
597
0
  if (static_cast<uint64_t>(SrcIdx) + static_cast<uint64_t>(Cnt) * BSize >
598
0
      DataInst->getData().size()) {
599
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
600
0
  }
601
602
0
  for (uint32_t Idx = 0; Idx < Cnt; Idx++) {
603
    // The value has been packed.
604
0
    Inst->getData(DstIdx + Idx) =
605
0
        DataInst->loadValue(SrcIdx + Idx * BSize, BSize);
606
0
  }
607
0
  return {};
608
0
}
609
610
Expect<void> Executor::arrayInitElem(
611
    const Runtime::Instance::ModuleInstance *ModInst, const RefVariant &Ref,
612
    const uint32_t TypeIdx, const uint32_t ElemIdx, const uint32_t DstIdx,
613
0
    const uint32_t SrcIdx, const uint32_t Cnt) const noexcept {
614
0
  auto *Inst = Ref.getPtr<Runtime::Instance::ArrayInstance>();
615
0
  if (Inst == nullptr) {
616
0
    return Unexpect(ErrCode::Value::AccessNullArray);
617
0
  }
618
0
  if (static_cast<uint64_t>(DstIdx) + static_cast<uint64_t>(Cnt) >
619
0
      Inst->getLength()) {
620
0
    return Unexpect(ErrCode::Value::ArrayOutOfBounds);
621
0
  }
622
0
  const auto &VType = getArrayStorageTypeByIdx(ModInst, TypeIdx);
623
0
  auto *ElemInst = getElemInstByIdx(ModInst, ElemIdx);
624
0
  assuming(ElemInst);
625
0
  auto ElemSrc = ElemInst->getRefs();
626
0
  if (static_cast<uint64_t>(SrcIdx) + static_cast<uint64_t>(Cnt) >
627
0
      ElemSrc.size()) {
628
0
    return Unexpect(ErrCode::Value::TableOutOfBounds);
629
0
  }
630
631
0
  auto Arr = Inst->getArray();
632
  // The value has been packed.
633
0
  std::transform(ElemSrc.begin() + SrcIdx, ElemSrc.begin() + SrcIdx + Cnt,
634
0
                 Arr.begin() + DstIdx,
635
0
                 [&](const RefVariant &V) { return packVal(VType, V); });
636
0
  return {};
637
0
}
638
639
Expect<void>
640
Executor::arrayCopy(const Runtime::Instance::ModuleInstance *ModInst,
641
                    const RefVariant &DstRef, const uint32_t DstTypeIdx,
642
                    const uint32_t DstIdx, const RefVariant &SrcRef,
643
                    const uint32_t SrcTypeIdx, const uint32_t SrcIdx,
644
0
                    const uint32_t Cnt) const noexcept {
645
0
  auto *SrcInst = SrcRef.getPtr<Runtime::Instance::ArrayInstance>();
646
0
  auto *DstInst = DstRef.getPtr<Runtime::Instance::ArrayInstance>();
647
0
  if (SrcInst == nullptr) {
648
0
    return Unexpect(ErrCode::Value::AccessNullArray);
649
0
  }
650
0
  if (DstInst == nullptr) {
651
0
    return Unexpect(ErrCode::Value::AccessNullArray);
652
0
  }
653
0
  if (static_cast<uint64_t>(SrcIdx) + static_cast<uint64_t>(Cnt) >
654
0
      SrcInst->getLength()) {
655
0
    return Unexpect(ErrCode::Value::ArrayOutOfBounds);
656
0
  }
657
0
  if (static_cast<uint64_t>(DstIdx) + static_cast<uint64_t>(Cnt) >
658
0
      DstInst->getLength()) {
659
0
    return Unexpect(ErrCode::Value::ArrayOutOfBounds);
660
0
  }
661
662
0
  auto SrcArr = SrcInst->getArray();
663
0
  auto DstArr = DstInst->getArray();
664
0
  const auto &SrcVType = getArrayStorageTypeByIdx(ModInst, SrcTypeIdx);
665
0
  const auto &DstVType = getArrayStorageTypeByIdx(ModInst, DstTypeIdx);
666
0
  if (DstIdx <= SrcIdx) {
667
0
    std::transform(SrcArr.begin() + SrcIdx, SrcArr.begin() + SrcIdx + Cnt,
668
0
                   DstArr.begin() + DstIdx, [&](const ValVariant &V) {
669
0
                     return packVal(DstVType, unpackVal(SrcVType, V));
670
0
                   });
671
0
  } else {
672
0
    std::transform(std::make_reverse_iterator(SrcArr.begin() + SrcIdx + Cnt),
673
0
                   std::make_reverse_iterator(SrcArr.begin() + SrcIdx),
674
0
                   std::make_reverse_iterator(DstArr.begin() + DstIdx + Cnt),
675
0
                   [&](const ValVariant &V) {
676
0
                     return packVal(DstVType, unpackVal(SrcVType, V));
677
0
                   });
678
0
  }
679
0
  return {};
680
0
}
681
682
} // namespace Executor
683
} // namespace WasmEdge