Coverage Report

Created: 2025-07-01 06:18

/src/WasmEdge/lib/executor/instantiate/data.cpp
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 "executor/executor.h"
5
6
#include "common/errinfo.h"
7
#include "common/spdlog.h"
8
9
#include <cstdint>
10
11
namespace WasmEdge {
12
namespace Executor {
13
14
// Instantiate data instance. See "include/executor/executor.h".
15
Expect<void> Executor::instantiate(Runtime::StackManager &StackMgr,
16
                                   Runtime::Instance::ModuleInstance &ModInst,
17
0
                                   const AST::DataSection &DataSec) {
18
  // A frame with the current module has been pushed into the stack outside.
19
20
  // Iterate through the data segments to instantiate data instances.
21
0
  for (const auto &DataSeg : DataSec.getContent()) {
22
0
    uint32_t Offset = 0;
23
    // Initialize memory if the data mode is active.
24
0
    if (DataSeg.getMode() == AST::DataSegment::DataMode::Active) {
25
      // Run initialize expression.
26
0
      EXPECTED_TRY(runExpression(StackMgr, DataSeg.getExpr().getInstrs())
27
0
                       .map_error([](auto E) {
28
0
                         spdlog::error(
29
0
                             ErrInfo::InfoAST(ASTNodeAttr::Expression));
30
0
                         spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Seg_Data));
31
0
                         return E;
32
0
                       }));
33
0
      Offset = StackMgr.pop().get<uint32_t>();
34
35
      // Check boundary unless ReferenceTypes or BulkMemoryOperations proposal
36
      // enabled.
37
0
      if (!Conf.hasProposal(Proposal::ReferenceTypes) &&
38
0
          !Conf.hasProposal(Proposal::BulkMemoryOperations)) {
39
        // Memory index should be 0. Checked in validation phase.
40
0
        auto *MemInst = getMemInstByIdx(StackMgr, DataSeg.getIdx());
41
        // Check data fits.
42
0
        assuming(MemInst);
43
0
        if (!MemInst->checkAccessBound(
44
0
                Offset, static_cast<uint32_t>(DataSeg.getData().size()))) {
45
0
          spdlog::error(ErrCode::Value::DataSegDoesNotFit);
46
0
          spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Seg_Data));
47
0
          return Unexpect(ErrCode::Value::DataSegDoesNotFit);
48
0
        }
49
0
      }
50
0
    }
51
52
    // Create and add the data instance into the module instance.
53
0
    ModInst.addData(Offset, DataSeg.getData());
54
0
  }
55
0
  return {};
56
0
}
57
58
// Initialize memory with Data section. See "include/executor/executor.h".
59
Expect<void> Executor::initMemory(Runtime::StackManager &StackMgr,
60
0
                                  const AST::DataSection &DataSec) {
61
  // initialize memory.
62
0
  uint32_t Idx = 0;
63
0
  for (const auto &DataSeg : DataSec.getContent()) {
64
    // Initialize memory if data mode is active.
65
0
    if (DataSeg.getMode() == AST::DataSegment::DataMode::Active) {
66
      // Memory index should be 0. Checked in validation phase.
67
0
      auto *MemInst = getMemInstByIdx(StackMgr, DataSeg.getIdx());
68
0
      assuming(MemInst);
69
70
0
      auto *DataInst = getDataInstByIdx(StackMgr, Idx);
71
0
      assuming(DataInst);
72
0
      const uint32_t Off = DataInst->getOffset();
73
74
      // Replace mem[Off : Off + n] with data[0 : n].
75
0
      EXPECTED_TRY(
76
0
          MemInst
77
0
              ->setBytes(DataInst->getData(), Off, 0,
78
0
                         static_cast<uint32_t>(DataInst->getData().size()))
79
0
              .map_error([](auto E) {
80
0
                spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Seg_Data));
81
0
                return E;
82
0
              }));
83
84
      // Drop the data instance.
85
0
      DataInst->clear();
86
87
      // Operation above is equal to the following instruction sequence:
88
      //   expr(init) -> i32.const off
89
      //   i32.const 0
90
      //   i32.const n
91
      //   memory.init idx
92
      //   data.drop idx
93
0
    }
94
0
    Idx++;
95
0
  }
96
0
  return {};
97
0
}
98
99
} // namespace Executor
100
} // namespace WasmEdge