/src/WasmEdge/lib/loader/serialize/serial_segment.cpp
Line | Count | Source |
1 | | // SPDX-License-Identifier: Apache-2.0 |
2 | | // SPDX-FileCopyrightText: Copyright The WasmEdge Authors |
3 | | |
4 | | #include "loader/serialize.h" |
5 | | |
6 | | namespace WasmEdge { |
7 | | namespace Loader { |
8 | | |
9 | | // Serialize table segment. See "include/loader/serialize.h". |
10 | | void Serializer::serializeSegment(const AST::TableSegment &Seg, |
11 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
12 | | // Table segment: tabletype |
13 | | // |0x40 + 0x00 + tabletype + expr |
14 | 0 | if (Seg.getExpr().getInstrs().size() > 0) { |
15 | 0 | OutVec.push_back(0x40U); |
16 | 0 | OutVec.push_back(0x00U); |
17 | 0 | serializeType(Seg.getTableType(), OutVec); |
18 | 0 | serializeExpression(Seg.getExpr(), OutVec); |
19 | 0 | } else { |
20 | 0 | serializeType(Seg.getTableType(), OutVec); |
21 | 0 | } |
22 | 0 | } |
23 | | |
24 | | // Serialize global segment. See "include/loader/serialize.h". |
25 | | void Serializer::serializeSegment(const AST::GlobalSegment &Seg, |
26 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
27 | | // Global segment: globaltype + expr. |
28 | 0 | serializeType(Seg.getGlobalType(), OutVec); |
29 | 0 | serializeExpression(Seg.getExpr(), OutVec); |
30 | 0 | } |
31 | | |
32 | | // Serialize element segment. See "include/loader/serialize.h". |
33 | | void Serializer::serializeSegment(const AST::ElementSegment &Seg, |
34 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
35 | | // Element segment: mode:u32 + tableidx:u32 + offset:expr + elemkind:reftype + |
36 | | // vec(u32) + vec(expr) |
37 | | // |
38 | | // Modes 0x00 to 0x04 only express a nullable funcref element type, and 0x00 |
39 | | // and 0x04 also imply table index 0. |
40 | 0 | const bool IsFuncRef = |
41 | 0 | Seg.getRefType() == ValType(TypeCode::RefNull, TypeCode::FuncRef); |
42 | | // Modes 0x00 to 0x03 can only express ref.func initialisers. |
43 | 0 | bool AllRefFunc = true; |
44 | 0 | for (const auto &Expr : Seg.getInitExprs()) { |
45 | 0 | const auto &Instrs = Expr.getInstrs(); |
46 | 0 | if (Instrs.size() != 2 || Instrs[0].getOpCode() != OpCode::Ref__func || |
47 | 0 | Instrs[1].getOpCode() != OpCode::End) { |
48 | 0 | AllRefFunc = false; |
49 | 0 | break; |
50 | 0 | } |
51 | 0 | } |
52 | |
|
53 | 0 | const bool IsPassive = |
54 | 0 | Seg.getMode() == AST::ElementSegment::ElemMode::Passive; |
55 | 0 | const bool IsDeclarative = |
56 | 0 | Seg.getMode() == AST::ElementSegment::ElemMode::Declarative; |
57 | |
|
58 | 0 | uint8_t Mode; |
59 | 0 | if (!IsFuncRef) { |
60 | | // Must use mode 0x05, 0x06 or 0x07: an expression form carrying a reftype. |
61 | 0 | Mode = 0x04U | (IsPassive ? 0x01U : IsDeclarative ? 0x03U : 0x02U); |
62 | 0 | } else { |
63 | 0 | Mode = static_cast<uint8_t>(AllRefFunc ? 0x00U : 0x04U) | |
64 | 0 | (IsPassive ? 0x01U |
65 | 0 | : IsDeclarative ? 0x03U |
66 | 0 | : (Seg.getIdx() != 0 ? 0x02U : 0x00U)); |
67 | 0 | } |
68 | 0 | OutVec.push_back(Mode); |
69 | | |
70 | | // Serialize the table index for the active modes carrying one. |
71 | 0 | if ((Mode & 0x03U) == 0x02U) { |
72 | 0 | serializeU32(Seg.getIdx(), OutVec); |
73 | 0 | } |
74 | | |
75 | | // Serialize the offset expression for the active modes. |
76 | 0 | if (!IsPassive && !IsDeclarative) { |
77 | 0 | serializeExpression(Seg.getExpr(), OutVec); |
78 | 0 | } |
79 | | |
80 | | // Serialize the element kind or the reference type. |
81 | 0 | if (Mode & 0x03U) { |
82 | 0 | if (Mode & 0x04U) { |
83 | 0 | serializeRefType(Seg.getRefType(), OutVec); |
84 | 0 | } else { |
85 | 0 | OutVec.push_back(0x00U); |
86 | 0 | } |
87 | 0 | } |
88 | | |
89 | | // Serialize vec(funcidx) or vec(expr). |
90 | 0 | assuming(Seg.getInitExprs().size() <= UINT32_MAX); |
91 | 0 | serializeU32(static_cast<uint32_t>(Seg.getInitExprs().size()), OutVec); |
92 | 0 | for (const auto &Expr : Seg.getInitExprs()) { |
93 | 0 | if (Mode & 0x04U) { |
94 | 0 | serializeExpression(Expr, OutVec); |
95 | 0 | } else { |
96 | 0 | serializeU32(Expr.getInstrs()[0].getTargetIndex(), OutVec); |
97 | 0 | } |
98 | 0 | } |
99 | 0 | } |
100 | | |
101 | | // Serialize code segment. See "include/loader/serialize.h". |
102 | | void Serializer::serializeSegment(const AST::CodeSegment &Seg, |
103 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
104 | | // Code segment: size:u32 + locals:vec(u32 + valtype) + body:expr. |
105 | 0 | assuming(Seg.getLocals().size() <= UINT32_MAX); |
106 | 0 | auto OrgSize = OutVec.size(); |
107 | 0 | serializeU32(static_cast<uint32_t>(Seg.getLocals().size()), OutVec); |
108 | 0 | for (auto &Locals : Seg.getLocals()) { |
109 | 0 | serializeU32(Locals.first, OutVec); |
110 | 0 | serializeValType(Locals.second, OutVec); |
111 | 0 | } |
112 | 0 | serializeExpression(Seg.getExpr(), OutVec); |
113 | | // Backward insert the code segment size. |
114 | 0 | serializeU32(static_cast<uint32_t>(OutVec.size() - OrgSize), OutVec, |
115 | 0 | std::next(OutVec.begin(), static_cast<ptrdiff_t>(OrgSize))); |
116 | 0 | } |
117 | | |
118 | | // Serialize data segment. See "include/loader/serialize.h". |
119 | | void Serializer::serializeSegment(const AST::DataSegment &Seg, |
120 | 0 | std::vector<uint8_t> &OutVec) const noexcept { |
121 | | // Data segment: mode:u32 + memidx:u32 + expr + vec(byte) |
122 | 0 | switch (Seg.getMode()) { |
123 | 0 | case AST::DataSegment::DataMode::Active: |
124 | 0 | if (Seg.getIdx() != 0) { |
125 | 0 | OutVec.push_back(0x02U); |
126 | 0 | serializeU32(Seg.getIdx(), OutVec); |
127 | 0 | } else { |
128 | 0 | OutVec.push_back(0x00U); |
129 | 0 | } |
130 | 0 | serializeExpression(Seg.getExpr(), OutVec); |
131 | 0 | break; |
132 | 0 | case AST::DataSegment::DataMode::Passive: |
133 | 0 | OutVec.push_back(0x01U); |
134 | 0 | break; |
135 | 0 | default: |
136 | 0 | assumingUnreachable(); |
137 | 0 | } |
138 | | |
139 | 0 | assuming(Seg.getData().size() <= UINT32_MAX); |
140 | 0 | serializeU32(static_cast<uint32_t>(Seg.getData().size()), OutVec); |
141 | 0 | OutVec.insert(OutVec.end(), Seg.getData().begin(), Seg.getData().end()); |
142 | 0 | } |
143 | | |
144 | | } // namespace Loader |
145 | | } // namespace WasmEdge |