/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 |