Coverage Report

Created: 2026-06-30 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/WasmEdge/lib/executor/instantiate/data.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
#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
    uint64_t Offset = 0;
23
    // Initialize memory if the data mode is active.
24
0
    if (DataSeg.getMode() == AST::DataSegment::DataMode::Active) {
25
      // Run the initialization 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
      // Get memory instance and address type.
34
      // Memory64 proposal is checked in validation phase.
35
0
      auto *MemInst = getMemInstByIdx(StackMgr, DataSeg.getIdx());
36
0
      assuming(MemInst);
37
0
      Offset = extractAddr(StackMgr.pop(),
38
0
                           MemInst->getMemoryType().getLimit().getAddrType());
39
40
      // Check boundary unless ReferenceTypes or BulkMemoryOperations proposal
41
      // enabled.
42
0
      if (unlikely(!Conf.hasProposal(Proposal::ReferenceTypes) &&
43
0
                   !Conf.hasProposal(Proposal::BulkMemoryOperations))) {
44
        // Check data fits.
45
0
        if (!MemInst->checkAccessBound(Offset, DataSeg.getData().size())) {
46
0
          spdlog::error(ErrCode::Value::DataSegDoesNotFit);
47
0
          spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Seg_Data));
48
0
          return Unexpect(ErrCode::Value::DataSegDoesNotFit);
49
0
        }
50
0
      }
51
0
    }
52
53
    // Create and add the data instance to the module instance.
54
0
    ModInst.addData(Offset, DataSeg.getData());
55
0
  }
56
0
  return {};
57
0
}
58
59
// Initialize memory with Data section. See "include/executor/executor.h".
60
Expect<void> Executor::initMemory(Runtime::StackManager &StackMgr,
61
0
                                  const AST::DataSection &DataSec) {
62
  // Initialize memory.
63
0
  uint32_t Idx = 0;
64
0
  for (const auto &DataSeg : DataSec.getContent()) {
65
    // Initialize memory if data mode is active.
66
0
    if (DataSeg.getMode() == AST::DataSegment::DataMode::Active) {
67
      // Memory and data indices are checked in the validation phase.
68
0
      auto *MemInst = getMemInstByIdx(StackMgr, DataSeg.getIdx());
69
0
      assuming(MemInst);
70
0
      auto *DataInst = getDataInstByIdx(StackMgr, Idx);
71
0
      assuming(DataInst);
72
0
      const uint64_t Off = DataInst->getOffset();
73
74
      // Replace mem[Off : Off + n] with data[0 : n].
75
0
      EXPECTED_TRY(MemInst
76
0
                       ->setBytes(DataInst->getData(), Off, 0,
77
0
                                  DataInst->getData().size())
78
0
                       .map_error([](auto E) {
79
0
                         spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Seg_Data));
80
0
                         return E;
81
0
                       }));
82
83
      // Drop the data instance.
84
0
      DataInst->clear();
85
86
      // Operation above is equal to the following instruction sequence:
87
      //   expr(init) -> i32.const off
88
      //   i32.const 0
89
      //   i32.const n
90
      //   memory.init idx
91
      //   data.drop idx
92
0
    }
93
0
    Idx++;
94
0
  }
95
0
  return {};
96
0
}
97
98
} // namespace Executor
99
} // namespace WasmEdge