Coverage Report

Created: 2026-09-28 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/WasmEdge/include/ast/component/descriptor.h
Line
Count
Source
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright The WasmEdge Authors
3
4
//===-- wasmedge/ast/component/descriptor.h - Descriptor class definitions ===//
5
//
6
// Part of the WasmEdge Project.
7
//
8
//===----------------------------------------------------------------------===//
9
///
10
/// \file
11
/// This file contains the declaration of the Descriptor related class.
12
///
13
//===----------------------------------------------------------------------===//
14
#pragma once
15
16
#include "ast/type.h"
17
18
#include <variant>
19
20
namespace WasmEdge {
21
namespace AST {
22
namespace Component {
23
24
/// NOTE: The `ImportDesc` in AST implements the full import with name and
25
/// module name in one class. Therefore, create a `CoreImportDesc` class with
26
/// only the import descriptions for the component model.
27
28
/// AST Component::CoreImportDesc node.
29
class CoreImportDesc {
30
public:
31
49
  uint32_t getTypeIndex() const noexcept {
32
49
    return *std::get_if<uint32_t>(&Type);
33
49
  }
34
17.8k
  void setTypeIndex(const uint32_t Idx) noexcept {
35
17.8k
    Type.emplace<uint32_t>(Idx);
36
17.8k
  }
37
38
890
  const TableType &getTableType() const noexcept {
39
890
    return *std::get_if<TableType>(&Type);
40
890
  }
41
667
  void setTableType(TableType &&TT) noexcept {
42
667
    Type.emplace<TableType>(std::move(TT));
43
667
  }
44
45
932
  const MemoryType &getMemoryType() const noexcept {
46
932
    return *std::get_if<MemoryType>(&Type);
47
932
  }
48
485
  void setMemoryType(MemoryType &&MT) noexcept {
49
485
    Type.emplace<MemoryType>(std::move(MT));
50
485
  }
51
52
97
  const GlobalType &getGlobalType() const noexcept {
53
97
    return *std::get_if<GlobalType>(&Type);
54
97
  }
55
132
  void setGlobalType(GlobalType &&GT) noexcept {
56
132
    Type.emplace<GlobalType>(std::move(GT));
57
132
  }
58
59
101
  const TagType &getTagType() const noexcept {
60
101
    return *std::get_if<TagType>(&Type);
61
101
  }
62
477
  void setTagType(TagType &&TT) noexcept {
63
477
    Type.emplace<TagType>(std::move(TT));
64
477
  }
65
66
  /// The kind of core extern the descriptor describes.
67
1.10k
  ExternalType getExternalType() const noexcept {
68
1.10k
    if (std::holds_alternative<TableType>(Type)) {
69
447
      return ExternalType::Table;
70
447
    }
71
660
    if (std::holds_alternative<MemoryType>(Type)) {
72
467
      return ExternalType::Memory;
73
467
    }
74
193
    if (std::holds_alternative<GlobalType>(Type)) {
75
50
      return ExternalType::Global;
76
50
    }
77
143
    if (std::holds_alternative<TagType>(Type)) {
78
101
      return ExternalType::Tag;
79
101
    }
80
42
    return ExternalType::Function;
81
143
  }
82
83
private:
84
  std::variant<uint32_t, TableType, MemoryType, GlobalType, TagType> Type;
85
};
86
87
/// FROM:
88
/// https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#type-checking
89
///
90
/// When we next consider type imports and exports, there are two distinct
91
/// subcases of typebound to consider: eq and sub.
92
///
93
/// The eq bound adds a type equality rule (extending the built-in set of
94
/// subtyping rules) saying that the imported type is structurally equivalent to
95
/// the type referenced in the bound.
96
///
97
/// In contrast, the sub bound introduces a new abstract type which the rest of
98
/// the component must conservatively assume can be any type that is a subtype
99
/// of the bound. What this means for type-checking is that each subtype-bound
100
/// type import/export introduces a fresh abstract type that is unequal to every
101
/// preceding type definition.
102
///
103
/// NOTE:
104
/// Think of Java's `? extends T`.
105
///
106
/// 1. optional `some i` as `(eq i)`
107
/// 2. optional `none` as `sub`, i.e. Subresource
108
109
// externdesc ::= 0x00 0x11 i:<core:typeidx> => (core module (type i))
110
//              | 0x01 i:<typeidx>           => (func (type i))
111
//              | 0x02 b:<valuebound>        => (value b) 🪙
112
//              | 0x03 b:<typebound>         => (type b)
113
//              | 0x04 i:<typeidx>           => (component (type i))
114
//              | 0x05 i:<typeidx>           => (instance (type i))
115
// valuebound ::= 0x00 i:<valueidx>          => (eq i) 🪙
116
//              | 0x01 t:<valtype>           => t 🪙
117
// typebound  ::= 0x00 i:<typeidx>           => (eq i)
118
//              | 0x01                       => (sub resource)
119
120
class ExternDesc {
121
public:
122
  enum class DescType : uint8_t {
123
    CoreType = 0x00,
124
    FuncType = 0x01,
125
    ValueBound = 0x02,
126
    TypeBound = 0x03,
127
    ComponentType = 0x04,
128
    InstanceType = 0x05,
129
  };
130
131
5.92k
  DescType getDescType() const noexcept { return Type; }
132
1.61k
  uint32_t getTypeIndex() const noexcept { return Idx; }
133
5.16k
  bool isEqType() const noexcept { return Eq; }
134
785
  const ComponentValType &getValType() const noexcept { return VType; }
135
136
195
  void setCoreTypeIdx(const uint32_t I) noexcept {
137
195
    Type = DescType::CoreType;
138
195
    Idx = I;
139
195
  }
140
1.17k
  void setFuncTypeIdx(const uint32_t I) noexcept {
141
1.17k
    Type = DescType::FuncType;
142
1.17k
    Idx = I;
143
1.17k
  }
144
196
  void setValueBound(const uint32_t I) noexcept {
145
196
    Type = DescType::ValueBound;
146
196
    Eq = true;
147
196
    Idx = I;
148
196
  }
149
578
  void setValueBound(const ComponentValType &T) noexcept {
150
578
    Type = DescType::ValueBound;
151
578
    Eq = false;
152
578
    VType = T;
153
578
  }
154
875
  void setTypeBound(const uint32_t I) noexcept {
155
875
    Type = DescType::TypeBound;
156
875
    Eq = true;
157
875
    Idx = I;
158
875
  }
159
4.45k
  void setTypeBound() noexcept {
160
4.45k
    Type = DescType::TypeBound;
161
4.45k
    Eq = false;
162
4.45k
  }
163
439
  void setComponentTypeIdx(const uint32_t I) noexcept {
164
439
    Type = DescType::ComponentType;
165
439
    Idx = I;
166
439
  }
167
317
  void setInstanceTypeIdx(const uint32_t I) noexcept {
168
317
    Type = DescType::InstanceType;
169
317
    Idx = I;
170
317
  }
171
172
private:
173
  DescType Type;
174
  bool Eq;
175
  uint32_t Idx;
176
  ComponentValType VType;
177
};
178
179
} // namespace Component
180
} // namespace AST
181
} // namespace WasmEdge