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/elem.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
#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 the stack.
33
0
      InitVals.push_back(StackMgr.pop().get<RefVariant>());
34
0
    }
35
36
0
    uint64_t Offset = 0;
37
0
    if (ElemSeg.getMode() == AST::ElementSegment::ElemMode::Active) {
38
      // Run the initialization 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
      // Get table instance and address type.
47
      // Memory64 proposal is checked in validation phase.
48
0
      auto *TabInst = getTabInstByIdx(StackMgr, ElemSeg.getIdx());
49
0
      assuming(TabInst);
50
0
      Offset = extractAddr(StackMgr.pop(),
51
0
                           TabInst->getTableType().getLimit().getAddrType());
52
53
      // Check boundary unless ReferenceTypes or BulkMemoryOperations proposal
54
      // enabled.
55
0
      if (unlikely(!Conf.hasProposal(Proposal::ReferenceTypes) &&
56
0
                   !Conf.hasProposal(Proposal::BulkMemoryOperations))) {
57
        // Check elements fits.
58
0
        if (!TabInst->checkAccessBound(Offset, InitVals.size())) {
59
0
          spdlog::error(ErrCode::Value::ElemSegDoesNotFit);
60
0
          spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Seg_Element));
61
0
          return Unexpect(ErrCode::Value::ElemSegDoesNotFit);
62
0
        }
63
0
      }
64
0
    }
65
66
    // Create and add the element instance to the module instance.
67
0
    ModInst.addElem(Offset, ElemSeg.getRefType(), InitVals);
68
0
  }
69
0
  return {};
70
0
}
71
72
// Initialize table with Element section. See "include/executor/executor.h".
73
Expect<void> Executor::initTable(Runtime::StackManager &StackMgr,
74
0
                                 const AST::ElementSection &ElemSec) {
75
  // Initialize tables.
76
0
  uint32_t Idx = 0;
77
0
  for (const auto &ElemSeg : ElemSec.getContent()) {
78
    // Element index is checked in validation phase.
79
0
    auto *ElemInst = getElemInstByIdx(StackMgr, Idx);
80
0
    assuming(ElemInst);
81
0
    if (ElemSeg.getMode() == AST::ElementSegment::ElemMode::Active) {
82
      // Table index is checked in validation phase.
83
0
      auto *TabInst = getTabInstByIdx(StackMgr, ElemSeg.getIdx());
84
0
      assuming(TabInst);
85
0
      const uint64_t Off = ElemInst->getOffset();
86
87
      // Replace table[Off : Off + n] with elem[0 : n].
88
0
      EXPECTED_TRY(
89
0
          TabInst
90
0
              ->setRefs(ElemInst->getRefs(), Off, 0, ElemInst->getRefs().size())
91
0
              .map_error([](auto E) {
92
0
                spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Seg_Element));
93
0
                return E;
94
0
              }));
95
96
      // Drop the element instance.
97
0
      ElemInst->clear();
98
99
      // Operation above is equal to the following instruction sequence:
100
      //   expr(init) -> i32.const off
101
      //   i32.const 0
102
      //   i32.const n
103
      //   table.init idx
104
      //   elem.drop idx
105
0
    } else if (ElemSeg.getMode() ==
106
0
               AST::ElementSegment::ElemMode::Declarative) {
107
      // Drop the element instance.
108
0
      ElemInst->clear();
109
0
    }
110
0
    Idx++;
111
0
  }
112
0
  return {};
113
0
}
114
115
} // namespace Executor
116
} // namespace WasmEdge