Coverage Report

Created: 2025-08-25 06:58

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