/src/WasmEdge/lib/executor/engine/memoryInstr.cpp
Line | Count | Source |
1 | | // SPDX-License-Identifier: Apache-2.0 |
2 | | // SPDX-FileCopyrightText: Copyright The WasmEdge Authors |
3 | | |
4 | | #include "executor/executor.h" |
5 | | |
6 | | namespace WasmEdge { |
7 | | namespace Executor { |
8 | | |
9 | | Expect<void> |
10 | | Executor::runMemorySizeOp(Runtime::StackManager &StackMgr, |
11 | 0 | Runtime::Instance::MemoryInstance &MemInst) { |
12 | | // Push SZ = page size to the stack. |
13 | 0 | const auto AddrType = MemInst.getMemoryType().getLimit().getAddrType(); |
14 | 0 | StackMgr.push(emplaceAddr(MemInst.getPageSize(), AddrType)); |
15 | 0 | return {}; |
16 | 0 | } |
17 | | |
18 | | Expect<void> |
19 | | Executor::runMemoryGrowOp(Runtime::StackManager &StackMgr, |
20 | 0 | Runtime::Instance::MemoryInstance &MemInst) { |
21 | | // Pop N, the number of pages to grow. |
22 | 0 | const auto AddrType = MemInst.getMemoryType().getLimit().getAddrType(); |
23 | 0 | uint64_t N = extractAddr(StackMgr.pop(), AddrType); |
24 | | |
25 | | // Grow the page and push the result. |
26 | 0 | const uint64_t CurrPageSize = MemInst.getPageSize(); |
27 | 0 | if (MemInst.growPage(N)) { |
28 | 0 | StackMgr.push(emplaceAddr(CurrPageSize, AddrType)); |
29 | 0 | } else { |
30 | 0 | StackMgr.push(emplaceAddr(static_cast<uint64_t>(-1), AddrType)); |
31 | 0 | } |
32 | 0 | return {}; |
33 | 0 | } |
34 | | |
35 | | Expect<void> Executor::runMemoryInitOp( |
36 | | Runtime::StackManager &StackMgr, Runtime::Instance::MemoryInstance &MemInst, |
37 | 0 | Runtime::Instance::DataInstance &DataInst, const AST::Instruction &Instr) { |
38 | | // Pop the length, source, and destination from the stack. |
39 | | // Currently, the length and source offset from the data instance are |
40 | | // 32-bit. |
41 | 0 | uint64_t Len = static_cast<uint64_t>(StackMgr.pop().get<uint32_t>()); |
42 | 0 | uint64_t Src = static_cast<uint64_t>(StackMgr.pop().get<uint32_t>()); |
43 | 0 | const auto AddrType = MemInst.getMemoryType().getLimit().getAddrType(); |
44 | 0 | uint64_t Dst = extractAddr(StackMgr.pop(), AddrType); |
45 | | |
46 | | // Replace mem[Dst : Dst + Len] with data[Src : Src + Len]. |
47 | 0 | return MemInst.setBytes(DataInst.getData(), Dst, Src, Len) |
48 | 0 | .map_error([&Instr](auto E) { |
49 | 0 | spdlog::error( |
50 | 0 | ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); |
51 | 0 | return E; |
52 | 0 | }); |
53 | 0 | } |
54 | | |
55 | | Expect<void> |
56 | 0 | Executor::runDataDropOp(Runtime::Instance::DataInstance &DataInst) { |
57 | | // Clear data instance. |
58 | 0 | DataInst.clear(); |
59 | 0 | return {}; |
60 | 0 | } |
61 | | |
62 | | Expect<void> |
63 | | Executor::runMemoryCopyOp(Runtime::StackManager &StackMgr, |
64 | | Runtime::Instance::MemoryInstance &MemInstDst, |
65 | | Runtime::Instance::MemoryInstance &MemInstSrc, |
66 | 0 | const AST::Instruction &Instr) { |
67 | | // Pop the length, source, and destination from the stack. |
68 | 0 | const auto AddrType1 = MemInstSrc.getMemoryType().getLimit().getAddrType(); |
69 | 0 | const auto AddrType2 = MemInstDst.getMemoryType().getLimit().getAddrType(); |
70 | 0 | uint64_t Len = extractAddr(StackMgr.pop(), std::min(AddrType1, AddrType2)); |
71 | 0 | uint64_t Src = extractAddr(StackMgr.pop(), AddrType1); |
72 | 0 | uint64_t Dst = extractAddr(StackMgr.pop(), AddrType2); |
73 | | |
74 | | // Replace mem[Dst : Dst + Len] with mem[Src : Src + Len]. |
75 | | // The overlapping region cases are handled in the setBytes() internal. |
76 | 0 | auto LogError = [&Instr](auto E) { |
77 | 0 | spdlog::error( |
78 | 0 | ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); |
79 | 0 | return E; |
80 | 0 | }; |
81 | 0 | EXPECTED_TRY(auto Data, MemInstSrc.getBytes(Src, Len).map_error(LogError)); |
82 | 0 | return MemInstDst.setBytes(Data, Dst, 0, Len).map_error(LogError); |
83 | 0 | } |
84 | | |
85 | | Expect<void> |
86 | | Executor::runMemoryFillOp(Runtime::StackManager &StackMgr, |
87 | | Runtime::Instance::MemoryInstance &MemInst, |
88 | 0 | const AST::Instruction &Instr) { |
89 | | // Pop the length, value, and offset from the stack. |
90 | 0 | const auto AddrType = MemInst.getMemoryType().getLimit().getAddrType(); |
91 | 0 | uint64_t Len = extractAddr(StackMgr.pop(), AddrType); |
92 | 0 | uint8_t Val = static_cast<uint8_t>(StackMgr.pop().get<uint32_t>()); |
93 | 0 | uint64_t Off = extractAddr(StackMgr.pop(), AddrType); |
94 | | |
95 | | // Fill data with Val. |
96 | 0 | return MemInst.fillBytes(Val, Off, Len).map_error([&Instr](auto E) { |
97 | 0 | spdlog::error( |
98 | 0 | ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); |
99 | 0 | return E; |
100 | 0 | }); |
101 | 0 | } |
102 | | |
103 | | } // namespace Executor |
104 | | } // namespace WasmEdge |