Coverage Report

Created: 2025-08-29 06:29

/src/WasmEdge/include/executor/engine/atomic.ipp
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: 2019-2024 Second State INC
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
23
0
  uint32_t Address = RawAddress.get<uint32_t>();
24
0
  if (Address >
25
0
      std::numeric_limits<uint32_t>::max() - Instr.getMemoryOffset()) {
26
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
27
0
    spdlog::error(ErrInfo::InfoBoundary(
28
0
        Address + static_cast<uint64_t>(Instr.getMemoryOffset()), sizeof(T),
29
0
        MemInst.getBoundIdx()));
30
0
    spdlog::error(
31
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
32
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
33
0
  }
34
0
  Address += Instr.getMemoryOffset();
35
36
0
  if (Address % sizeof(T) != 0) {
37
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
38
0
    spdlog::error(
39
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
40
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
41
0
  }
42
43
0
  int64_t Timeout = RawTimeout.get<int64_t>();
44
45
0
  return atomicWait<T>(MemInst, Address, RawValue.get<T>(), Timeout)
46
0
      .map_error([&Instr](auto E) {
47
0
        spdlog::error(E);
48
0
        spdlog::error(
49
0
            ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
50
0
        return E;
51
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
52
0
      .map([&](auto V) { RawAddress.emplace<uint32_t>(V); });
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 int>(unsigned int) 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 int>(unsigned int) const
53
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&)
54
55
template <typename T, typename I>
56
TypeT<T> Executor::runAtomicLoadOp(Runtime::StackManager &StackMgr,
57
                                   Runtime::Instance::MemoryInstance &MemInst,
58
0
                                   const AST::Instruction &Instr) {
59
0
  ValVariant &RawAddress = StackMgr.getTop();
60
0
  uint32_t Address = RawAddress.get<uint32_t>();
61
62
0
  if (Address >
63
0
      std::numeric_limits<uint32_t>::max() - Instr.getMemoryOffset()) {
64
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
65
0
    spdlog::error(ErrInfo::InfoBoundary(
66
0
        Address + static_cast<uint64_t>(Instr.getMemoryOffset()), sizeof(I),
67
0
        MemInst.getBoundIdx()));
68
0
    spdlog::error(
69
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
70
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
71
0
  }
72
0
  Address += Instr.getMemoryOffset();
73
74
0
  if (Address % sizeof(I) != 0) {
75
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
76
0
    spdlog::error(
77
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
78
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
79
0
  }
80
81
  // make sure the address no OOB with size I
82
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
83
0
  if (!AtomicObj) {
84
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
85
0
    spdlog::error(
86
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
87
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
88
0
  }
89
90
0
  EndianValue<I> Return = AtomicObj->load();
91
0
  RawAddress.emplace<T>(static_cast<T>(Return.le()));
92
0
  return {};
93
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&)
94
95
template <typename T, typename I>
96
TypeT<T> Executor::runAtomicStoreOp(Runtime::StackManager &StackMgr,
97
                                    Runtime::Instance::MemoryInstance &MemInst,
98
0
                                    const AST::Instruction &Instr) {
99
0
  ValVariant RawValue = StackMgr.pop();
100
0
  ValVariant RawAddress = StackMgr.pop();
101
0
  uint32_t Address = RawAddress.get<uint32_t>();
102
103
0
  if (Address >
104
0
      std::numeric_limits<uint32_t>::max() - Instr.getMemoryOffset()) {
105
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
106
0
    spdlog::error(ErrInfo::InfoBoundary(
107
0
        Address + static_cast<uint64_t>(Instr.getMemoryOffset()), sizeof(I),
108
0
        MemInst.getBoundIdx()));
109
0
    spdlog::error(
110
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
111
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
112
0
  }
113
0
  Address += Instr.getMemoryOffset();
114
115
0
  if (Address % sizeof(I) != 0) {
116
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
117
0
    spdlog::error(
118
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
119
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
120
0
  }
121
122
  // make sure the address no OOB with size I
123
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
124
0
  if (!AtomicObj) {
125
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
126
0
    spdlog::error(
127
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
128
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
129
0
  }
130
0
  EndianValue<I> Value = static_cast<I>(RawValue.get<T>());
131
132
0
  AtomicObj->store(Value.le());
133
0
  return {};
134
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&)
135
136
template <typename T, typename AtomicOp, typename BinaryOp>
137
T runAtomicOp(std::atomic<T> *AtomicObj, T Value, AtomicOp Op [[maybe_unused]],
138
0
              BinaryOp BinOp [[maybe_unused]]) {
139
0
  if constexpr (Endian::native == Endian::little) {
140
0
    return Op(AtomicObj, Value);
141
  } else {
142
    EndianValue<T> Return;
143
    EndianValue<T> Result;
144
    do {
145
      Return = AtomicObj->load();
146
      Result = BinOp(Return.le(), Value);
147
    } while (!AtomicObj->compare_exchange_weak(Return.raw(), Result.le()));
148
    return Return.le();
149
  }
150
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>)
151
152
template <typename T, typename I>
153
TypeT<T> Executor::runAtomicAddOp(Runtime::StackManager &StackMgr,
154
                                  Runtime::Instance::MemoryInstance &MemInst,
155
0
                                  const AST::Instruction &Instr) {
156
0
  ValVariant RawValue = StackMgr.pop();
157
0
  ValVariant &RawAddress = StackMgr.getTop();
158
0
  uint32_t Address = RawAddress.get<uint32_t>();
159
160
0
  if (Address >
161
0
      std::numeric_limits<uint32_t>::max() - Instr.getMemoryOffset()) {
162
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
163
0
    spdlog::error(ErrInfo::InfoBoundary(
164
0
        Address + static_cast<uint64_t>(Instr.getMemoryOffset()), sizeof(I),
165
0
        MemInst.getBoundIdx()));
166
0
    spdlog::error(
167
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
168
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
169
0
  }
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_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
192
0
      std::plus<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::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&)
196
197
template <typename T, typename I>
198
TypeT<T> Executor::runAtomicSubOp(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
  uint32_t Address = RawAddress.get<uint32_t>();
204
205
0
  if (Address >
206
0
      std::numeric_limits<uint32_t>::max() - Instr.getMemoryOffset()) {
207
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
208
0
    spdlog::error(ErrInfo::InfoBoundary(
209
0
        Address + static_cast<uint64_t>(Instr.getMemoryOffset()), sizeof(I),
210
0
        MemInst.getBoundIdx()));
211
0
    spdlog::error(
212
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
213
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
214
0
  }
215
0
  Address += Instr.getMemoryOffset();
216
217
0
  if (Address % sizeof(I) != 0) {
218
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
219
0
    spdlog::error(
220
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
221
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
222
0
  }
223
224
  // make sure the address no OOB with size I
225
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
226
0
  if (!AtomicObj) {
227
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
228
0
    spdlog::error(
229
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
230
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
231
0
  }
232
0
  I Value = static_cast<I>(RawValue.get<T>());
233
234
0
  I Return = runAtomicOp(
235
0
      AtomicObj, Value,
236
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
237
0
      std::minus<I>{});
238
0
  RawAddress.emplace<T>(static_cast<T>(Return));
239
0
  return {};
240
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&)
241
242
template <typename T, typename I>
243
TypeT<T> Executor::runAtomicOrOp(Runtime::StackManager &StackMgr,
244
                                 Runtime::Instance::MemoryInstance &MemInst,
245
0
                                 const AST::Instruction &Instr) {
246
0
  ValVariant RawValue = StackMgr.pop();
247
0
  ValVariant &RawAddress = StackMgr.getTop();
248
0
  uint32_t Address = RawAddress.get<uint32_t>();
249
250
0
  if (Address >
251
0
      std::numeric_limits<uint32_t>::max() - Instr.getMemoryOffset()) {
252
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
253
0
    spdlog::error(ErrInfo::InfoBoundary(
254
0
        Address + static_cast<uint64_t>(Instr.getMemoryOffset()), sizeof(I),
255
0
        MemInst.getBoundIdx()));
256
0
    spdlog::error(
257
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
258
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
259
0
  }
260
0
  Address += Instr.getMemoryOffset();
261
262
0
  if (Address % sizeof(I) != 0) {
263
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
264
0
    spdlog::error(
265
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
266
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
267
0
  }
268
269
  // make sure the address no OOB with size I
270
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
271
0
  if (!AtomicObj) {
272
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
273
0
    spdlog::error(
274
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
275
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
276
0
  }
277
0
  EndianValue<I> Value = static_cast<I>(RawValue.get<T>());
278
279
0
  EndianValue<I> Return = AtomicObj->fetch_or(Value.le());
280
0
  RawAddress.emplace<T>(static_cast<T>(Return.le()));
281
0
  return {};
282
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&)
283
284
template <typename T, typename I>
285
TypeT<T> Executor::runAtomicAndOp(Runtime::StackManager &StackMgr,
286
                                  Runtime::Instance::MemoryInstance &MemInst,
287
0
                                  const AST::Instruction &Instr) {
288
0
  ValVariant RawValue = StackMgr.pop();
289
0
  ValVariant &RawAddress = StackMgr.getTop();
290
0
  uint32_t Address = RawAddress.get<uint32_t>();
291
292
0
  if (Address >
293
0
      std::numeric_limits<uint32_t>::max() - Instr.getMemoryOffset()) {
294
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
295
0
    spdlog::error(ErrInfo::InfoBoundary(
296
0
        Address + static_cast<uint64_t>(Instr.getMemoryOffset()), sizeof(I),
297
0
        MemInst.getBoundIdx()));
298
0
    spdlog::error(
299
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
300
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
301
0
  }
302
0
  Address += Instr.getMemoryOffset();
303
304
0
  if (Address % sizeof(I) != 0) {
305
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
306
0
    spdlog::error(
307
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
308
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
309
0
  }
310
311
  // make sure the address no OOB with size I
312
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
313
0
  if (!AtomicObj) {
314
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
315
0
    spdlog::error(
316
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
317
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
318
0
  }
319
0
  EndianValue<I> Value = static_cast<I>(RawValue.get<T>());
320
321
0
  EndianValue<I> Return = AtomicObj->fetch_and(Value.le());
322
0
  RawAddress.emplace<T>(static_cast<T>(Return.le()));
323
0
  return {};
324
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&)
325
326
template <typename T, typename I>
327
TypeT<T> Executor::runAtomicXorOp(Runtime::StackManager &StackMgr,
328
                                  Runtime::Instance::MemoryInstance &MemInst,
329
0
                                  const AST::Instruction &Instr) {
330
0
  ValVariant RawValue = StackMgr.pop();
331
0
  ValVariant &RawAddress = StackMgr.getTop();
332
0
  uint32_t Address = RawAddress.get<uint32_t>();
333
334
0
  if (Address >
335
0
      std::numeric_limits<uint32_t>::max() - Instr.getMemoryOffset()) {
336
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
337
0
    spdlog::error(ErrInfo::InfoBoundary(
338
0
        Address + static_cast<uint64_t>(Instr.getMemoryOffset()), sizeof(I),
339
0
        MemInst.getBoundIdx()));
340
0
    spdlog::error(
341
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
342
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
343
0
  }
344
0
  Address += Instr.getMemoryOffset();
345
346
0
  if (Address % sizeof(I) != 0) {
347
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
348
0
    spdlog::error(
349
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
350
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
351
0
  }
352
353
  // make sure the address no OOB with size I
354
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
355
0
  if (!AtomicObj) {
356
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
357
0
    spdlog::error(
358
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
359
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
360
0
  }
361
0
  EndianValue<I> Value = static_cast<I>(RawValue.get<T>());
362
363
0
  EndianValue<I> Return = AtomicObj->fetch_xor(Value.le());
364
0
  RawAddress.emplace<T>(static_cast<T>(Return.le()));
365
0
  return {};
366
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&)
367
368
template <typename T, typename I>
369
TypeT<T>
370
Executor::runAtomicExchangeOp(Runtime::StackManager &StackMgr,
371
                              Runtime::Instance::MemoryInstance &MemInst,
372
0
                              const AST::Instruction &Instr) {
373
0
  ValVariant RawValue = StackMgr.pop();
374
0
  ValVariant &RawAddress = StackMgr.getTop();
375
0
  uint32_t Address = RawAddress.get<uint32_t>();
376
377
0
  if (Address >
378
0
      std::numeric_limits<uint32_t>::max() - Instr.getMemoryOffset()) {
379
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
380
0
    spdlog::error(ErrInfo::InfoBoundary(
381
0
        Address + static_cast<uint64_t>(Instr.getMemoryOffset()), sizeof(I),
382
0
        MemInst.getBoundIdx()));
383
0
    spdlog::error(
384
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
385
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
386
0
  }
387
0
  Address += Instr.getMemoryOffset();
388
389
0
  if (Address % sizeof(I) != 0) {
390
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
391
0
    spdlog::error(
392
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
393
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
394
0
  }
395
396
  // make sure the address no OOB with size I
397
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
398
0
  if (!AtomicObj) {
399
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
400
0
    spdlog::error(
401
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
402
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
403
0
  }
404
0
  EndianValue<I> Value = static_cast<I>(RawValue.get<T>());
405
406
0
  EndianValue<I> Return = AtomicObj->exchange(Value.le());
407
0
  RawAddress.emplace<T>(static_cast<T>(Return.le()));
408
0
  return {};
409
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&)
410
411
template <typename T, typename I>
412
TypeT<T>
413
Executor::runAtomicCompareExchangeOp(Runtime::StackManager &StackMgr,
414
                                     Runtime::Instance::MemoryInstance &MemInst,
415
0
                                     const AST::Instruction &Instr) {
416
0
  ValVariant RawReplacement = StackMgr.pop();
417
0
  ValVariant RawExpected = StackMgr.pop();
418
0
  ValVariant &RawAddress = StackMgr.getTop();
419
0
  uint32_t Address = RawAddress.get<uint32_t>();
420
421
0
  if (Address >
422
0
      std::numeric_limits<uint32_t>::max() - Instr.getMemoryOffset()) {
423
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
424
0
    spdlog::error(ErrInfo::InfoBoundary(
425
0
        Address + static_cast<uint64_t>(Instr.getMemoryOffset()), sizeof(I),
426
0
        MemInst.getBoundIdx()));
427
0
    spdlog::error(
428
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
429
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
430
0
  }
431
0
  Address += Instr.getMemoryOffset();
432
433
0
  if (Address % sizeof(I) != 0) {
434
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
435
0
    spdlog::error(
436
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
437
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
438
0
  }
439
440
  // make sure the address no OOB with size I
441
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<I> *>(Address);
442
0
  if (!AtomicObj) {
443
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
444
0
    spdlog::error(
445
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
446
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
447
0
  }
448
0
  EndianValue<I> Replacement = static_cast<I>(RawReplacement.get<T>());
449
0
  I Expected = EndianValue<I>(static_cast<I>(RawExpected.get<T>())).le();
450
451
0
  AtomicObj->compare_exchange_strong(Expected, Replacement.le());
452
0
  RawAddress.emplace<T>(static_cast<T>(Expected));
453
0
  return {};
454
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&)
455
456
template <typename T>
457
Expect<uint32_t>
458
Executor::atomicWait(Runtime::Instance::MemoryInstance &MemInst,
459
                     uint32_t Address, EndianValue<T> Expected,
460
0
                     int64_t Timeout) noexcept {
461
  // The error message should be handled by the caller, or the AOT mode will
462
  // produce the duplicated messages.
463
0
  if (!MemInst.isShared()) {
464
0
    return Unexpect(ErrCode::Value::ExpectSharedMemory);
465
0
  }
466
467
0
  if (auto *AtomicObj = MemInst.getPointer<std::atomic<T> *>(Address);
468
0
      !AtomicObj) {
469
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
470
0
  }
471
472
0
  std::optional<std::chrono::time_point<std::chrono::steady_clock>> Until;
473
0
  if (Timeout >= 0) {
474
0
    Until.emplace(std::chrono::steady_clock::now() +
475
0
                  std::chrono::nanoseconds(Timeout));
476
0
  }
477
478
0
  auto *AtomicObj = MemInst.getPointer<std::atomic<T> *>(Address);
479
0
  assuming(AtomicObj);
480
481
0
  if (AtomicObj->load() != Expected.le()) {
482
0
    return UINT32_C(1); // NotEqual
483
0
  }
484
485
0
  decltype(WaiterMap)::iterator WaiterIterator;
486
0
  {
487
0
    std::unique_lock<decltype(WaiterMapMutex)> Locker(WaiterMapMutex);
488
0
    WaiterIterator = WaiterMap.emplace(Address, &MemInst);
489
0
  }
490
491
0
  cxx20::scope_exit ScopeExitHolder([&]() noexcept {
492
0
    std::unique_lock<decltype(WaiterMapMutex)> Locker(WaiterMapMutex);
493
0
    WaiterMap.erase(WaiterIterator);
494
0
  });
Unexecuted instantiation: WasmEdge::Executor::Executor::atomicWait<unsigned long>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned int, WasmEdge::EndianValue<unsigned long>, long)::{lambda()#1}::operator()() const
Unexecuted instantiation: WasmEdge::Executor::Executor::atomicWait<unsigned int>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned int, WasmEdge::EndianValue<unsigned int>, long)::{lambda()#1}::operator()() const
Unexecuted instantiation: WasmEdge::Executor::Executor::atomicWait<int>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned int, WasmEdge::EndianValue<int>, long)::{lambda()#1}::operator()() const
Unexecuted instantiation: WasmEdge::Executor::Executor::atomicWait<long>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned int, WasmEdge::EndianValue<long>, long)::{lambda()#1}::operator()() const
495
496
0
  while (true) {
497
0
    std::unique_lock<decltype(WaiterIterator->second.Mutex)> Locker(
498
0
        WaiterIterator->second.Mutex);
499
0
    std::cv_status WaitResult = std::cv_status::no_timeout;
500
0
    if (!Until) {
501
0
      WaiterIterator->second.Cond.wait(Locker);
502
0
    } else {
503
0
      WaitResult = WaiterIterator->second.Cond.wait_until(Locker, *Until);
504
0
    }
505
0
    if (unlikely(StopToken.load(std::memory_order_relaxed) != 0)) {
506
0
      return Unexpect(ErrCode::Value::Interrupted);
507
0
    }
508
0
    if (likely(AtomicObj->load() != Expected.le())) {
509
0
      return UINT32_C(0); // ok
510
0
    }
511
0
    if (WaitResult == std::cv_status::timeout) {
512
0
      return UINT32_C(2); // Timed-out
513
0
    }
514
0
  }
515
0
}
Unexecuted instantiation: cxx20::expected<unsigned int, WasmEdge::ErrCode> WasmEdge::Executor::Executor::atomicWait<unsigned long>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned int, WasmEdge::EndianValue<unsigned long>, long)
Unexecuted instantiation: cxx20::expected<unsigned int, WasmEdge::ErrCode> WasmEdge::Executor::Executor::atomicWait<unsigned int>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned int, WasmEdge::EndianValue<unsigned int>, long)
Unexecuted instantiation: cxx20::expected<unsigned int, WasmEdge::ErrCode> WasmEdge::Executor::Executor::atomicWait<int>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned int, WasmEdge::EndianValue<int>, long)
Unexecuted instantiation: cxx20::expected<unsigned int, WasmEdge::ErrCode> WasmEdge::Executor::Executor::atomicWait<long>(WasmEdge::Runtime::Instance::MemoryInstance&, unsigned int, WasmEdge::EndianValue<long>, long)
516
517
} // namespace Executor
518
} // namespace WasmEdge