Coverage Report

Created: 2025-07-01 06:18

/src/WasmEdge/include/loader/serialize.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
4
//===-- wasmedge/loader/serialize.h - Serializer class definition ---------===//
5
//
6
// Part of the WasmEdge Project.
7
//
8
//===----------------------------------------------------------------------===//
9
///
10
/// \file
11
/// This file contains the declaration of the Serializer class, which serialize
12
/// a AST Module into a buffer.
13
///
14
//===----------------------------------------------------------------------===//
15
#pragma once
16
17
#include "ast/module.h"
18
#include "common/configure.h"
19
#include "common/errcode.h"
20
#include "common/errinfo.h"
21
22
#include <vector>
23
24
namespace WasmEdge {
25
namespace Loader {
26
27
class Serializer {
28
public:
29
9.30k
  Serializer(const Configure &Conf) noexcept : Conf(Conf) {}
30
  ~Serializer() noexcept = default;
31
32
  /// Serialize a WASM module.
33
  Expect<std::vector<uint8_t>>
34
  serializeModule(const AST::Module &Mod) const noexcept;
35
36
  /// \name Serialize functions for WASM sections.
37
  /// @{
38
  Expect<void> serializeSection(const AST::CustomSection &Sec,
39
                                std::vector<uint8_t> &OutVec) const noexcept;
40
  Expect<void> serializeSection(const AST::TypeSection &Sec,
41
                                std::vector<uint8_t> &OutVec) const noexcept;
42
  Expect<void> serializeSection(const AST::ImportSection &Sec,
43
                                std::vector<uint8_t> &OutVec) const noexcept;
44
  Expect<void> serializeSection(const AST::FunctionSection &Sec,
45
                                std::vector<uint8_t> &OutVec) const noexcept;
46
  Expect<void> serializeSection(const AST::TableSection &Sec,
47
                                std::vector<uint8_t> &OutVec) const noexcept;
48
  Expect<void> serializeSection(const AST::MemorySection &Sec,
49
                                std::vector<uint8_t> &OutVec) const noexcept;
50
  Expect<void> serializeSection(const AST::GlobalSection &Sec,
51
                                std::vector<uint8_t> &OutVec) const noexcept;
52
  Expect<void> serializeSection(const AST::ExportSection &Sec,
53
                                std::vector<uint8_t> &OutVec) const noexcept;
54
  Expect<void> serializeSection(const AST::StartSection &Sec,
55
                                std::vector<uint8_t> &OutVec) const noexcept;
56
  Expect<void> serializeSection(const AST::ElementSection &Sec,
57
                                std::vector<uint8_t> &OutVec) const noexcept;
58
  Expect<void> serializeSection(const AST::CodeSection &Sec,
59
                                std::vector<uint8_t> &OutVec) const noexcept;
60
  Expect<void> serializeSection(const AST::DataSection &Sec,
61
                                std::vector<uint8_t> &OutVec) const noexcept;
62
  Expect<void> serializeSection(const AST::DataCountSection &Sec,
63
                                std::vector<uint8_t> &OutVec) const noexcept;
64
  Expect<void> serializeSection(const AST::TagSection &Sec,
65
                                std::vector<uint8_t> &OutVec) const noexcept;
66
  /// @}
67
68
0
  void serializeU32(uint32_t Num, std::vector<uint8_t> &OutVec) const noexcept {
69
0
    serializeUN<uint32_t, 32>(Num, OutVec, OutVec.end());
70
0
  }
71
72
private:
73
  /// \name Serialize functions for the other nodes of AST.
74
  /// @{
75
  Expect<void> serializeSegment(const AST::TableSegment &Seg,
76
                                std::vector<uint8_t> &OutVec) const noexcept;
77
  Expect<void> serializeSegment(const AST::GlobalSegment &Seg,
78
                                std::vector<uint8_t> &OutVec) const noexcept;
79
  Expect<void> serializeSegment(const AST::ElementSegment &Seg,
80
                                std::vector<uint8_t> &OutVec) const noexcept;
81
  Expect<void> serializeSegment(const AST::CodeSegment &Seg,
82
                                std::vector<uint8_t> &OutVec) const noexcept;
83
  Expect<void> serializeSegment(const AST::DataSegment &Seg,
84
                                std::vector<uint8_t> &OutVec) const noexcept;
85
  Expect<void> serializeDesc(const AST::ImportDesc &Desc,
86
                             std::vector<uint8_t> &OutVec) const noexcept;
87
  Expect<void> serializeDesc(const AST::ExportDesc &Desc,
88
                             std::vector<uint8_t> &OutVec) const noexcept;
89
  Expect<void> serializeHeapType(const ValType &Type, ASTNodeAttr From,
90
                                 std::vector<uint8_t> &OutVec) const noexcept;
91
  Expect<void> serializeRefType(const ValType &Type, ASTNodeAttr From,
92
                                std::vector<uint8_t> &OutVec) const noexcept;
93
  Expect<void> serializeValType(const ValType &Type, ASTNodeAttr From,
94
                                std::vector<uint8_t> &OutVec) const noexcept;
95
  Expect<void> serializeLimit(const AST::Limit &Lim,
96
                              std::vector<uint8_t> &OutVec) const noexcept;
97
  Expect<void> serializeType(const AST::SubType &SType,
98
                             std::vector<uint8_t> &OutVec) const noexcept;
99
  Expect<void> serializeType(const AST::FunctionType &Type,
100
                             std::vector<uint8_t> &OutVec) const noexcept;
101
  Expect<void> serializeType(const AST::TableType &Type,
102
                             std::vector<uint8_t> &OutVec) const noexcept;
103
  Expect<void> serializeType(const AST::MemoryType &Type,
104
                             std::vector<uint8_t> &OutVec) const noexcept;
105
  Expect<void> serializeType(const AST::GlobalType &Type,
106
                             std::vector<uint8_t> &OutVec) const noexcept;
107
  Expect<void> serializeType(const AST::FieldType &Type,
108
                             std::vector<uint8_t> &OutVec) const noexcept;
109
  Expect<void> serializeType(const AST::TagType &Type,
110
                             std::vector<uint8_t> &OutVec) const noexcept;
111
  Expect<void> serializeExpression(const AST::Expression &Expr,
112
                                   std::vector<uint8_t> &OutVec) const noexcept;
113
  Expect<void>
114
  serializeInstruction(const AST::Instruction &Instr,
115
                       std::vector<uint8_t> &OutVec) const noexcept;
116
  /// @}
117
118
  /// \name Helper functions
119
  /// @{
120
  inline Unexpected<ErrCode>
121
0
  logSerializeError(ErrCode Code, ASTNodeAttr Node) const noexcept {
122
0
    spdlog::error(Code);
123
0
    spdlog::error(ErrInfo::InfoAST(Node));
124
0
    return Unexpect(Code);
125
0
  }
126
  inline Unexpected<ErrCode> logNeedProposal(ErrCode Code, Proposal Prop,
127
0
                                             ASTNodeAttr Node) const noexcept {
128
0
    spdlog::error(Code);
129
0
    spdlog::error(ErrInfo::InfoProposal(Prop));
130
0
    spdlog::error(ErrInfo::InfoAST(Node));
131
0
    return Unexpect(Code);
132
0
  }
133
134
  template <typename NumType, size_t N>
135
  void serializeUN(NumType Num, std::vector<uint8_t> &OutVec,
136
0
                   std::vector<uint8_t>::iterator It) const noexcept {
137
0
    uint8_t Buf[N / 7 + 1];
138
0
    uint32_t Len = 0;
139
0
    do {
140
0
      uint8_t X = std::make_unsigned_t<NumType>(Num) & 0x7FU;
141
0
      Num >>= 7;
142
0
      if (Num) {
143
0
        X |= 0x80U;
144
0
      }
145
0
      Buf[Len] = X;
146
0
      Len++;
147
0
    } while (Num);
148
0
    OutVec.insert(It, Buf, Buf + Len);
149
0
  }
Unexecuted instantiation: void WasmEdge::Loader::Serializer::serializeUN<unsigned int, 32ul>(unsigned int, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, std::__1::__wrap_iter<unsigned char*>) const
Unexecuted instantiation: void WasmEdge::Loader::Serializer::serializeUN<unsigned long, 64ul>(unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, std::__1::__wrap_iter<unsigned char*>) const
150
151
  void serializeU32(uint32_t Num, std::vector<uint8_t> &OutVec,
152
0
                    std::vector<uint8_t>::iterator It) const noexcept {
153
0
    serializeUN<uint32_t, 32>(Num, OutVec, It);
154
0
  }
155
  void serializeU64(uint64_t Num, std::vector<uint8_t> &OutVec,
156
0
                    std::vector<uint8_t>::iterator It) const noexcept {
157
0
    serializeUN<uint64_t, 64>(Num, OutVec, It);
158
0
  }
159
0
  void serializeU64(uint64_t Num, std::vector<uint8_t> &OutVec) const noexcept {
160
0
    serializeUN<uint64_t, 64>(Num, OutVec, OutVec.end());
161
0
  }
162
163
  template <typename NumType, size_t N>
164
0
  void serializeSN(NumType Num, std::vector<uint8_t> &OutVec) const noexcept {
165
0
    uint8_t Buf[N / 7 + 1];
166
0
    uint32_t Len = 0;
167
0
    bool More = true;
168
0
    while (More) {
169
0
      uint8_t X = static_cast<std::make_unsigned_t<NumType>>(Num) & 0x7FU;
170
0
      Num >>= 7;
171
0
      if ((Num == 0 && !(X & 0x40)) || (Num == -1 && X & 0x40)) {
172
0
        More = false;
173
0
      } else {
174
0
        X |= 0x80;
175
0
      }
176
0
      Buf[Len] = X;
177
0
      Len++;
178
0
    }
179
0
    OutVec.insert(OutVec.end(), Buf, Buf + Len);
180
0
  }
Unexecuted instantiation: void WasmEdge::Loader::Serializer::serializeSN<int, 32ul>(int, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const
Unexecuted instantiation: void WasmEdge::Loader::Serializer::serializeSN<long, 33ul>(long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const
Unexecuted instantiation: void WasmEdge::Loader::Serializer::serializeSN<long, 64ul>(long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const
181
182
0
  void serializeS32(int32_t Num, std::vector<uint8_t> &OutVec) const noexcept {
183
0
    serializeSN<int32_t, 32>(Num, OutVec);
184
0
  }
185
0
  void serializeS33(int64_t Num, std::vector<uint8_t> &OutVec) const noexcept {
186
0
    serializeSN<int64_t, 33>(Num, OutVec);
187
0
  }
188
0
  void serializeS64(int64_t Num, std::vector<uint8_t> &OutVec) const noexcept {
189
0
    serializeSN<int64_t, 64>(Num, OutVec);
190
0
  }
191
192
  template <typename NumType, typename IntType>
193
  typename std::enable_if_t<
194
      sizeof(NumType) == sizeof(IntType) && std::is_integral_v<IntType>, void>
195
0
  serializeFN(NumType Num, std::vector<uint8_t> &OutVec) const noexcept {
196
0
    std::make_unsigned_t<IntType> Buf = 0;
197
0
    std::memcpy(&Buf, &Num, sizeof(NumType));
198
    // Forcing convert into little endian.
199
0
    for (uint32_t I = 0; I < sizeof(NumType); I++) {
200
0
      OutVec.push_back(static_cast<uint8_t>(Buf & 0xFFU));
201
0
      Buf = Buf >> 8;
202
0
    }
203
0
  }
Unexecuted instantiation: _ZNK8WasmEdge6Loader10Serializer11serializeFNIfjEENSt3__19enable_ifIXaaeqstT_stT0_sr3stdE13is_integral_vIS6_EEvE4typeES5_RNS3_6vectorIhNS3_9allocatorIhEEEE
Unexecuted instantiation: _ZNK8WasmEdge6Loader10Serializer11serializeFNIdmEENSt3__19enable_ifIXaaeqstT_stT0_sr3stdE13is_integral_vIS6_EEvE4typeES5_RNS3_6vectorIhNS3_9allocatorIhEEEE
204
205
0
  void serializeF32(float Num, std::vector<uint8_t> &OutVec) const noexcept {
206
0
    serializeFN<float, uint32_t>(Num, OutVec);
207
0
  }
208
0
  void serializeF64(double Num, std::vector<uint8_t> &OutVec) const noexcept {
209
0
    serializeFN<double, uint64_t>(Num, OutVec);
210
0
  }
211
212
  template <typename T, typename L>
213
  Expect<void> serializeSectionContent(const T &Sec, uint8_t Code,
214
                                       std::vector<uint8_t> &OutVec,
215
0
                                       L &&Func) const noexcept {
216
    // Section: section_id + size:u32 + content.
217
0
    auto Content = Sec.getContent();
218
0
    if (Content.size()) {
219
      // Section ID.
220
0
      OutVec.push_back(Code);
221
0
      auto OrgSize = OutVec.size();
222
      // Content: vec(T).
223
0
      serializeU32(static_cast<uint32_t>(Content.size()), OutVec);
224
0
      for (const auto &Item : Content) {
225
0
        EXPECTED_TRY(Func(Item, OutVec));
226
0
      }
227
      // Backward insert the section size.
228
0
      serializeU32(static_cast<uint32_t>(OutVec.size() - OrgSize), OutVec,
229
0
                   std::next(OutVec.begin(), static_cast<ptrdiff_t>(OrgSize)));
230
0
    }
231
0
    return {};
232
0
  }
Unexecuted instantiation: serial_section.cpp:cxx20::expected<void, WasmEdge::ErrCode> WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::ImportSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::ImportSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::ImportSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::ImportSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:cxx20::expected<void, WasmEdge::ErrCode> WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::FunctionSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::FunctionSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::FunctionSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::FunctionSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:cxx20::expected<void, WasmEdge::ErrCode> WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::TableSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::TableSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::TableSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::TableSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:cxx20::expected<void, WasmEdge::ErrCode> WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::MemorySection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::MemorySection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::MemorySection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::MemorySection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:cxx20::expected<void, WasmEdge::ErrCode> WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::GlobalSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::GlobalSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::GlobalSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::GlobalSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:cxx20::expected<void, WasmEdge::ErrCode> WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::ExportSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::ExportSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::ExportSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::ExportSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:cxx20::expected<void, WasmEdge::ErrCode> WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::ElementSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::ElementSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::ElementSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::ElementSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:cxx20::expected<void, WasmEdge::ErrCode> WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::CodeSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::CodeSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::CodeSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::CodeSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:cxx20::expected<void, WasmEdge::ErrCode> WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::DataSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::DataSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::DataSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::DataSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
Unexecuted instantiation: serial_section.cpp:cxx20::expected<void, WasmEdge::ErrCode> WasmEdge::Loader::Serializer::serializeSectionContent<WasmEdge::AST::TagSection, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::TagSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0>(WasmEdge::AST::TagSection const&, unsigned char, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, WasmEdge::Loader::Serializer::serializeSection(WasmEdge::AST::TagSection const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&) const::$_0&&) const
233
  /// @}
234
235
  /// \name Serializer members
236
  /// @{
237
  const Configure &Conf;
238
  /// @}
239
};
240
241
} // namespace Loader
242
} // namespace WasmEdge