Coverage Report

Created: 2025-07-01 06:18

/src/WasmEdge/include/validator/context.h
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: 2019-2024 Second State INC
3
#pragma once
4
5
#include "ast/component/component.h"
6
#include "ast/module.h"
7
#include "common/errinfo.h"
8
9
#include <deque>
10
#include <optional>
11
#include <unordered_map>
12
#include <vector>
13
14
namespace WasmEdge {
15
namespace Validator {
16
17
class Context {
18
public:
19
  struct ComponentContext {
20
    const AST::Component::Component *Component;
21
    std::vector<AST::Module> CoreModules;
22
    std::vector<AST::Component::Component> ChildComponents;
23
    std::optional<const ComponentContext *> Parent;
24
    std::unordered_map<AST::Component::SortCase, size_t> ComponentIndexSizes;
25
    std::unordered_map<AST::Component::CoreSort, size_t> CoreIndexSizes;
26
    std::unordered_map<std::string, uint32_t> TypeSubstitutions;
27
28
    std::unordered_map<uint32_t, std::unordered_map<std::string_view,
29
                                                    AST::Component::ExternDesc>>
30
        ComponentInstanceExports;
31
    std::unordered_map<uint32_t,
32
                       std::unordered_map<std::string_view, ExternalType>>
33
        CoreInstanceExports;
34
    std::unordered_map<uint32_t, AST::Component::InstanceType>
35
        ComponentInstanceTypes;
36
    std::unordered_map<uint32_t, AST::Component::ResourceType>
37
        ComponentResourceTypes;
38
39
    ComponentContext(const AST::Component::Component *C,
40
                     std::optional<const ComponentContext *> P = std::nullopt)
41
0
        : Component(C), CoreModules(), ChildComponents(), Parent(P) {}
42
43
0
    size_t getComponentIndexSize(AST::Component::SortCase SC) const noexcept {
44
0
      auto It = ComponentIndexSizes.find(SC);
45
0
      if (It != ComponentIndexSizes.end()) {
46
0
        return It->second;
47
0
      } else {
48
0
        return 0;
49
0
      }
50
0
    }
51
52
0
    size_t getCoreIndexSize(AST::Component::CoreSort CS) const noexcept {
53
0
      auto It = CoreIndexSizes.find(CS);
54
0
      if (It != CoreIndexSizes.end()) {
55
0
        return It->second;
56
0
      } else {
57
0
        return 0;
58
0
      }
59
0
    }
60
  };
61
62
0
  void enterComponent(const AST::Component::Component &C) {
63
0
    if (!ComponentContexts.empty()) {
64
0
      ComponentContexts.back().ChildComponents.emplace_back(C);
65
0
    }
66
67
0
    std::optional<const ComponentContext *> Parent;
68
0
    if (ComponentContexts.empty()) {
69
0
      Parent = std::nullopt;
70
0
    } else {
71
0
      Parent = std::optional{&ComponentContexts.back()};
72
0
    }
73
74
0
    ComponentContexts.emplace_back(&C, Parent);
75
0
  }
76
77
0
  void exitComponent() {
78
0
    if (!ComponentContexts.empty()) {
79
0
      ComponentContexts.pop_back();
80
0
    } else {
81
0
      assumingUnreachable();
82
0
    }
83
0
  }
84
85
0
  ComponentContext &getCurrentContext() { return ComponentContexts.back(); }
86
87
0
  const ComponentContext &getCurrentContext() const {
88
0
    return ComponentContexts.back();
89
0
  }
90
91
0
  void addCoreModule(const AST::Module &M) {
92
0
    getCurrentContext().CoreModules.emplace_back(M);
93
0
  }
94
95
0
  const AST::Module &getCoreModule(uint32_t Index) const {
96
0
    return getCurrentContext().CoreModules.at(Index);
97
0
  }
98
99
0
  size_t getCoreModuleCount() const {
100
0
    return getCurrentContext().CoreModules.size();
101
0
  }
102
103
0
  const AST::Component::Component &getComponent(uint32_t Index) const {
104
0
    return getCurrentContext().ChildComponents.at(Index);
105
0
  }
106
107
0
  size_t getComponentCount() const {
108
0
    return getCurrentContext().ChildComponents.size();
109
0
  }
110
111
0
  std::optional<const ComponentContext *> getParentContext() const {
112
0
    if (ComponentContexts.empty()) {
113
0
      return std::nullopt;
114
0
    }
115
0
    return ComponentContexts.back().Parent;
116
0
  }
117
118
0
  size_t getComponentIndexSize(AST::Component::SortCase SC) const noexcept {
119
0
    const auto &Ctx = getCurrentContext();
120
0
    auto It = Ctx.ComponentIndexSizes.find(SC);
121
0
    if (It != Ctx.ComponentIndexSizes.end()) {
122
0
      return It->second;
123
0
    } else {
124
0
      return 0;
125
0
    }
126
0
  }
127
128
0
  size_t getCoreIndexSize(AST::Component::CoreSort CS) const noexcept {
129
0
    const auto &Ctx = getCurrentContext();
130
0
    auto It = Ctx.CoreIndexSizes.find(CS);
131
0
    if (It != Ctx.CoreIndexSizes.end()) {
132
0
      return It->second;
133
0
    } else {
134
0
      return 0;
135
0
    }
136
0
  }
137
138
0
  void incComponentIndexSize(AST::Component::SortCase SC) noexcept {
139
0
    getCurrentContext().ComponentIndexSizes[SC]++;
140
0
  }
141
142
0
  void incCoreIndexSize(AST::Component::CoreSort CS) noexcept {
143
0
    getCurrentContext().CoreIndexSizes[CS]++;
144
0
  }
145
146
0
  void substituteTypeImport(const std::string &ImportName, uint32_t TypeIdx) {
147
0
    getCurrentContext().TypeSubstitutions[ImportName] = TypeIdx;
148
0
  }
149
150
  std::optional<uint32_t>
151
0
  getSubstitutedType(const std::string &ImportName) const {
152
0
    const auto &Ctx = getCurrentContext();
153
0
    auto It = Ctx.TypeSubstitutions.find(ImportName);
154
0
    if (It != Ctx.TypeSubstitutions.end()) {
155
0
      return It->second;
156
0
    }
157
0
    return std::nullopt;
158
0
  }
159
160
  void addComponentInstanceExport(uint32_t InstanceIdx,
161
                                  const std::string_view &ExportName,
162
0
                                  const AST::Component::ExternDesc &ED) {
163
0
    auto &Ctx = getCurrentContext();
164
0
    Ctx.ComponentInstanceExports[InstanceIdx][ExportName] = ED;
165
0
  }
166
167
  std::unordered_map<std::string_view, AST::Component::ExternDesc>
168
0
  getComponentInstanceExports(uint32_t InstanceIdx) const {
169
0
    const auto &Ctx = getCurrentContext();
170
0
    auto It = Ctx.ComponentInstanceExports.find(InstanceIdx);
171
0
    if (It != Ctx.ComponentInstanceExports.end()) {
172
0
      return It->second;
173
0
    }
174
0
    return {};
175
0
  }
176
177
0
  size_t getComponentInstanceExportsSize() const {
178
0
    const auto &Exports = getCurrentContext().ComponentInstanceExports;
179
0
    if (Exports.empty()) {
180
0
      return 0;
181
0
    }
182
183
0
    uint32_t MaxIdx = 0;
184
0
    for (const auto &Pair : Exports) {
185
0
      if (Pair.first > MaxIdx) {
186
0
        MaxIdx = Pair.first;
187
0
      }
188
0
    }
189
0
    return static_cast<size_t>(MaxIdx) + 1;
190
0
  }
191
192
  void addCoreInstanceExport(uint32_t InstanceIdx,
193
                             const std::string_view &ExportName,
194
0
                             const ExternalType &ET) {
195
0
    auto &Ctx = getCurrentContext();
196
0
    Ctx.CoreInstanceExports[InstanceIdx][ExportName] = ET;
197
0
  }
198
199
  std::unordered_map<std::string_view, ExternalType>
200
0
  getCoreInstanceExports(uint32_t InstanceIdx) const {
201
0
    const auto &Ctx = getCurrentContext();
202
0
    auto It = Ctx.CoreInstanceExports.find(InstanceIdx);
203
0
    if (It != Ctx.CoreInstanceExports.end()) {
204
0
      return It->second;
205
0
    }
206
0
    return {};
207
0
  }
208
209
0
  size_t getCoreInstanceExportsSize() const {
210
0
    const auto &Exports = getCurrentContext().CoreInstanceExports;
211
0
    if (Exports.empty()) {
212
0
      return 0;
213
0
    }
214
215
0
    uint32_t MaxIdx = 0;
216
0
    for (const auto &Pair : Exports) {
217
0
      if (Pair.first > MaxIdx) {
218
0
        MaxIdx = Pair.first;
219
0
      }
220
0
    }
221
0
    return static_cast<size_t>(MaxIdx) + 1;
222
0
  }
223
224
  void addComponentInstanceType(uint32_t Idx,
225
0
                                const AST::Component::InstanceType &IT) {
226
0
    auto &Ctx = getCurrentContext();
227
0
    Ctx.ComponentInstanceTypes[Idx] = IT;
228
0
  }
229
230
  const AST::Component::InstanceType *
231
0
  getComponentInstanceType(uint32_t Idx) const {
232
0
    const auto &Ctx = getCurrentContext();
233
0
    auto It = Ctx.ComponentInstanceTypes.find(Idx);
234
0
    if (It != Ctx.ComponentInstanceTypes.end()) {
235
0
      return &It->second;
236
0
    } else {
237
0
      return nullptr;
238
0
    }
239
0
  }
240
241
  void addComponentResourceType(uint32_t Idx,
242
0
                                const AST::Component::ResourceType &IT) {
243
0
    auto &Ctx = getCurrentContext();
244
0
    Ctx.ComponentResourceTypes[Idx] = IT;
245
0
  }
246
247
  const AST::Component::ResourceType *
248
0
  getComponentResourceType(uint32_t Idx) const {
249
0
    const auto &Ctx = getCurrentContext();
250
0
    auto It = Ctx.ComponentResourceTypes.find(Idx);
251
0
252
0
    if (It != Ctx.ComponentResourceTypes.end()) {
253
0
      return &It->second;
254
0
    } else {
255
0
      return nullptr;
256
0
    }
257
0
  }
258
259
private:
260
  std::deque<ComponentContext> ComponentContexts;
261
};
262
263
class ComponentContextGuard {
264
public:
265
  ComponentContextGuard(const AST::Component::Component &C, Context &Ctx)
266
0
      : Ctx(Ctx) {
267
0
    Ctx.enterComponent(C);
268
0
  }
269
270
0
  ~ComponentContextGuard() { Ctx.exitComponent(); }
271
272
private:
273
  Context &Ctx;
274
};
275
276
} // namespace Validator
277
} // namespace WasmEdge