Coverage Report

Created: 2026-06-30 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/WasmEdge/include/executor/engine/atomic.ipp
Line
Count
Source
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright The WasmEdge Authors
3
4
#include "common/endian.h"
5
#include "common/types.h"
6
#include "executor/executor.h"
7
#include "runtime/instance/memory.h"
8
#include <experimental/scope.hpp>
9
10
#include <cstdint>
11
12
namespace WasmEdge {
13
namespace Executor {
14
15
template <typename T>
16
TypeT<T> Executor::runAtomicWaitOp(Runtime::StackManager &StackMgr,
17
                                   Runtime::Instance::MemoryInstance &MemInst,
18
0
                                   const AST::Instruction &Instr) {
19
0
  ValVariant RawTimeout = StackMgr.pop();
20
0
  ValVariant RawValue = StackMgr.pop();
21
0
  ValVariant &RawAddress = StackMgr.getTop();
22
0
  const auto AddrType = MemInst.getMemoryType().getLimit().getAddrType();
23
0
  uint64_t Address = extractAddr(RawAddress, AddrType);
24
0
  EXPECTED_TRY(checkOffsetOverflow(MemInst, Instr, Address, sizeof(T)));
25
0
  Address += Instr.getMemoryOffset();
26
27
0
  if (Address % sizeof(T) != 0) {
28
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
29
0
    spdlog::error(
30
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
31
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
32
0
  }
33
34
0
  int64_t Timeout = RawTimeout.get<int64_t>();
35
36
0
  return atomicWait<T>(MemInst, Address, RawValue.get<T>(), Timeout)
37
0
      .map_error([&Instr](auto E) {
38
0
        spdlog::error(E);
39
0
        spdlog::error(
40
0
            ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
41
0
        return E;
42
0
      })
Unexecuted instantiation: auto WasmEdge::Executor::Executor::runAtomicWaitOp<int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(auto:1)#1}::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const
Unexecuted instantiation: auto WasmEdge::Executor::Executor::runAtomicWaitOp<long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(auto:1)#1}::operator()<WasmEdge::ErrCode>(WasmEdge::ErrCode) const
43
0
      .map([&](auto V) { RawAddress = emplaceAddr(V, AddrType); });
Unexecuted instantiation: auto WasmEdge::Executor::Executor::runAtomicWaitOp<int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(auto:1)#2}::operator()<unsigned long>(unsigned long) const
Unexecuted instantiation: auto WasmEdge::Executor::Executor::runAtomicWaitOp<long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(auto:1)#2}::operator()<unsigned long>(unsigned long) const
44
0
}
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicWaitOp<int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicWaitOp<long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
45
46
template <typename T, typename I>
47
TypeT<T> Executor::runAtomicLoadOp(Runtime::StackManager &StackMgr,
48
                                   Runtime::Instance::MemoryInstance &MemInst,
49
0
                                   const AST::Instruction &Instr) {
50
0
  ValVariant &RawAddress = StackMgr.getTop();
51
0
  const auto AddrType = MemInst.getMemoryType().getLimit().getAddrType();
52
0
  uint64_t Address = extractAddr(RawAddress, AddrType);
53
0
  EXPECTED_TRY(checkOffsetOverflow(MemInst, Instr, Address, sizeof(T)));
54
0
  Address += Instr.getMemoryOffset();
55
56
0
  if (Address % sizeof(I) != 0) {
57
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
58
0
    spdlog::error(
59
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
60
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
61
0
  }
62
63
  // make sure the address no OOB with size I
64
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
65
0
  if (!AtomicObj) {
66
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
67
0
    spdlog::error(
68
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
69
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
70
0
  }
71
72
0
  EndianValue<I> Return = AtomicObj->load();
73
0
  RawAddress.emplace<T>(static_cast<T>(Return.le()));
74
0
  return {};
75
0
}
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicLoadOp<int, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicLoadOp<long, unsigned long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicLoadOp<unsigned int, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicLoadOp<unsigned int, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicLoadOp<unsigned long, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicLoadOp<unsigned long, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicLoadOp<unsigned long, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
76
77
template <typename T, typename I>
78
TypeT<T> Executor::runAtomicStoreOp(Runtime::StackManager &StackMgr,
79
                                    Runtime::Instance::MemoryInstance &MemInst,
80
0
                                    const AST::Instruction &Instr) {
81
0
  ValVariant RawValue = StackMgr.pop();
82
0
  ValVariant RawAddress = StackMgr.pop();
83
0
  const auto AddrType = MemInst.getMemoryType().getLimit().getAddrType();
84
0
  uint64_t Address = extractAddr(RawAddress, AddrType);
85
0
  EXPECTED_TRY(checkOffsetOverflow(MemInst, Instr, Address, sizeof(T)));
86
0
  Address += Instr.getMemoryOffset();
87
88
0
  if (Address % sizeof(I) != 0) {
89
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
90
0
    spdlog::error(
91
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
92
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
93
0
  }
94
95
  // make sure the address no OOB with size I
96
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
97
0
  if (!AtomicObj) {
98
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
99
0
    spdlog::error(
100
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
101
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
102
0
  }
103
0
  EndianValue<I> Value = static_cast<I>(RawValue.get<T>());
104
105
0
  AtomicObj->store(Value.le());
106
0
  return {};
107
0
}
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicStoreOp<int, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicStoreOp<long, unsigned long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicStoreOp<unsigned int, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicStoreOp<unsigned int, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicStoreOp<unsigned long, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicStoreOp<unsigned long, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicStoreOp<unsigned long, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
108
109
template <typename T, typename AtomicOp, typename BinaryOp>
110
T runAtomicOp(std::atomic<T> *AtomicObj, T Value, AtomicOp Op [[maybe_unused]],
111
0
              BinaryOp BinOp [[maybe_unused]]) {
112
0
  if constexpr (Endian::native == Endian::little) {
113
0
    return Op(AtomicObj, Value);
114
  } else {
115
    EndianValue<T> Return;
116
    EndianValue<T> Result;
117
    do {
118
      Return = AtomicObj->load();
119
      Result = BinOp(Return.le(), Value);
120
    } while (!AtomicObj->compare_exchange_weak(Return.raw(), Result.le()));
121
    return Return.le();
122
  }
123
0
}
Unexecuted instantiation: unsigned int WasmEdge::Executor::runAtomicOp<unsigned int, WasmEdge::Executor::Executor::runAtomicAddOp<int, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned int>*, unsigned int)#1}, std::__1::plus<unsigned int> >(std::__1::atomic<unsigned int>*, unsigned int, WasmEdge::Executor::Executor::runAtomicAddOp<int, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned int>*, unsigned int)#1}, std::__1::plus<unsigned int>)
Unexecuted instantiation: unsigned long WasmEdge::Executor::runAtomicOp<unsigned long, WasmEdge::Executor::Executor::runAtomicAddOp<long, unsigned long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned long>*, unsigned long)#1}, std::__1::plus<unsigned long> >(std::__1::atomic<unsigned long>*, unsigned long, WasmEdge::Executor::Executor::runAtomicAddOp<long, unsigned long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned long>*, unsigned long)#1}, std::__1::plus<unsigned long>)
Unexecuted instantiation: unsigned char WasmEdge::Executor::runAtomicOp<unsigned char, WasmEdge::Executor::Executor::runAtomicAddOp<unsigned int, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned char>*, unsigned char)#1}, std::__1::plus<unsigned char> >(std::__1::atomic<unsigned char>*, unsigned char, WasmEdge::Executor::Executor::runAtomicAddOp<unsigned int, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned char>*, unsigned char)#1}, std::__1::plus<unsigned char>)
Unexecuted instantiation: unsigned short WasmEdge::Executor::runAtomicOp<unsigned short, WasmEdge::Executor::Executor::runAtomicAddOp<unsigned int, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned short>*, unsigned short)#1}, std::__1::plus<unsigned short> >(std::__1::atomic<unsigned short>*, unsigned short, WasmEdge::Executor::Executor::runAtomicAddOp<unsigned int, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned short>*, unsigned short)#1}, std::__1::plus<unsigned short>)
Unexecuted instantiation: unsigned char WasmEdge::Executor::runAtomicOp<unsigned char, WasmEdge::Executor::Executor::runAtomicAddOp<unsigned long, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned char>*, unsigned char)#1}, std::__1::plus<unsigned char> >(std::__1::atomic<unsigned char>*, unsigned char, WasmEdge::Executor::Executor::runAtomicAddOp<unsigned long, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned char>*, unsigned char)#1}, std::__1::plus<unsigned char>)
Unexecuted instantiation: unsigned short WasmEdge::Executor::runAtomicOp<unsigned short, WasmEdge::Executor::Executor::runAtomicAddOp<unsigned long, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned short>*, unsigned short)#1}, std::__1::plus<unsigned short> >(std::__1::atomic<unsigned short>*, unsigned short, WasmEdge::Executor::Executor::runAtomicAddOp<unsigned long, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned short>*, unsigned short)#1}, std::__1::plus<unsigned short>)
Unexecuted instantiation: unsigned int WasmEdge::Executor::runAtomicOp<unsigned int, WasmEdge::Executor::Executor::runAtomicAddOp<unsigned long, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned int>*, unsigned int)#1}, std::__1::plus<unsigned int> >(std::__1::atomic<unsigned int>*, unsigned int, WasmEdge::Executor::Executor::runAtomicAddOp<unsigned long, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned int>*, unsigned int)#1}, std::__1::plus<unsigned int>)
Unexecuted instantiation: unsigned int WasmEdge::Executor::runAtomicOp<unsigned int, WasmEdge::Executor::Executor::runAtomicSubOp<int, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned int>*, unsigned int)#1}, std::__1::minus<unsigned int> >(std::__1::atomic<unsigned int>*, unsigned int, WasmEdge::Executor::Executor::runAtomicSubOp<int, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned int>*, unsigned int)#1}, std::__1::minus<unsigned int>)
Unexecuted instantiation: unsigned long WasmEdge::Executor::runAtomicOp<unsigned long, WasmEdge::Executor::Executor::runAtomicSubOp<long, unsigned long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned long>*, unsigned long)#1}, std::__1::minus<unsigned long> >(std::__1::atomic<unsigned long>*, unsigned long, WasmEdge::Executor::Executor::runAtomicSubOp<long, unsigned long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned long>*, unsigned long)#1}, std::__1::minus<unsigned long>)
Unexecuted instantiation: unsigned char WasmEdge::Executor::runAtomicOp<unsigned char, WasmEdge::Executor::Executor::runAtomicSubOp<unsigned int, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned char>*, unsigned char)#1}, std::__1::minus<unsigned char> >(std::__1::atomic<unsigned char>*, unsigned char, WasmEdge::Executor::Executor::runAtomicSubOp<unsigned int, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned char>*, unsigned char)#1}, std::__1::minus<unsigned char>)
Unexecuted instantiation: unsigned short WasmEdge::Executor::runAtomicOp<unsigned short, WasmEdge::Executor::Executor::runAtomicSubOp<unsigned int, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned short>*, unsigned short)#1}, std::__1::minus<unsigned short> >(std::__1::atomic<unsigned short>*, unsigned short, WasmEdge::Executor::Executor::runAtomicSubOp<unsigned int, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned short>*, unsigned short)#1}, std::__1::minus<unsigned short>)
Unexecuted instantiation: unsigned char WasmEdge::Executor::runAtomicOp<unsigned char, WasmEdge::Executor::Executor::runAtomicSubOp<unsigned long, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned char>*, unsigned char)#1}, std::__1::minus<unsigned char> >(std::__1::atomic<unsigned char>*, unsigned char, WasmEdge::Executor::Executor::runAtomicSubOp<unsigned long, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned char>*, unsigned char)#1}, std::__1::minus<unsigned char>)
Unexecuted instantiation: unsigned short WasmEdge::Executor::runAtomicOp<unsigned short, WasmEdge::Executor::Executor::runAtomicSubOp<unsigned long, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned short>*, unsigned short)#1}, std::__1::minus<unsigned short> >(std::__1::atomic<unsigned short>*, unsigned short, WasmEdge::Executor::Executor::runAtomicSubOp<unsigned long, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned short>*, unsigned short)#1}, std::__1::minus<unsigned short>)
Unexecuted instantiation: unsigned int WasmEdge::Executor::runAtomicOp<unsigned int, WasmEdge::Executor::Executor::runAtomicSubOp<unsigned long, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned int>*, unsigned int)#1}, std::__1::minus<unsigned int> >(std::__1::atomic<unsigned int>*, unsigned int, WasmEdge::Executor::Executor::runAtomicSubOp<unsigned long, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned int>*, unsigned int)#1}, std::__1::minus<unsigned int>)
124
125
template <typename T, typename I>
126
TypeT<T> Executor::runAtomicAddOp(Runtime::StackManager &StackMgr,
127
                                  Runtime::Instance::MemoryInstance &MemInst,
128
0
                                  const AST::Instruction &Instr) {
129
0
  ValVariant RawValue = StackMgr.pop();
130
0
  ValVariant &RawAddress = StackMgr.getTop();
131
0
  const auto AddrType = MemInst.getMemoryType().getLimit().getAddrType();
132
0
  uint64_t Address = extractAddr(RawAddress, AddrType);
133
0
  EXPECTED_TRY(checkOffsetOverflow(MemInst, Instr, Address, sizeof(T)));
134
0
  Address += Instr.getMemoryOffset();
135
136
0
  if (Address % sizeof(I) != 0) {
137
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
138
0
    spdlog::error(
139
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
140
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
141
0
  }
142
143
  // make sure the address no OOB with size I
144
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
145
0
  if (!AtomicObj) {
146
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
147
0
    spdlog::error(
148
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
149
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
150
0
  }
151
0
  I Value = static_cast<I>(RawValue.get<T>());
152
153
0
  I Return = runAtomicOp(
154
0
      AtomicObj, Value,
155
0
      [](std::atomic<I> *Obj, I Val) { return Obj->fetch_add(Val); },
Unexecuted instantiation: WasmEdge::Executor::Executor::runAtomicAddOp<int, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned int>*, unsigned int)#1}::operator()(std::__1::atomic<unsigned int>*, unsigned int) const
Unexecuted instantiation: WasmEdge::Executor::Executor::runAtomicAddOp<long, unsigned long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned long>*, unsigned long)#1}::operator()(std::__1::atomic<unsigned long>*, unsigned long) const
Unexecuted instantiation: WasmEdge::Executor::Executor::runAtomicAddOp<unsigned int, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned char>*, unsigned char)#1}::operator()(std::__1::atomic<unsigned char>*, unsigned char) const
Unexecuted instantiation: WasmEdge::Executor::Executor::runAtomicAddOp<unsigned int, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned short>*, unsigned short)#1}::operator()(std::__1::atomic<unsigned short>*, unsigned short) const
Unexecuted instantiation: WasmEdge::Executor::Executor::runAtomicAddOp<unsigned long, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned char>*, unsigned char)#1}::operator()(std::__1::atomic<unsigned char>*, unsigned char) const
Unexecuted instantiation: WasmEdge::Executor::Executor::runAtomicAddOp<unsigned long, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned short>*, unsigned short)#1}::operator()(std::__1::atomic<unsigned short>*, unsigned short) const
Unexecuted instantiation: WasmEdge::Executor::Executor::runAtomicAddOp<unsigned long, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned int>*, unsigned int)#1}::operator()(std::__1::atomic<unsigned int>*, unsigned int) const
156
0
      std::plus<I>{});
157
0
  RawAddress.emplace<T>(static_cast<T>(Return));
158
0
  return {};
159
0
}
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicAddOp<int, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicAddOp<long, unsigned long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicAddOp<unsigned int, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicAddOp<unsigned int, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicAddOp<unsigned long, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicAddOp<unsigned long, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicAddOp<unsigned long, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
160
161
template <typename T, typename I>
162
TypeT<T> Executor::runAtomicSubOp(Runtime::StackManager &StackMgr,
163
                                  Runtime::Instance::MemoryInstance &MemInst,
164
0
                                  const AST::Instruction &Instr) {
165
0
  ValVariant RawValue = StackMgr.pop();
166
0
  ValVariant &RawAddress = StackMgr.getTop();
167
0
  const auto AddrType = MemInst.getMemoryType().getLimit().getAddrType();
168
0
  uint64_t Address = extractAddr(RawAddress, AddrType);
169
0
  EXPECTED_TRY(checkOffsetOverflow(MemInst, Instr, Address, sizeof(T)));
170
0
  Address += Instr.getMemoryOffset();
171
172
0
  if (Address % sizeof(I) != 0) {
173
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
174
0
    spdlog::error(
175
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
176
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
177
0
  }
178
179
  // make sure the address no OOB with size I
180
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
181
0
  if (!AtomicObj) {
182
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
183
0
    spdlog::error(
184
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
185
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
186
0
  }
187
0
  I Value = static_cast<I>(RawValue.get<T>());
188
189
0
  I Return = runAtomicOp(
190
0
      AtomicObj, Value,
191
0
      [](std::atomic<I> *Obj, I Val) { return Obj->fetch_sub(Val); },
Unexecuted instantiation: WasmEdge::Executor::Executor::runAtomicSubOp<int, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned int>*, unsigned int)#1}::operator()(std::__1::atomic<unsigned int>*, unsigned int) const
Unexecuted instantiation: WasmEdge::Executor::Executor::runAtomicSubOp<long, unsigned long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned long>*, unsigned long)#1}::operator()(std::__1::atomic<unsigned long>*, unsigned long) const
Unexecuted instantiation: WasmEdge::Executor::Executor::runAtomicSubOp<unsigned int, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned char>*, unsigned char)#1}::operator()(std::__1::atomic<unsigned char>*, unsigned char) const
Unexecuted instantiation: WasmEdge::Executor::Executor::runAtomicSubOp<unsigned int, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned short>*, unsigned short)#1}::operator()(std::__1::atomic<unsigned short>*, unsigned short) const
Unexecuted instantiation: WasmEdge::Executor::Executor::runAtomicSubOp<unsigned long, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned char>*, unsigned char)#1}::operator()(std::__1::atomic<unsigned char>*, unsigned char) const
Unexecuted instantiation: WasmEdge::Executor::Executor::runAtomicSubOp<unsigned long, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned short>*, unsigned short)#1}::operator()(std::__1::atomic<unsigned short>*, unsigned short) const
Unexecuted instantiation: WasmEdge::Executor::Executor::runAtomicSubOp<unsigned long, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)::{lambda(std::__1::atomic<unsigned int>*, unsigned int)#1}::operator()(std::__1::atomic<unsigned int>*, unsigned int) const
192
0
      std::minus<I>{});
193
0
  RawAddress.emplace<T>(static_cast<T>(Return));
194
0
  return {};
195
0
}
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicSubOp<int, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicSubOp<long, unsigned long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicSubOp<unsigned int, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicSubOp<unsigned int, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicSubOp<unsigned long, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicSubOp<unsigned long, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicSubOp<unsigned long, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
196
197
template <typename T, typename I>
198
TypeT<T> Executor::runAtomicOrOp(Runtime::StackManager &StackMgr,
199
                                 Runtime::Instance::MemoryInstance &MemInst,
200
0
                                 const AST::Instruction &Instr) {
201
0
  ValVariant RawValue = StackMgr.pop();
202
0
  ValVariant &RawAddress = StackMgr.getTop();
203
0
  const auto AddrType = MemInst.getMemoryType().getLimit().getAddrType();
204
0
  uint64_t Address = extractAddr(RawAddress, AddrType);
205
0
  EXPECTED_TRY(checkOffsetOverflow(MemInst, Instr, Address, sizeof(T)));
206
0
  Address += Instr.getMemoryOffset();
207
208
0
  if (Address % sizeof(I) != 0) {
209
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
210
0
    spdlog::error(
211
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
212
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
213
0
  }
214
215
  // make sure the address no OOB with size I
216
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
217
0
  if (!AtomicObj) {
218
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
219
0
    spdlog::error(
220
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
221
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
222
0
  }
223
0
  EndianValue<I> Value = static_cast<I>(RawValue.get<T>());
224
225
0
  EndianValue<I> Return = AtomicObj->fetch_or(Value.le());
226
0
  RawAddress.emplace<T>(static_cast<T>(Return.le()));
227
0
  return {};
228
0
}
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicOrOp<int, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicOrOp<long, unsigned long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicOrOp<unsigned int, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicOrOp<unsigned int, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicOrOp<unsigned long, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicOrOp<unsigned long, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicOrOp<unsigned long, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
229
230
template <typename T, typename I>
231
TypeT<T> Executor::runAtomicAndOp(Runtime::StackManager &StackMgr,
232
                                  Runtime::Instance::MemoryInstance &MemInst,
233
0
                                  const AST::Instruction &Instr) {
234
0
  ValVariant RawValue = StackMgr.pop();
235
0
  ValVariant &RawAddress = StackMgr.getTop();
236
0
  const auto AddrType = MemInst.getMemoryType().getLimit().getAddrType();
237
0
  uint64_t Address = extractAddr(RawAddress, AddrType);
238
0
  EXPECTED_TRY(checkOffsetOverflow(MemInst, Instr, Address, sizeof(T)));
239
0
  Address += Instr.getMemoryOffset();
240
241
0
  if (Address % sizeof(I) != 0) {
242
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
243
0
    spdlog::error(
244
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
245
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
246
0
  }
247
248
  // make sure the address no OOB with size I
249
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
250
0
  if (!AtomicObj) {
251
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
252
0
    spdlog::error(
253
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
254
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
255
0
  }
256
0
  EndianValue<I> Value = static_cast<I>(RawValue.get<T>());
257
258
0
  EndianValue<I> Return = AtomicObj->fetch_and(Value.le());
259
0
  RawAddress.emplace<T>(static_cast<T>(Return.le()));
260
0
  return {};
261
0
}
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicAndOp<int, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicAndOp<long, unsigned long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicAndOp<unsigned int, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicAndOp<unsigned int, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicAndOp<unsigned long, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicAndOp<unsigned long, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicAndOp<unsigned long, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
262
263
template <typename T, typename I>
264
TypeT<T> Executor::runAtomicXorOp(Runtime::StackManager &StackMgr,
265
                                  Runtime::Instance::MemoryInstance &MemInst,
266
0
                                  const AST::Instruction &Instr) {
267
0
  ValVariant RawValue = StackMgr.pop();
268
0
  ValVariant &RawAddress = StackMgr.getTop();
269
0
  const auto AddrType = MemInst.getMemoryType().getLimit().getAddrType();
270
0
  uint64_t Address = extractAddr(RawAddress, AddrType);
271
0
  EXPECTED_TRY(checkOffsetOverflow(MemInst, Instr, Address, sizeof(T)));
272
0
  Address += Instr.getMemoryOffset();
273
274
0
  if (Address % sizeof(I) != 0) {
275
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
276
0
    spdlog::error(
277
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
278
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
279
0
  }
280
281
  // make sure the address no OOB with size I
282
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
283
0
  if (!AtomicObj) {
284
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
285
0
    spdlog::error(
286
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
287
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
288
0
  }
289
0
  EndianValue<I> Value = static_cast<I>(RawValue.get<T>());
290
291
0
  EndianValue<I> Return = AtomicObj->fetch_xor(Value.le());
292
0
  RawAddress.emplace<T>(static_cast<T>(Return.le()));
293
0
  return {};
294
0
}
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicXorOp<int, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicXorOp<long, unsigned long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicXorOp<unsigned int, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicXorOp<unsigned int, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicXorOp<unsigned long, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicXorOp<unsigned long, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicXorOp<unsigned long, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
295
296
template <typename T, typename I>
297
TypeT<T>
298
Executor::runAtomicExchangeOp(Runtime::StackManager &StackMgr,
299
                              Runtime::Instance::MemoryInstance &MemInst,
300
0
                              const AST::Instruction &Instr) {
301
0
  ValVariant RawValue = StackMgr.pop();
302
0
  ValVariant &RawAddress = StackMgr.getTop();
303
0
  const auto AddrType = MemInst.getMemoryType().getLimit().getAddrType();
304
0
  uint64_t Address = extractAddr(RawAddress, AddrType);
305
0
  EXPECTED_TRY(checkOffsetOverflow(MemInst, Instr, Address, sizeof(T)));
306
0
  Address += Instr.getMemoryOffset();
307
308
0
  if (Address % sizeof(I) != 0) {
309
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
310
0
    spdlog::error(
311
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
312
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
313
0
  }
314
315
  // make sure the address no OOB with size I
316
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
317
0
  if (!AtomicObj) {
318
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
319
0
    spdlog::error(
320
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
321
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
322
0
  }
323
0
  EndianValue<I> Value = static_cast<I>(RawValue.get<T>());
324
325
0
  EndianValue<I> Return = AtomicObj->exchange(Value.le());
326
0
  RawAddress.emplace<T>(static_cast<T>(Return.le()));
327
0
  return {};
328
0
}
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicExchangeOp<int, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicExchangeOp<long, unsigned long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicExchangeOp<unsigned int, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicExchangeOp<unsigned int, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicExchangeOp<unsigned long, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicExchangeOp<unsigned long, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicExchangeOp<unsigned long, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
329
330
template <typename T, typename I>
331
TypeT<T>
332
Executor::runAtomicCompareExchangeOp(Runtime::StackManager &StackMgr,
333
                                     Runtime::Instance::MemoryInstance &MemInst,
334
0
                                     const AST::Instruction &Instr) {
335
0
  ValVariant RawReplacement = StackMgr.pop();
336
0
  ValVariant RawExpected = StackMgr.pop();
337
0
  ValVariant &RawAddress = StackMgr.getTop();
338
0
  const auto AddrType = MemInst.getMemoryType().getLimit().getAddrType();
339
0
  uint64_t Address = extractAddr(RawAddress, AddrType);
340
0
  EXPECTED_TRY(checkOffsetOverflow(MemInst, Instr, Address, sizeof(T)));
341
0
  Address += Instr.getMemoryOffset();
342
343
0
  if (Address % sizeof(I) != 0) {
344
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
345
0
    spdlog::error(
346
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
347
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
348
0
  }
349
350
  // make sure the address no OOB with size I
351
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
352
0
  if (!AtomicObj) {
353
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
354
0
    spdlog::error(
355
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
356
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
357
0
  }
358
0
  EndianValue<I> Replacement = static_cast<I>(RawReplacement.get<T>());
359
0
  I Expected = EndianValue<I>(static_cast<I>(RawExpected.get<T>())).le();
360
361
0
  AtomicObj->compare_exchange_strong(Expected, Replacement.le());
362
0
  RawAddress.emplace<T>(static_cast<T>(Expected));
363
0
  return {};
364
0
}
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicCompareExchangeOp<int, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicCompareExchangeOp<long, unsigned long>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicCompareExchangeOp<unsigned int, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned int>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicCompareExchangeOp<unsigned int, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicCompareExchangeOp<unsigned long, unsigned char>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicCompareExchangeOp<unsigned long, unsigned short>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
Unexecuted instantiation: std::__1::enable_if<IsWasmNumV<unsigned long>, cxx20::expected<void, WasmEdge::ErrCode> >::type WasmEdge::Executor::Executor::runAtomicCompareExchangeOp<unsigned long, unsigned int>(WasmEdge::Runtime::StackManager&, WasmEdge::Runtime::Instance::MemoryInstance&, WasmEdge::AST::Instruction const&)
365
366
template <typename T>
367
Expect<uint64_t>
368
Executor::atomicWait(Runtime::Instance::MemoryInstance &MemInst,
369
                     uint64_t Address, EndianValue<T> Expected,
370
0
                     int64_t Timeout) noexcept {
371
  // The error message should be handled by the caller, or the AOT mode will
372
  // produce the duplicated messages.
373
0
  if (!MemInst.isShared()) {
374
0
    return Unexpect(ErrCode::Value::ExpectSharedMemory);
375
0
  }
376
377
0
  if (auto *AtomicObj = MemInst.getPointer<std::atomic<T> *>(Address);
378
0
      !AtomicObj) {
379
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
380
0
  }
381
382
0
  std::optional<std::chrono::time_point<std::chrono::steady_clock>> Until;
383
0
  if (Timeout >= 0) {
384
0
    Until.emplace(std::chrono::steady_clock::now() +
385
0
                  std::chrono::nanoseconds(Timeout));
386
0
  }
387
388
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<T> *>(Address);
389
0
  assuming(AtomicObj);
390
391
0
  if (AtomicObj->load() != Expected.le()) {
392
0
    return static_cast<uint64_t>(1); // NotEqual
393
0
  }
394
395
0
  auto &WaiterMapMtx = MemInst.getWaiterMapMutex();
396
0
  auto &WaiterMap = MemInst.getWaiterMap();
397
398
0
  std::remove_reference_t<decltype(WaiterMap)>::iterator WaiterIterator;
399
0
  {
400
0
    std::unique_lock<std::mutex> Locker(WaiterMapMtx);
401
0
    WaiterIterator = WaiterMap.emplace(std::piecewise_construct,
402
0
                                       std::forward_as_tuple(Address),
403
0
                                       std::forward_as_tuple());
404
0
  }
405
406
0
  WaitingMemory.store(&MemInst, std::memory_order_release);
407
0
  cxx20::scope_exit ScopeExitHolder([&]() noexcept {
408
0
    WaitingMemory.store(nullptr, std::memory_order_release);
409
0
    std::unique_lock<std::mutex> Locker(WaiterMapMtx);
410
0
    WaiterMap.erase(WaiterIterator);
411
0
  });
Unexecuted instantiation: WasmEdge::Executor::Executor::atomicWait<unsigned long>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned long, WasmEdge::EndianValue<unsigned long>, long)::{lambda()#1}::operator()() const
Unexecuted instantiation: WasmEdge::Executor::Executor::atomicWait<unsigned int>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned long, WasmEdge::EndianValue<unsigned int>, long)::{lambda()#1}::operator()() const
Unexecuted instantiation: WasmEdge::Executor::Executor::atomicWait<int>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned long, WasmEdge::EndianValue<int>, long)::{lambda()#1}::operator()() const
Unexecuted instantiation: WasmEdge::Executor::Executor::atomicWait<long>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned long, WasmEdge::EndianValue<long>, long)::{lambda()#1}::operator()() const
412
413
0
  while (true) {
414
0
    std::unique_lock<decltype(WaiterIterator->second.Mutex)> Locker(
415
0
        WaiterIterator->second.Mutex);
416
    // Check StopToken while holding the Waiter mutex, before entering wait.
417
    // This pairs with notifyAllWaiters() which acquires+releases this mutex
418
    // before calling notify_all(), ensuring we either see StopToken here or
419
    // get woken by the subsequent notify_all().
420
0
    if (unlikely(StopToken.load(std::memory_order_acquire) != 0)) {
421
0
      return Unexpect(ErrCode::Value::Interrupted);
422
0
    }
423
0
    std::cv_status WaitResult = std::cv_status::no_timeout;
424
0
    if (!Until) {
425
0
      WaiterIterator->second.Cond.wait(Locker);
426
0
    } else {
427
0
      WaitResult = WaiterIterator->second.Cond.wait_until(Locker, *Until);
428
0
    }
429
0
    if (unlikely(StopToken.load(std::memory_order_relaxed) != 0)) {
430
0
      return Unexpect(ErrCode::Value::Interrupted);
431
0
    }
432
0
    if (WaiterIterator->second.Notified) {
433
      // Woken by memory.atomic.notify — return "ok" per the spec,
434
      // regardless of the current memory value.
435
0
      return static_cast<uint64_t>(0); // ok
436
0
    }
437
0
    if (WaitResult == std::cv_status::timeout) {
438
0
      return static_cast<uint64_t>(2); // Timed-out
439
0
    }
440
0
  }
441
0
}
Unexecuted instantiation: cxx20::expected<unsigned long, WasmEdge::ErrCode> WasmEdge::Executor::Executor::atomicWait<unsigned long>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned long, WasmEdge::EndianValue<unsigned long>, long)
Unexecuted instantiation: cxx20::expected<unsigned long, WasmEdge::ErrCode> WasmEdge::Executor::Executor::atomicWait<unsigned int>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned long, WasmEdge::EndianValue<unsigned int>, long)
Unexecuted instantiation: cxx20::expected<unsigned long, WasmEdge::ErrCode> WasmEdge::Executor::Executor::atomicWait<int>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned long, WasmEdge::EndianValue<int>, long)
Unexecuted instantiation: cxx20::expected<unsigned long, WasmEdge::ErrCode> WasmEdge::Executor::Executor::atomicWait<long>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned long, WasmEdge::EndianValue<long>, long)
442
443
} // namespace Executor
444
} // namespace WasmEdge