Coverage Report

Created: 2025-08-25 06:58

/src/WasmEdge/include/ast/component/descriptor.h
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: 2019-2025 Second State INC
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/component/valtype.h"
17
#include "ast/type.h"
18
19
#include <variant>
20
21
namespace WasmEdge {
22
namespace AST {
23
namespace Component {
24
25
/// NOTE: The `ImportDesc` in AST implemented the fully import with name and
26
/// module name in a class. Therefore create a `CoreImportDesc` class with
27
/// only the import descriptions for component model.
28
29
/// AST Component::CoreImportDesc node.
30
class CoreImportDesc {
31
public:
32
0
  uint32_t getTypeIndex() const noexcept {
33
0
    return *std::get_if<uint32_t>(&Type);
34
0
  }
35
0
  void setTypeIndex(const uint32_t Idx) noexcept {
36
0
    Type.emplace<uint32_t>(Idx);
37
0
  }
38
39
0
  const TableType &getTableType() const noexcept {
40
0
    return *std::get_if<TableType>(&Type);
41
0
  }
42
0
  void setTableType(TableType &&TT) noexcept {
43
0
    Type.emplace<TableType>(std::move(TT));
44
0
  }
45
46
0
  const MemoryType &getMemoryType() const noexcept {
47
0
    return *std::get_if<MemoryType>(&Type);
48
0
  }
49
0
  void setMemoryType(MemoryType &&MT) noexcept {
50
0
    Type.emplace<MemoryType>(std::move(MT));
51
0
  }
52
53
0
  const GlobalType &getGlobalType() const noexcept {
54
0
    return *std::get_if<GlobalType>(&Type);
55
0
  }
56
0
  void setGlobalType(GlobalType &&GT) noexcept {
57
0
    Type.emplace<GlobalType>(std::move(GT));
58
0
  }
59
60
0
  const TagType &getTagType() const noexcept {
61
0
    return *std::get_if<TagType>(&Type);
62
0
  }
63
0
  void setTagType(TagType &&TT) noexcept {
64
0
    Type.emplace<TagType>(std::move(TT));
65
0
  }
66
67
private:
68
  std::variant<uint32_t, TableType, MemoryType, GlobalType, TagType> Type;
69
};
70
71
/// FROM:
72
/// https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#type-checking
73
///
74
/// When we next consider type imports and exports, there are two distinct
75
/// subcases of typebound to consider: eq and sub.
76
///
77
/// The eq bound adds a type equality rule (extending the built-in set of
78
/// subtyping rules) saying that the imported type is structurally equivalent to
79
/// the type referenced in the bound.
80
///
81
/// In contrast, the sub bound introduces a new abstract type which the rest of
82
/// the component must conservatively assume can be any type that is a subtype
83
/// of the bound. What this means for type-checking is that each subtype-bound
84
/// type import/export introduces a fresh abstract type that is unequal to every
85
/// preceding type definition.
86
///
87
/// NOTE:
88
/// One just need to consider Java's `? extends T` in mind.
89
///
90
/// 1. optional `some i` as `(eq i)`
91
/// 2. optional `none` as `sub`, i.e. Subresource
92
93
// externdesc ::= 0x00 0x11 i:<core:typeidx> => (core module (type i))
94
//              | 0x01 i:<typeidx>           => (func (type i))
95
//              | 0x02 b:<valuebound>        => (value b) 🪙
96
//              | 0x03 b:<typebound>         => (type b)
97
//              | 0x04 i:<typeidx>           => (component (type i))
98
//              | 0x05 i:<typeidx>           => (instance (type i))
99
// valuebound ::= 0x00 i:<valueidx>          => (eq i) 🪙
100
//              | 0x01 t:<valtype>           => t 🪙
101
// typebound  ::= 0x00 i:<typeidx>           => (eq i)
102
//              | 0x01                       => (sub resource)
103
104
class ExternDesc {
105
public:
106
  enum class DescType : Byte {
107
    CoreType = 0x00,
108
    FuncType = 0x01,
109
    ValueBound = 0x02,
110
    TypeBound = 0x03,
111
    ComponentType = 0x04,
112
    InstanceType = 0x05,
113
  };
114
115
0
  DescType getDescType() const noexcept { return Type; }
116
0
  uint32_t getTypeIndex() const noexcept { return Idx; }
117
0
  bool isEqType() const noexcept { return Eq; }
118
0
  const ValueType &getValueType() const noexcept { return VType; }
119
120
0
  void setCoreTypeIdx(const uint32_t I) noexcept {
121
0
    Type = DescType::CoreType;
122
0
    Idx = I;
123
0
  }
124
0
  void setFuncTypeIdx(const uint32_t I) noexcept {
125
0
    Type = DescType::FuncType;
126
0
    Idx = I;
127
0
  }
128
0
  void setValueBound(const uint32_t I) noexcept {
129
0
    Type = DescType::ValueBound;
130
0
    Eq = true;
131
0
    Idx = I;
132
0
  }
133
0
  void setValueBound(const ValueType &T) noexcept {
134
0
    Type = DescType::ValueBound;
135
0
    Eq = false;
136
0
    VType = T;
137
0
  }
138
0
  void setTypeBound(const uint32_t I) noexcept {
139
0
    Type = DescType::TypeBound;
140
0
    Eq = true;
141
0
    Idx = I;
142
0
  }
143
0
  void setTypeBound() noexcept {
144
0
    Type = DescType::TypeBound;
145
0
    Eq = false;
146
0
  }
147
0
  void setComponentTypeIdx(const uint32_t I) noexcept {
148
0
    Type = DescType::ComponentType;
149
0
    Idx = I;
150
0
  }
151
0
  void setInstanceTypeIdx(const uint32_t I) noexcept {
152
0
    Type = DescType::InstanceType;
153
0
    Idx = I;
154
0
  }
155
156
private:
157
  DescType Type;
158
  bool Eq;
159
  uint32_t Idx;
160
  ValueType VType;
161
};
162
163
} // namespace Component
164
} // namespace AST
165
} // namespace WasmEdge