Coverage Report

Created: 2025-07-01 06:18

/src/WasmEdge/lib/executor/instantiate/elem.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
#include <cstdint>
9
#include <vector>
10
11
namespace WasmEdge {
12
namespace Executor {
13
14
// Instantiate element instance. See "include/executor/executor.h".
15
Expect<void> Executor::instantiate(Runtime::StackManager &StackMgr,
16
                                   Runtime::Instance::ModuleInstance &ModInst,
17
0
                                   const AST::ElementSection &ElemSec) {
18
  // A frame with the current module has been pushed into the stack outside.
19
20
  // Iterate through the element segments to instantiate element instances.
21
0
  for (const auto &ElemSeg : ElemSec.getContent()) {
22
0
    std::vector<RefVariant> InitVals;
23
0
    for (const auto &Expr : ElemSeg.getInitExprs()) {
24
      // Run init expr of every elements and get the result reference.
25
0
      EXPECTED_TRY(
26
0
          runExpression(StackMgr, Expr.getInstrs()).map_error([](auto E) {
27
0
            spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Expression));
28
0
            spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Seg_Element));
29
0
            return E;
30
0
          }));
31
      // Pop result from stack.
32
0
      InitVals.push_back(StackMgr.pop().get<RefVariant>());
33
0
    }
34
35
0
    uint32_t Offset = 0;
36
0
    if (ElemSeg.getMode() == AST::ElementSegment::ElemMode::Active) {
37
      // Run initialize expression.
38
0
      EXPECTED_TRY(
39
0
          runExpression(StackMgr, ElemSeg.getExpr().getInstrs())
40
0
              .map_error([](auto E) {
41
0
                spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Expression));
42
0
                spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Seg_Element));
43
0
                return E;
44
0
              }));
45
0
      Offset = StackMgr.pop().get<uint32_t>();
46
47
      // Check boundary unless ReferenceTypes or BulkMemoryOperations proposal
48
      // enabled.
49
0
      if (!Conf.hasProposal(Proposal::ReferenceTypes) &&
50
0
          !Conf.hasProposal(Proposal::BulkMemoryOperations)) {
51
        // Table index should be 0. Checked in validation phase.
52
0
        auto *TabInst = getTabInstByIdx(StackMgr, ElemSeg.getIdx());
53
        // Check elements fits.
54
0
        assuming(TabInst);
55
0
        if (!TabInst->checkAccessBound(
56
0
                Offset, static_cast<uint32_t>(InitVals.size()))) {
57
0
          spdlog::error(ErrCode::Value::ElemSegDoesNotFit);
58
0
          spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Seg_Element));
59
0
          return Unexpect(ErrCode::Value::ElemSegDoesNotFit);
60
0
        }
61
0
      }
62
0
    }
63
64
    // Create and add the element instance into the module instance.
65
0
    ModInst.addElem(Offset, ElemSeg.getRefType(), InitVals);
66
0
  }
67
0
  return {};
68
0
}
69
70
// Initialize table with Element section. See "include/executor/executor.h".
71
Expect<void> Executor::initTable(Runtime::StackManager &StackMgr,
72
0
                                 const AST::ElementSection &ElemSec) {
73
  // Initialize tables.
74
0
  uint32_t Idx = 0;
75
0
  for (const auto &ElemSeg : ElemSec.getContent()) {
76
0
    auto *ElemInst = getElemInstByIdx(StackMgr, Idx);
77
0
    assuming(ElemInst);
78
0
    if (ElemSeg.getMode() == AST::ElementSegment::ElemMode::Active) {
79
      // Table index is checked in validation phase.
80
0
      auto *TabInst = getTabInstByIdx(StackMgr, ElemSeg.getIdx());
81
0
      assuming(TabInst);
82
0
      const uint32_t Off = ElemInst->getOffset();
83
84
      // Replace table[Off : Off + n] with elem[0 : n].
85
0
      EXPECTED_TRY(
86
0
          TabInst
87
0
              ->setRefs(ElemInst->getRefs(), Off, 0,
88
0
                        static_cast<uint32_t>(ElemInst->getRefs().size()))
89
0
              .map_error([](auto E) {
90
0
                spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Seg_Element));
91
0
                return E;
92
0
              }));
93
94
      // Drop the element instance.
95
0
      ElemInst->clear();
96
97
      // Operation above is equal to the following instruction sequence:
98
      //   expr(init) -> i32.const off
99
      //   i32.const 0
100
      //   i32.const n
101
      //   table.init idx
102
      //   elem.drop idx
103
0
    } else if (ElemSeg.getMode() ==
104
0
               AST::ElementSegment::ElemMode::Declarative) {
105
      // Drop the element instance.
106
0
      ElemInst->clear();
107
0
    }
108
0
    Idx++;
109
0
  }
110
0
  return {};
111
0
}
112
113
} // namespace Executor
114
} // namespace WasmEdge