/src/wabt/src/binary-reader.cc
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2016 WebAssembly Community Group participants |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | |
17 | | #include "wabt/binary-reader.h" |
18 | | |
19 | | #include <cassert> |
20 | | #include <cinttypes> |
21 | | #include <cstdarg> |
22 | | #include <cstdint> |
23 | | #include <cstdio> |
24 | | #include <cstring> |
25 | | #include <stack> |
26 | | #include <vector> |
27 | | |
28 | | #include "wabt/config.h" |
29 | | |
30 | | #include "wabt/binary-reader-logging.h" |
31 | | #include "wabt/binary.h" |
32 | | #include "wabt/leb128.h" |
33 | | #include "wabt/stream.h" |
34 | | #include "wabt/utf8.h" |
35 | | |
36 | | #if HAVE_ALLOCA |
37 | | #include <alloca.h> |
38 | | #endif |
39 | | |
40 | | #define ERROR(...) \ |
41 | 10.7M | do { \ |
42 | 10.7M | PrintError(__VA_ARGS__); \ |
43 | 10.7M | return Result::Error; \ |
44 | 10.7M | } while (0) |
45 | | |
46 | | #define ERROR_IF(expr, ...) \ |
47 | 220M | do { \ |
48 | 268M | if (expr) { \ |
49 | 10.7M | ERROR(__VA_ARGS__); \ |
50 | 10.7M | } \ |
51 | 220M | } while (0) |
52 | | |
53 | 219M | #define ERROR_UNLESS(expr, ...) ERROR_IF(!(expr), __VA_ARGS__) |
54 | | |
55 | | #define ERROR_UNLESS_OPCODE_ENABLED(opcode) \ |
56 | 14.6M | do { \ |
57 | 14.6M | if (!opcode.IsEnabled(options_.features)) { \ |
58 | 871 | return ReportUnexpectedOpcode(opcode); \ |
59 | 871 | } \ |
60 | 14.6M | } while (0) |
61 | | |
62 | | #define CALLBACK0(member) \ |
63 | 23.3M | ERROR_UNLESS(Succeeded(delegate_->member()), #member " callback failed") |
64 | | |
65 | | #define CALLBACK(member, ...) \ |
66 | 61.9M | ERROR_UNLESS(Succeeded(delegate_->member(__VA_ARGS__)), \ |
67 | 61.9M | #member " callback failed") |
68 | | |
69 | | namespace wabt { |
70 | | |
71 | | namespace { |
72 | | |
73 | | class BinaryReader { |
74 | | public: |
75 | | struct ReadModuleOptions { |
76 | | bool stop_on_first_error; |
77 | | }; |
78 | | |
79 | | BinaryReader(const void* data, |
80 | | size_t size, |
81 | | BinaryReaderDelegate* delegate, |
82 | | const ReadBinaryOptions& options); |
83 | | |
84 | | Result ReadModule(const ReadModuleOptions& options); |
85 | | |
86 | | private: |
87 | | template <typename T, T BinaryReader::*member> |
88 | | struct ValueRestoreGuard { |
89 | | explicit ValueRestoreGuard(BinaryReader* this_) |
90 | 18.9M | : this_(this_), previous_value_(this_->*member) {}binary-reader.cc:wabt::(anonymous namespace)::BinaryReader::ValueRestoreGuard<unsigned long, &wabt::(anonymous namespace)::BinaryReader::read_end_>::ValueRestoreGuard(wabt::(anonymous namespace)::BinaryReader*) Line | Count | Source | 90 | 14.0M | : this_(this_), previous_value_(this_->*member) {} |
binary-reader.cc:wabt::(anonymous namespace)::BinaryReader::ValueRestoreGuard<bool, &wabt::(anonymous namespace)::BinaryReader::reading_custom_section_>::ValueRestoreGuard(wabt::(anonymous namespace)::BinaryReader*) Line | Count | Source | 90 | 2.43M | : this_(this_), previous_value_(this_->*member) {} |
binary-reader.cc:wabt::(anonymous namespace)::BinaryReader::ValueRestoreGuard<wabt::BinaryReaderDelegate::State, &wabt::(anonymous namespace)::BinaryReader::state_>::ValueRestoreGuard(wabt::(anonymous namespace)::BinaryReader*) Line | Count | Source | 90 | 2.43M | : this_(this_), previous_value_(this_->*member) {} |
|
91 | 18.9M | ~ValueRestoreGuard() { this_->*member = previous_value_; }binary-reader.cc:wabt::(anonymous namespace)::BinaryReader::ValueRestoreGuard<wabt::BinaryReaderDelegate::State, &wabt::(anonymous namespace)::BinaryReader::state_>::~ValueRestoreGuard() Line | Count | Source | 91 | 2.43M | ~ValueRestoreGuard() { this_->*member = previous_value_; } |
binary-reader.cc:wabt::(anonymous namespace)::BinaryReader::ValueRestoreGuard<bool, &wabt::(anonymous namespace)::BinaryReader::reading_custom_section_>::~ValueRestoreGuard() Line | Count | Source | 91 | 2.43M | ~ValueRestoreGuard() { this_->*member = previous_value_; } |
binary-reader.cc:wabt::(anonymous namespace)::BinaryReader::ValueRestoreGuard<unsigned long, &wabt::(anonymous namespace)::BinaryReader::read_end_>::~ValueRestoreGuard() Line | Count | Source | 91 | 14.0M | ~ValueRestoreGuard() { this_->*member = previous_value_; } |
|
92 | | |
93 | | BinaryReader* this_; |
94 | | T previous_value_; |
95 | | }; |
96 | | |
97 | | struct ReadSectionsOptions { |
98 | | bool stop_on_first_error; |
99 | | }; |
100 | | |
101 | | void WABT_PRINTF_FORMAT(2, 3) PrintError(const char* format, ...); |
102 | | [[nodiscard]] Result ReadOpcode(Opcode* out_value, const char* desc); |
103 | | template <typename T> |
104 | | [[nodiscard]] Result ReadT(T* out_value, |
105 | | const char* type_name, |
106 | | const char* desc); |
107 | | [[nodiscard]] Result ReadU8(uint8_t* out_value, const char* desc); |
108 | | [[nodiscard]] Result ReadU16(uint16_t* out_value, const char* desc); |
109 | | [[nodiscard]] Result ReadU32(uint32_t* out_value, const char* desc); |
110 | | [[nodiscard]] Result ReadF32(uint32_t* out_value, const char* desc); |
111 | | [[nodiscard]] Result ReadF64(uint64_t* out_value, const char* desc); |
112 | | [[nodiscard]] Result ReadV128(v128* out_value, const char* desc); |
113 | | [[nodiscard]] Result ReadU32Leb128(uint32_t* out_value, const char* desc); |
114 | | [[nodiscard]] Result ReadU64Leb128(uint64_t* out_value, const char* desc); |
115 | | [[nodiscard]] Result ReadS32Leb128(uint32_t* out_value, const char* desc); |
116 | | [[nodiscard]] Result ReadS64Leb128(uint64_t* out_value, const char* desc); |
117 | | [[nodiscard]] Result ReadType(Type* out_value, const char* desc); |
118 | | [[nodiscard]] Result ReadRefType(Type* out_value, const char* desc); |
119 | | [[nodiscard]] Result ReadExternalKind(ExternalKind* out_value, |
120 | | const char* desc); |
121 | | [[nodiscard]] Result ReadStr(std::string_view* out_str, const char* desc); |
122 | | [[nodiscard]] Result ReadBytes(const void** out_data, |
123 | | Address* out_data_size, |
124 | | const char* desc); |
125 | | [[nodiscard]] Result ReadBytesWithSize(const void** out_data, |
126 | | Offset size, |
127 | | const char* desc); |
128 | | [[nodiscard]] Result ReadIndex(Index* index, const char* desc); |
129 | | [[nodiscard]] Result ReadOffset(Offset* offset, const char* desc); |
130 | | [[nodiscard]] Result ReadAlignment(Address* align_log2, const char* desc); |
131 | | [[nodiscard]] Result CheckAlignment(Address* align_log2, const char* desc); |
132 | | [[nodiscard]] Result TakeHasMemidx(Address* align_log2, bool* has_memidx); |
133 | | [[nodiscard]] Result ReadMemidx(Index* memidx, const char* desc); |
134 | | [[nodiscard]] Result ReadMemLocation(Address* alignment_log2, |
135 | | Index* memidx, |
136 | | Address* offset, |
137 | | const char* desc_align, |
138 | | const char* desc_memidx, |
139 | | const char* desc_offset, |
140 | | uint8_t* lane_val = nullptr); |
141 | | [[nodiscard]] Result CallbackMemLocation(const Address* alignment_log2, |
142 | | const Index* memidx, |
143 | | const Address* offset, |
144 | | const uint8_t* lane_val = nullptr); |
145 | | [[nodiscard]] Result ReadCount(Index* index, const char* desc); |
146 | | [[nodiscard]] Result ReadField(TypeMut* out_value); |
147 | | |
148 | | bool IsConcreteReferenceType(Type::Enum); |
149 | | bool IsConcreteType(Type); |
150 | | bool IsBlockType(Type); |
151 | | |
152 | | Index NumTotalFuncs(); |
153 | | |
154 | | [[nodiscard]] Result ReadInitExpr(Index index); |
155 | | [[nodiscard]] Result ReadTable(Limits* out_elem_limits); |
156 | | [[nodiscard]] Result ReadMemory(Limits* out_page_limits, |
157 | | uint32_t* out_page_size); |
158 | | [[nodiscard]] Result ReadGlobalHeader(Type* out_type, bool* out_mutable); |
159 | | [[nodiscard]] Result ReadTagType(Index* out_sig_index); |
160 | | [[nodiscard]] Result ReadAddress(Address* out_value, |
161 | | Index memory, |
162 | | const char* desc); |
163 | | [[nodiscard]] Result ReadFunctionBody(Offset end_offset); |
164 | | // ReadInstructions reads until end_offset or the nesting depth reaches zero. |
165 | | [[nodiscard]] Result ReadInstructions(Offset end_offset, const char* context); |
166 | | [[nodiscard]] Result ReadNameSection(Offset section_size); |
167 | | [[nodiscard]] Result ReadRelocSection(Offset section_size); |
168 | | [[nodiscard]] Result ReadDylinkSection(Offset section_size); |
169 | | [[nodiscard]] Result ReadGenericCustomSection(std::string_view name, |
170 | | Offset section_size); |
171 | | [[nodiscard]] Result ReadDylink0Section(Offset section_size); |
172 | | [[nodiscard]] Result ReadTargetFeaturesSections(Offset section_size); |
173 | | [[nodiscard]] Result ReadLinkingSection(Offset section_size); |
174 | | [[nodiscard]] Result ReadCodeMetadataSection(std::string_view name, |
175 | | Offset section_size); |
176 | | [[nodiscard]] Result ReadCustomSection(Index section_index, |
177 | | Offset section_size); |
178 | | [[nodiscard]] Result ReadTypeSection(Offset section_size); |
179 | | [[nodiscard]] Result ReadImportSection(Offset section_size); |
180 | | [[nodiscard]] Result ReadFunctionSection(Offset section_size); |
181 | | [[nodiscard]] Result ReadTableSection(Offset section_size); |
182 | | [[nodiscard]] Result ReadMemorySection(Offset section_size); |
183 | | [[nodiscard]] Result ReadGlobalSection(Offset section_size); |
184 | | [[nodiscard]] Result ReadExportSection(Offset section_size); |
185 | | [[nodiscard]] Result ReadStartSection(Offset section_size); |
186 | | [[nodiscard]] Result ReadElemSection(Offset section_size); |
187 | | [[nodiscard]] Result ReadCodeSection(Offset section_size); |
188 | | [[nodiscard]] Result ReadDataSection(Offset section_size); |
189 | | [[nodiscard]] Result ReadDataCountSection(Offset section_size); |
190 | | [[nodiscard]] Result ReadTagSection(Offset section_size); |
191 | | [[nodiscard]] Result ReadSections(const ReadSectionsOptions& options); |
192 | | Result ReportUnexpectedOpcode(Opcode opcode, const char* message = nullptr); |
193 | | |
194 | | size_t read_end_ = 0; // Either the section end or data_size. |
195 | | BinaryReaderDelegate::State state_; |
196 | | BinaryReaderLogging logging_delegate_; |
197 | | BinaryReaderDelegate* delegate_ = nullptr; |
198 | | TypeVector param_types_; |
199 | | TypeVector result_types_; |
200 | | TypeMutVector fields_; |
201 | | std::vector<Index> target_depths_; |
202 | | CatchClauseVector catches_; |
203 | | const ReadBinaryOptions& options_; |
204 | | BinarySection last_known_section_ = BinarySection::Invalid; |
205 | | bool did_read_names_section_ = false; |
206 | | bool reading_custom_section_ = false; |
207 | | Index num_func_imports_ = 0; |
208 | | Index num_table_imports_ = 0; |
209 | | Index num_memory_imports_ = 0; |
210 | | Index num_global_imports_ = 0; |
211 | | Index num_tag_imports_ = 0; |
212 | | Index num_function_signatures_ = 0; |
213 | | Index num_function_bodies_ = 0; |
214 | | Index num_data_segments_ = 0; |
215 | | Index data_count_ = kInvalidIndex; |
216 | | |
217 | | using ReadEndRestoreGuard = |
218 | | ValueRestoreGuard<size_t, &BinaryReader::read_end_>; |
219 | | }; |
220 | | |
221 | | BinaryReader::BinaryReader(const void* data, |
222 | | size_t size, |
223 | | BinaryReaderDelegate* delegate, |
224 | | const ReadBinaryOptions& options) |
225 | 93.4k | : read_end_(size), |
226 | 93.4k | state_(static_cast<const uint8_t*>(data), size), |
227 | 93.4k | logging_delegate_(options.log_stream, delegate), |
228 | 93.4k | delegate_(options.log_stream ? &logging_delegate_ : delegate), |
229 | 93.4k | options_(options), |
230 | 93.4k | last_known_section_(BinarySection::Invalid) { |
231 | 93.4k | delegate->OnSetState(&state_); |
232 | 93.4k | } |
233 | | |
234 | | void WABT_PRINTF_FORMAT(2, 3) BinaryReader::PrintError(const char* format, |
235 | 11.5M | ...) { |
236 | 11.5M | ErrorLevel error_level = |
237 | 11.5M | reading_custom_section_ && !options_.fail_on_custom_section_error |
238 | 11.5M | ? ErrorLevel::Warning |
239 | 11.5M | : ErrorLevel::Error; |
240 | | |
241 | 11.5M | WABT_SNPRINTF_ALLOCA(buffer, length, format); |
242 | 11.5M | Error error(error_level, Location(state_.offset), buffer); |
243 | 11.5M | bool handled = delegate_->OnError(error); |
244 | | |
245 | 11.5M | if (!handled) { |
246 | | // Not great to just print, but we don't want to eat the error either. |
247 | 1.73M | fprintf(stderr, "%07" PRIzx ": %s: %s\n", state_.offset, |
248 | 1.73M | GetErrorLevelName(error_level), buffer); |
249 | 1.73M | } |
250 | 11.5M | } |
251 | | |
252 | 5.47k | Result BinaryReader::ReportUnexpectedOpcode(Opcode opcode, const char* where) { |
253 | 5.47k | std::string message = "unexpected opcode"; |
254 | 5.47k | if (where) { |
255 | 0 | message += ' '; |
256 | 0 | message += where; |
257 | 0 | } |
258 | | |
259 | 5.47k | message += ":"; |
260 | | |
261 | 5.47k | std::vector<uint8_t> bytes = opcode.GetBytes(); |
262 | 5.47k | assert(bytes.size() > 0); |
263 | | |
264 | 7.63k | for (uint8_t byte : bytes) { |
265 | 7.63k | message += StringPrintf(" 0x%x", byte); |
266 | 7.63k | } |
267 | | |
268 | 5.47k | PrintError("%s", message.c_str()); |
269 | 5.47k | return Result::Error; |
270 | 5.47k | } |
271 | | |
272 | 14.6M | Result BinaryReader::ReadOpcode(Opcode* out_value, const char* desc) { |
273 | 14.6M | uint8_t value = 0; |
274 | 14.6M | CHECK_RESULT(ReadU8(&value, desc)); |
275 | | |
276 | 14.6M | if (Opcode::IsPrefixByte(value)) { |
277 | 755k | uint32_t code; |
278 | 755k | CHECK_RESULT(ReadU32Leb128(&code, desc)); |
279 | 754k | *out_value = Opcode::FromCode(value, code); |
280 | 13.8M | } else { |
281 | 13.8M | *out_value = Opcode::FromCode(value); |
282 | 13.8M | } |
283 | 14.6M | return Result::Ok; |
284 | 14.6M | } |
285 | | |
286 | | template <typename T> |
287 | | Result BinaryReader::ReadT(T* out_value, |
288 | | const char* type_name, |
289 | 30.4M | const char* desc) { |
290 | 30.4M | if (state_.offset + sizeof(T) > read_end_) { |
291 | 18.6k | PrintError("unable to read %s: %s", type_name, desc); |
292 | 18.6k | return Result::Error; |
293 | 18.6k | } |
294 | | #if WABT_BIG_ENDIAN |
295 | | uint8_t tmp[sizeof(T)]; |
296 | | memcpy(tmp, state_.data + state_.offset, sizeof(tmp)); |
297 | | SwapBytesSized(tmp, sizeof(tmp)); |
298 | | memcpy(out_value, tmp, sizeof(T)); |
299 | | #else |
300 | 30.4M | memcpy(out_value, state_.data + state_.offset, sizeof(T)); |
301 | 30.4M | #endif |
302 | 30.4M | state_.offset += sizeof(T); |
303 | 30.4M | return Result::Ok; |
304 | 30.4M | } binary-reader.cc:wabt::Result wabt::(anonymous namespace)::BinaryReader::ReadT<unsigned int>(unsigned int*, char const*, char const*) Line | Count | Source | 289 | 153k | const char* desc) { | 290 | 153k | if (state_.offset + sizeof(T) > read_end_) { | 291 | 192 | PrintError("unable to read %s: %s", type_name, desc); | 292 | 192 | return Result::Error; | 293 | 192 | } | 294 | | #if WABT_BIG_ENDIAN | 295 | | uint8_t tmp[sizeof(T)]; | 296 | | memcpy(tmp, state_.data + state_.offset, sizeof(tmp)); | 297 | | SwapBytesSized(tmp, sizeof(tmp)); | 298 | | memcpy(out_value, tmp, sizeof(T)); | 299 | | #else | 300 | 153k | memcpy(out_value, state_.data + state_.offset, sizeof(T)); | 301 | 153k | #endif | 302 | 153k | state_.offset += sizeof(T); | 303 | 153k | return Result::Ok; | 304 | 153k | } |
binary-reader.cc:wabt::Result wabt::(anonymous namespace)::BinaryReader::ReadT<unsigned short>(unsigned short*, char const*, char const*) Line | Count | Source | 289 | 185k | const char* desc) { | 290 | 185k | if (state_.offset + sizeof(T) > read_end_) { | 291 | 28 | PrintError("unable to read %s: %s", type_name, desc); | 292 | 28 | return Result::Error; | 293 | 28 | } | 294 | | #if WABT_BIG_ENDIAN | 295 | | uint8_t tmp[sizeof(T)]; | 296 | | memcpy(tmp, state_.data + state_.offset, sizeof(tmp)); | 297 | | SwapBytesSized(tmp, sizeof(tmp)); | 298 | | memcpy(out_value, tmp, sizeof(T)); | 299 | | #else | 300 | 185k | memcpy(out_value, state_.data + state_.offset, sizeof(T)); | 301 | 185k | #endif | 302 | 185k | state_.offset += sizeof(T); | 303 | 185k | return Result::Ok; | 304 | 185k | } |
binary-reader.cc:wabt::Result wabt::(anonymous namespace)::BinaryReader::ReadT<unsigned char>(unsigned char*, char const*, char const*) Line | Count | Source | 289 | 30.0M | const char* desc) { | 290 | 30.0M | if (state_.offset + sizeof(T) > read_end_) { | 291 | 18.1k | PrintError("unable to read %s: %s", type_name, desc); | 292 | 18.1k | return Result::Error; | 293 | 18.1k | } | 294 | | #if WABT_BIG_ENDIAN | 295 | | uint8_t tmp[sizeof(T)]; | 296 | | memcpy(tmp, state_.data + state_.offset, sizeof(tmp)); | 297 | | SwapBytesSized(tmp, sizeof(tmp)); | 298 | | memcpy(out_value, tmp, sizeof(T)); | 299 | | #else | 300 | 30.0M | memcpy(out_value, state_.data + state_.offset, sizeof(T)); | 301 | 30.0M | #endif | 302 | 30.0M | state_.offset += sizeof(T); | 303 | 30.0M | return Result::Ok; | 304 | 30.0M | } |
binary-reader.cc:wabt::Result wabt::(anonymous namespace)::BinaryReader::ReadT<unsigned long>(unsigned long*, char const*, char const*) Line | Count | Source | 289 | 26.6k | const char* desc) { | 290 | 26.6k | if (state_.offset + sizeof(T) > read_end_) { | 291 | 208 | PrintError("unable to read %s: %s", type_name, desc); | 292 | 208 | return Result::Error; | 293 | 208 | } | 294 | | #if WABT_BIG_ENDIAN | 295 | | uint8_t tmp[sizeof(T)]; | 296 | | memcpy(tmp, state_.data + state_.offset, sizeof(tmp)); | 297 | | SwapBytesSized(tmp, sizeof(tmp)); | 298 | | memcpy(out_value, tmp, sizeof(T)); | 299 | | #else | 300 | 26.4k | memcpy(out_value, state_.data + state_.offset, sizeof(T)); | 301 | 26.4k | #endif | 302 | 26.4k | state_.offset += sizeof(T); | 303 | 26.4k | return Result::Ok; | 304 | 26.6k | } |
binary-reader.cc:wabt::Result wabt::(anonymous namespace)::BinaryReader::ReadT<v128>(v128*, char const*, char const*) Line | Count | Source | 289 | 24.4k | const char* desc) { | 290 | 24.4k | if (state_.offset + sizeof(T) > read_end_) { | 291 | 107 | PrintError("unable to read %s: %s", type_name, desc); | 292 | 107 | return Result::Error; | 293 | 107 | } | 294 | | #if WABT_BIG_ENDIAN | 295 | | uint8_t tmp[sizeof(T)]; | 296 | | memcpy(tmp, state_.data + state_.offset, sizeof(tmp)); | 297 | | SwapBytesSized(tmp, sizeof(tmp)); | 298 | | memcpy(out_value, tmp, sizeof(T)); | 299 | | #else | 300 | 24.3k | memcpy(out_value, state_.data + state_.offset, sizeof(T)); | 301 | 24.3k | #endif | 302 | 24.3k | state_.offset += sizeof(T); | 303 | 24.3k | return Result::Ok; | 304 | 24.4k | } |
|
305 | | |
306 | 30.0M | Result BinaryReader::ReadU8(uint8_t* out_value, const char* desc) { |
307 | 30.0M | return ReadT(out_value, "uint8_t", desc); |
308 | 30.0M | } |
309 | | |
310 | 185k | Result BinaryReader::ReadU16(uint16_t* out_value, const char* desc) { |
311 | 185k | return ReadT(out_value, "uint16_t", desc); |
312 | 185k | } |
313 | | |
314 | 93.4k | Result BinaryReader::ReadU32(uint32_t* out_value, const char* desc) { |
315 | 93.4k | return ReadT(out_value, "uint32_t", desc); |
316 | 93.4k | } |
317 | | |
318 | 59.9k | Result BinaryReader::ReadF32(uint32_t* out_value, const char* desc) { |
319 | 59.9k | return ReadT(out_value, "float", desc); |
320 | 59.9k | } |
321 | | |
322 | 26.6k | Result BinaryReader::ReadF64(uint64_t* out_value, const char* desc) { |
323 | 26.6k | return ReadT(out_value, "double", desc); |
324 | 26.6k | } |
325 | | |
326 | 24.4k | Result BinaryReader::ReadV128(v128* out_value, const char* desc) { |
327 | 24.4k | return ReadT(out_value, "v128", desc); |
328 | 24.4k | } |
329 | | |
330 | 64.9M | Result BinaryReader::ReadU32Leb128(uint32_t* out_value, const char* desc) { |
331 | 64.9M | const uint8_t* p = state_.data + state_.offset; |
332 | 64.9M | const uint8_t* end = state_.data + read_end_; |
333 | 64.9M | size_t bytes_read = wabt::ReadU32Leb128(p, end, out_value); |
334 | 64.9M | ERROR_UNLESS(bytes_read > 0, "unable to read u32 leb128: %s", desc); |
335 | 54.7M | state_.offset += bytes_read; |
336 | 54.7M | return Result::Ok; |
337 | 64.9M | } |
338 | | |
339 | 219k | Result BinaryReader::ReadU64Leb128(uint64_t* out_value, const char* desc) { |
340 | 219k | const uint8_t* p = state_.data + state_.offset; |
341 | 219k | const uint8_t* end = state_.data + read_end_; |
342 | 219k | size_t bytes_read = wabt::ReadU64Leb128(p, end, out_value); |
343 | 219k | ERROR_UNLESS(bytes_read > 0, "unable to read u64 leb128: %s", desc); |
344 | 218k | state_.offset += bytes_read; |
345 | 218k | return Result::Ok; |
346 | 219k | } |
347 | | |
348 | 2.91M | Result BinaryReader::ReadS32Leb128(uint32_t* out_value, const char* desc) { |
349 | 2.91M | const uint8_t* p = state_.data + state_.offset; |
350 | 2.91M | const uint8_t* end = state_.data + read_end_; |
351 | 2.91M | size_t bytes_read = wabt::ReadS32Leb128(p, end, out_value); |
352 | 2.91M | ERROR_UNLESS(bytes_read > 0, "unable to read i32 leb128: %s", desc); |
353 | 2.90M | state_.offset += bytes_read; |
354 | 2.90M | return Result::Ok; |
355 | 2.91M | } |
356 | | |
357 | 116k | Result BinaryReader::ReadS64Leb128(uint64_t* out_value, const char* desc) { |
358 | 116k | const uint8_t* p = state_.data + state_.offset; |
359 | 116k | const uint8_t* end = state_.data + read_end_; |
360 | 116k | size_t bytes_read = wabt::ReadS64Leb128(p, end, out_value); |
361 | 116k | ERROR_UNLESS(bytes_read > 0, "unable to read i64 leb128: %s", desc); |
362 | 115k | state_.offset += bytes_read; |
363 | 115k | return Result::Ok; |
364 | 116k | } |
365 | | |
366 | 2.80M | Result BinaryReader::ReadType(Type* out_value, const char* desc) { |
367 | 2.80M | uint32_t type = 0; |
368 | 2.80M | CHECK_RESULT(ReadS32Leb128(&type, desc)); |
369 | 2.80M | if (options_.features.reference_types_enabled() && |
370 | 2.80M | Type::EnumIsReferenceWithIndex(static_cast<Type::Enum>(type))) { |
371 | 12.0k | uint64_t heap_type = 0; |
372 | 12.0k | CHECK_RESULT(ReadS64Leb128(&heap_type, desc)); |
373 | | |
374 | 11.7k | if (static_cast<int64_t>(heap_type) < 0 || |
375 | 9.78k | static_cast<int64_t>(heap_type) >= kInvalidIndex) { |
376 | 2.84k | Type::Enum heap_type_code = static_cast<Type::Enum>(heap_type); |
377 | 2.84k | ERROR_UNLESS( |
378 | 2.02k | heap_type_code == Type::FuncRef || heap_type_code == Type::ExternRef, |
379 | 2.02k | "Reference type is limited to func and extern: %s", desc); |
380 | 2.02k | type = (static_cast<Type::Enum>(type) == Type::Ref) |
381 | 2.02k | ? Type::ReferenceNonNull |
382 | 2.02k | : Type::ReferenceOrNull; |
383 | 2.02k | *out_value = Type(heap_type_code, type); |
384 | 8.94k | } else { |
385 | 8.94k | *out_value = |
386 | 8.94k | Type(static_cast<Type::Enum>(type), static_cast<Index>(heap_type)); |
387 | 8.94k | } |
388 | 2.79M | } else { |
389 | 2.79M | *out_value = static_cast<Type>(type); |
390 | 2.79M | } |
391 | 2.80M | return Result::Ok; |
392 | 2.80M | } |
393 | | |
394 | 156k | Result BinaryReader::ReadRefType(Type* out_value, const char* desc) { |
395 | 156k | CHECK_RESULT(ReadType(out_value, desc)); |
396 | 156k | ERROR_UNLESS(out_value->IsRef(), "%s must be a reference type", desc); |
397 | 155k | return Result::Ok; |
398 | 156k | } |
399 | | |
400 | | Result BinaryReader::ReadExternalKind(ExternalKind* out_value, |
401 | 147k | const char* desc) { |
402 | 147k | uint8_t value = 0; |
403 | 147k | CHECK_RESULT(ReadU8(&value, desc)); |
404 | 147k | ERROR_UNLESS(value < kExternalKindCount, "invalid export external kind: %d", |
405 | 146k | value); |
406 | 146k | *out_value = static_cast<ExternalKind>(value); |
407 | 146k | return Result::Ok; |
408 | 147k | } |
409 | | |
410 | 16.5M | Result BinaryReader::ReadStr(std::string_view* out_str, const char* desc) { |
411 | 16.5M | uint32_t str_len = 0; |
412 | 16.5M | CHECK_RESULT(ReadU32Leb128(&str_len, "string length")); |
413 | | |
414 | 6.57M | ERROR_UNLESS(state_.offset + str_len <= read_end_, |
415 | 6.49M | "unable to read string: %s", desc); |
416 | | |
417 | 6.49M | *out_str = std::string_view( |
418 | 6.49M | reinterpret_cast<const char*>(state_.data) + state_.offset, str_len); |
419 | 6.49M | state_.offset += str_len; |
420 | | |
421 | 6.49M | ERROR_UNLESS(IsValidUtf8(out_str->data(), out_str->length()), |
422 | 6.46M | "invalid utf-8 encoding: %s", desc); |
423 | 6.46M | return Result::Ok; |
424 | 6.49M | } |
425 | | |
426 | | Result BinaryReader::ReadBytes(const void** out_data, |
427 | | Address* out_data_size, |
428 | 369k | const char* desc) { |
429 | 369k | uint32_t data_size = 0; |
430 | 369k | CHECK_RESULT(ReadU32Leb128(&data_size, "data size")); |
431 | 367k | CHECK_RESULT(ReadBytesWithSize(out_data, data_size, desc)); |
432 | 358k | *out_data_size = data_size; |
433 | 358k | return Result::Ok; |
434 | 367k | } |
435 | | |
436 | | Result BinaryReader::ReadBytesWithSize(const void** out_data, |
437 | | Offset size, |
438 | 2.79M | const char* desc) { |
439 | 2.79M | ERROR_UNLESS(state_.offset + size <= read_end_, "unable to read data: %s", |
440 | 2.79M | desc); |
441 | | |
442 | 2.79M | *out_data = static_cast<const uint8_t*>(state_.data) + state_.offset; |
443 | 2.79M | state_.offset += size; |
444 | 2.79M | return Result::Ok; |
445 | 2.79M | } |
446 | | |
447 | 27.5M | Result BinaryReader::ReadIndex(Index* index, const char* desc) { |
448 | 27.5M | uint32_t value; |
449 | 27.5M | CHECK_RESULT(ReadU32Leb128(&value, desc)); |
450 | 27.5M | *index = value; |
451 | 27.5M | return Result::Ok; |
452 | 27.5M | } |
453 | | |
454 | 14.6M | Result BinaryReader::ReadOffset(Offset* offset, const char* desc) { |
455 | 14.6M | uint32_t value; |
456 | 14.6M | CHECK_RESULT(ReadU32Leb128(&value, desc)); |
457 | 14.5M | *offset = value; |
458 | 14.5M | return Result::Ok; |
459 | 14.6M | } |
460 | | |
461 | 312k | Result BinaryReader::ReadAlignment(Address* alignment_log2, const char* desc) { |
462 | 312k | uint32_t value; |
463 | 312k | CHECK_RESULT(ReadU32Leb128(&value, desc)); |
464 | 309k | *alignment_log2 = value; |
465 | 309k | return Result::Ok; |
466 | 312k | } |
467 | | |
468 | 309k | Result BinaryReader::CheckAlignment(Address* align_log2, const char* desc) { |
469 | 309k | uint32_t value = *align_log2; |
470 | 309k | if (value >= 32) { |
471 | 3.45k | PrintError("invalid %s: %" PRIu32, desc, value); |
472 | 3.45k | return Result::Error; |
473 | 3.45k | } |
474 | 306k | return Result::Ok; |
475 | 309k | } |
476 | | |
477 | 281k | Result BinaryReader::TakeHasMemidx(Address* align_log2, bool* has_memidx) { |
478 | | // extract the has_memidx flag |
479 | 281k | *has_memidx = (*align_log2 >> 6) & 1; |
480 | | // then clear it |
481 | 281k | *align_log2 &= ~(1 << 6); |
482 | 281k | return Result::Ok; |
483 | 281k | } |
484 | | |
485 | 53.1k | Result BinaryReader::ReadMemidx(Index* memidx, const char* desc) { |
486 | 53.1k | CHECK_RESULT(ReadIndex(memidx, desc)); |
487 | 52.8k | return Result::Ok; |
488 | 53.1k | } |
489 | | |
490 | | Result BinaryReader::ReadMemLocation(Address* alignment_log2, |
491 | | Index* memidx, |
492 | | Address* offset, |
493 | | const char* desc_align, |
494 | | const char* desc_memidx, |
495 | | const char* desc_offset, |
496 | 283k | uint8_t* lane_val) { |
497 | 283k | bool has_memidx = false; |
498 | 283k | CHECK_RESULT(ReadAlignment(alignment_log2, desc_align)); |
499 | 281k | CHECK_RESULT(TakeHasMemidx(alignment_log2, &has_memidx)); |
500 | 281k | CHECK_RESULT(CheckAlignment(alignment_log2, desc_align)); |
501 | 279k | *memidx = 0; |
502 | 279k | if (has_memidx) { |
503 | 19.1k | ERROR_IF(!options_.features.multi_memory_enabled(), |
504 | 19.1k | "multi_memory not allowed"); |
505 | 19.0k | CHECK_RESULT(ReadMemidx(memidx, desc_memidx)); |
506 | 19.0k | } |
507 | 279k | CHECK_RESULT(ReadAddress(offset, 0, desc_offset)); |
508 | | |
509 | 278k | if (lane_val) { |
510 | 22.2k | CHECK_RESULT(ReadU8(lane_val, "Lane idx")); |
511 | 22.2k | } |
512 | | |
513 | 278k | return Result::Ok; |
514 | 278k | } |
515 | | |
516 | | Result BinaryReader::CallbackMemLocation(const Address* alignment_log2, |
517 | | const Index* memidx, |
518 | | const Address* offset, |
519 | 278k | const uint8_t* lane_val) { |
520 | 278k | if (lane_val) { |
521 | 22.1k | if (*memidx) { |
522 | 2.42k | CALLBACK(OnOpcodeUint32Uint32Uint32Uint32, *alignment_log2, *memidx, |
523 | 2.42k | *offset, *lane_val); |
524 | 19.7k | } else { |
525 | 19.7k | CALLBACK(OnOpcodeUint32Uint32Uint32, *alignment_log2, *offset, *lane_val); |
526 | 19.7k | } |
527 | 256k | } else { |
528 | 256k | if (*memidx) { |
529 | 14.7k | CALLBACK(OnOpcodeUint32Uint32Uint32, *alignment_log2, *memidx, *offset); |
530 | 241k | } else { |
531 | 241k | CALLBACK(OnOpcodeUint32Uint32, *alignment_log2, *offset); |
532 | 241k | } |
533 | 256k | } |
534 | | |
535 | 278k | return Result::Ok; |
536 | 278k | } |
537 | | |
538 | 2.09M | Result BinaryReader::ReadCount(Index* count, const char* desc) { |
539 | 2.09M | CHECK_RESULT(ReadIndex(count, desc)); |
540 | | |
541 | | // This check assumes that each item follows in this section, and takes at |
542 | | // least 1 byte. It's possible that this check passes but reading fails |
543 | | // later. It is still useful to check here, though, because it early-outs |
544 | | // when an erroneous large count is used, before allocating memory for it. |
545 | 2.07M | size_t section_remaining = read_end_ - state_.offset; |
546 | 2.07M | if (*count > section_remaining) { |
547 | 30.8k | PrintError("invalid %s %" PRIindex ", only %" PRIzd |
548 | 30.8k | " bytes left in section", |
549 | 30.8k | desc, *count, section_remaining); |
550 | 30.8k | return Result::Error; |
551 | 30.8k | } |
552 | 2.04M | return Result::Ok; |
553 | 2.07M | } |
554 | | |
555 | 2.37k | Result BinaryReader::ReadField(TypeMut* out_value) { |
556 | | // TODO: Reuse for global header too? |
557 | 2.37k | Type field_type; |
558 | 2.37k | CHECK_RESULT(ReadType(&field_type, "field type")); |
559 | 2.34k | ERROR_UNLESS(IsConcreteType(field_type), |
560 | 1.93k | "expected valid field type (got " PRItypecode ")", |
561 | 1.93k | WABT_PRINTF_TYPE_CODE(field_type)); |
562 | | |
563 | 1.93k | uint8_t mutable_ = 0; |
564 | 1.93k | CHECK_RESULT(ReadU8(&mutable_, "field mutability")); |
565 | 1.87k | ERROR_UNLESS(mutable_ <= 1, "field mutability must be 0 or 1"); |
566 | 1.79k | out_value->type = field_type; |
567 | 1.79k | out_value->mutable_ = mutable_; |
568 | 1.79k | return Result::Ok; |
569 | 1.87k | } |
570 | | |
571 | 2.28M | bool BinaryReader::IsConcreteReferenceType(Type::Enum type) { |
572 | 2.28M | switch (type) { |
573 | 27.7k | case Type::FuncRef: |
574 | 56.5k | case Type::ExternRef: |
575 | 56.5k | return options_.features.reference_types_enabled(); |
576 | | |
577 | 6.03k | case Type::ExnRef: |
578 | 6.03k | return options_.features.exceptions_enabled(); |
579 | | |
580 | 2.22M | default: |
581 | 2.22M | return false; |
582 | 2.28M | } |
583 | 2.28M | } |
584 | | |
585 | 2.63M | bool BinaryReader::IsConcreteType(Type type) { |
586 | 2.63M | switch (type) { |
587 | 43.0k | case Type::I32: |
588 | 68.0k | case Type::I64: |
589 | 96.6k | case Type::F32: |
590 | 334k | case Type::F64: |
591 | 334k | return true; |
592 | | |
593 | 19.9k | case Type::V128: |
594 | 19.9k | return options_.features.simd_enabled(); |
595 | | |
596 | 2.38k | case Type::Reference: |
597 | 3.82k | case Type::Ref: |
598 | 5.63k | case Type::RefNull: |
599 | 5.63k | return options_.features.function_references_enabled(); |
600 | | |
601 | 2.27M | default: |
602 | 2.27M | return IsConcreteReferenceType(type); |
603 | 2.63M | } |
604 | 2.63M | } |
605 | | |
606 | 2.26M | bool BinaryReader::IsBlockType(Type type) { |
607 | 2.26M | if (IsConcreteType(type) || type == Type::Void) { |
608 | 72.0k | return true; |
609 | 72.0k | } |
610 | | |
611 | 2.19M | if (!(options_.features.multi_value_enabled() && type.IsIndex())) { |
612 | 899 | return false; |
613 | 899 | } |
614 | | |
615 | 2.19M | return true; |
616 | 2.19M | } |
617 | | |
618 | 1.42M | Index BinaryReader::NumTotalFuncs() { |
619 | 1.42M | return num_func_imports_ + num_function_signatures_; |
620 | 1.42M | } |
621 | | |
622 | 116k | Result BinaryReader::ReadInitExpr(Index index) { |
623 | 116k | CHECK_RESULT(ReadInstructions(read_end_, "init expression")); |
624 | 116k | assert(state_.offset <= read_end_); |
625 | 83.6k | return Result::Ok; |
626 | 83.6k | } |
627 | | |
628 | 153k | Result BinaryReader::ReadTable(Limits* out_elem_limits) { |
629 | 153k | uint8_t flags; |
630 | 153k | uint32_t initial; |
631 | 153k | uint32_t max = 0; |
632 | 153k | CHECK_RESULT(ReadU8(&flags, "table flags")); |
633 | 153k | bool has_max = flags & WABT_BINARY_LIMITS_HAS_MAX_FLAG; |
634 | 153k | bool is_shared = flags & WABT_BINARY_LIMITS_IS_SHARED_FLAG; |
635 | 153k | bool is_64 = flags & WABT_BINARY_LIMITS_IS_64_FLAG; |
636 | 153k | const uint8_t unknown_flags = flags & ~WABT_BINARY_LIMITS_ALL_TABLE_FLAGS; |
637 | 153k | ERROR_IF(is_shared, "tables may not be shared"); |
638 | 153k | ERROR_IF(is_64 && !options_.features.memory64_enabled(), |
639 | 153k | "memory64 not allowed"); |
640 | 153k | ERROR_UNLESS(unknown_flags == 0, "malformed table limits flag: %d", flags); |
641 | 153k | CHECK_RESULT(ReadU32Leb128(&initial, "table initial elem count")); |
642 | 153k | if (has_max) { |
643 | 122k | CHECK_RESULT(ReadU32Leb128(&max, "table max elem count")); |
644 | 122k | } |
645 | | |
646 | 153k | out_elem_limits->has_max = has_max; |
647 | 153k | out_elem_limits->is_64 = is_64; |
648 | 153k | out_elem_limits->initial = initial; |
649 | 153k | out_elem_limits->max = max; |
650 | 153k | return Result::Ok; |
651 | 153k | } |
652 | | |
653 | | Result BinaryReader::ReadMemory(Limits* out_page_limits, |
654 | 187k | uint32_t* out_page_size) { |
655 | 187k | uint8_t flags; |
656 | 187k | uint64_t initial; |
657 | 187k | uint64_t max = 0; |
658 | 187k | CHECK_RESULT(ReadU8(&flags, "memory flags")); |
659 | 187k | bool has_max = flags & WABT_BINARY_LIMITS_HAS_MAX_FLAG; |
660 | 187k | bool is_shared = flags & WABT_BINARY_LIMITS_IS_SHARED_FLAG; |
661 | 187k | bool is_64 = flags & WABT_BINARY_LIMITS_IS_64_FLAG; |
662 | 187k | bool has_custom_page_size = |
663 | 187k | flags & WABT_BINARY_LIMITS_HAS_CUSTOM_PAGE_SIZE_FLAG; |
664 | 187k | const uint8_t unknown_flags = flags & ~WABT_BINARY_LIMITS_ALL_MEMORY_FLAGS; |
665 | 187k | ERROR_UNLESS(unknown_flags == 0, "malformed memory limits flag: %d", flags); |
666 | 187k | ERROR_IF(is_shared && !options_.features.threads_enabled(), |
667 | 187k | "memory may not be shared: threads not allowed"); |
668 | 187k | ERROR_IF(is_64 && !options_.features.memory64_enabled(), |
669 | 187k | "memory64 not allowed"); |
670 | 187k | ERROR_IF( |
671 | 187k | has_custom_page_size && !options_.features.custom_page_sizes_enabled(), |
672 | 187k | "custom page sizes not allowed"); |
673 | 187k | if (options_.features.memory64_enabled()) { |
674 | 46.0k | CHECK_RESULT(ReadU64Leb128(&initial, "memory initial page count")); |
675 | 45.7k | if (has_max) { |
676 | 16.2k | CHECK_RESULT(ReadU64Leb128(&max, "memory max page count")); |
677 | 16.2k | } |
678 | 141k | } else { |
679 | 141k | uint32_t initial32; |
680 | 141k | CHECK_RESULT(ReadU32Leb128(&initial32, "memory initial page count")); |
681 | 141k | initial = initial32; |
682 | 141k | if (has_max) { |
683 | 90.2k | uint32_t max32; |
684 | 90.2k | CHECK_RESULT(ReadU32Leb128(&max32, "memory max page count")); |
685 | 90.2k | max = max32; |
686 | 90.2k | } |
687 | 141k | } |
688 | 186k | if (has_custom_page_size) { |
689 | 8.95k | uint32_t page_size_log2; |
690 | 8.95k | CHECK_RESULT(ReadU32Leb128(&page_size_log2, "memory page size")); |
691 | 8.88k | ERROR_IF(page_size_log2 > 16, "malformed memory page size"); |
692 | 8.78k | *out_page_size = 1 << page_size_log2; |
693 | 177k | } else { |
694 | 177k | *out_page_size = WABT_DEFAULT_PAGE_SIZE; |
695 | 177k | } |
696 | | |
697 | 186k | out_page_limits->has_max = has_max; |
698 | 186k | out_page_limits->is_shared = is_shared; |
699 | 186k | out_page_limits->is_64 = is_64; |
700 | 186k | out_page_limits->initial = initial; |
701 | 186k | out_page_limits->max = max; |
702 | | |
703 | 186k | return Result::Ok; |
704 | 186k | } |
705 | | |
706 | 31.9k | Result BinaryReader::ReadGlobalHeader(Type* out_type, bool* out_mutable) { |
707 | 31.9k | Type global_type = Type::Void; |
708 | 31.9k | uint8_t mutable_ = 0; |
709 | 31.9k | CHECK_RESULT(ReadType(&global_type, "global type")); |
710 | 31.6k | ERROR_UNLESS(IsConcreteType(global_type), "invalid global type: %#x", |
711 | 30.7k | static_cast<int>(global_type)); |
712 | | |
713 | 30.7k | CHECK_RESULT(ReadU8(&mutable_, "global mutability")); |
714 | 30.6k | ERROR_UNLESS(mutable_ <= 1, "global mutability must be 0 or 1"); |
715 | | |
716 | 30.5k | *out_type = global_type; |
717 | 30.5k | *out_mutable = mutable_; |
718 | 30.5k | return Result::Ok; |
719 | 30.6k | } |
720 | | |
721 | | Result BinaryReader::ReadAddress(Address* out_value, |
722 | | Index memory, |
723 | 279k | const char* desc) { |
724 | 279k | if (options_.features.memory64_enabled()) { |
725 | 157k | return ReadU64Leb128(out_value, desc); |
726 | 157k | } else { |
727 | 122k | uint32_t val; |
728 | 122k | Result res = ReadU32Leb128(&val, desc); |
729 | 122k | *out_value = val; |
730 | 122k | return res; |
731 | 122k | } |
732 | 279k | } |
733 | | |
734 | 6.39k | Result BinaryReader::ReadFunctionBody(Offset end_offset) { |
735 | 6.39k | CHECK_RESULT(ReadInstructions(end_offset, "function body")); |
736 | 2.54k | ERROR_UNLESS(state_.offset == end_offset, |
737 | 2.42k | "function body shorter than given size"); |
738 | 2.42k | return Result::Ok; |
739 | 2.54k | } |
740 | | |
741 | 122k | Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { |
742 | 122k | std::stack<Opcode> nested_blocks; |
743 | 14.6M | while (state_.offset < end_offset) { |
744 | 14.6M | Opcode opcode; |
745 | 14.6M | CHECK_RESULT(ReadOpcode(&opcode, "opcode")); |
746 | 14.6M | CALLBACK(OnOpcode, opcode); |
747 | 14.6M | ERROR_UNLESS_OPCODE_ENABLED(opcode); |
748 | | |
749 | 14.6M | switch (opcode) { |
750 | 6.67M | case Opcode::Unreachable: |
751 | 6.67M | CALLBACK0(OnUnreachableExpr); |
752 | 6.67M | CALLBACK0(OnOpcodeBare); |
753 | 6.67M | break; |
754 | | |
755 | 6.67M | case Opcode::Block: { |
756 | 368k | nested_blocks.push(opcode); |
757 | 368k | Type sig_type; |
758 | 368k | CHECK_RESULT(ReadType(&sig_type, "block signature type")); |
759 | 368k | ERROR_UNLESS(IsBlockType(sig_type), |
760 | 368k | "expected valid block signature type"); |
761 | 368k | CALLBACK(OnBlockExpr, sig_type); |
762 | 368k | CALLBACK(OnOpcodeBlockSig, sig_type); |
763 | 368k | break; |
764 | 368k | } |
765 | | |
766 | 422k | case Opcode::Loop: { |
767 | 422k | nested_blocks.push(opcode); |
768 | 422k | Type sig_type; |
769 | 422k | CHECK_RESULT(ReadType(&sig_type, "loop signature type")); |
770 | 422k | ERROR_UNLESS(IsBlockType(sig_type), |
771 | 421k | "expected valid block signature type"); |
772 | 421k | CALLBACK(OnLoopExpr, sig_type); |
773 | 421k | CALLBACK(OnOpcodeBlockSig, sig_type); |
774 | 421k | break; |
775 | 421k | } |
776 | | |
777 | 1.00M | case Opcode::If: { |
778 | 1.00M | nested_blocks.push(opcode); |
779 | 1.00M | Type sig_type; |
780 | 1.00M | CHECK_RESULT(ReadType(&sig_type, "if signature type")); |
781 | 1.00M | ERROR_UNLESS(IsBlockType(sig_type), |
782 | 1.00M | "expected valid block signature type"); |
783 | 1.00M | CALLBACK(OnIfExpr, sig_type); |
784 | 1.00M | CALLBACK(OnOpcodeBlockSig, sig_type); |
785 | 1.00M | break; |
786 | 1.00M | } |
787 | | |
788 | 1.00M | case Opcode::Else: |
789 | 11.3k | ERROR_IF(nested_blocks.empty() || (nested_blocks.top() != Opcode::If), |
790 | 11.3k | "else outside if block"); |
791 | 11.0k | CALLBACK0(OnElseExpr); |
792 | 11.0k | CALLBACK0(OnOpcodeBare); |
793 | 11.0k | break; |
794 | | |
795 | 20.6k | case Opcode::SelectT: { |
796 | 20.6k | Index num_results; |
797 | 20.6k | CHECK_RESULT(ReadCount(&num_results, "num result types")); |
798 | | |
799 | 20.5k | result_types_.resize(num_results); |
800 | 241k | for (Index i = 0; i < num_results; ++i) { |
801 | 222k | Type result_type; |
802 | 222k | CHECK_RESULT(ReadType(&result_type, "select result type")); |
803 | 222k | ERROR_UNLESS(IsConcreteType(result_type), |
804 | 221k | "expected valid select result type (got " PRItypecode |
805 | 221k | ")", |
806 | 221k | WABT_PRINTF_TYPE_CODE(result_type)); |
807 | 221k | result_types_[i] = result_type; |
808 | 221k | } |
809 | | |
810 | 19.6k | if (num_results) { |
811 | 5.34k | CALLBACK(OnSelectExpr, num_results, result_types_.data()); |
812 | 5.34k | CALLBACK(OnOpcodeType, result_types_[0]); |
813 | 14.2k | } else { |
814 | 14.2k | CALLBACK(OnSelectExpr, 0, NULL); |
815 | 14.2k | CALLBACK0(OnOpcodeBare); |
816 | 14.2k | } |
817 | 19.6k | break; |
818 | 19.6k | } |
819 | | |
820 | 19.6k | case Opcode::Select: |
821 | 17.3k | CALLBACK(OnSelectExpr, 0, nullptr); |
822 | 17.3k | CALLBACK0(OnOpcodeBare); |
823 | 17.3k | break; |
824 | | |
825 | 22.1k | case Opcode::Br: { |
826 | 22.1k | Index depth; |
827 | 22.1k | CHECK_RESULT(ReadIndex(&depth, "br depth")); |
828 | 22.1k | CALLBACK(OnBrExpr, depth); |
829 | 22.1k | CALLBACK(OnOpcodeIndex, depth); |
830 | 22.1k | break; |
831 | 22.1k | } |
832 | | |
833 | 22.1k | case Opcode::BrIf: { |
834 | 14.4k | Index depth; |
835 | 14.4k | CHECK_RESULT(ReadIndex(&depth, "br_if depth")); |
836 | 14.3k | CALLBACK(OnBrIfExpr, depth); |
837 | 14.3k | CALLBACK(OnOpcodeIndex, depth); |
838 | 14.3k | break; |
839 | 14.3k | } |
840 | | |
841 | 14.3k | case Opcode::BrOnNonNull: { |
842 | 1.47k | Index depth; |
843 | 1.47k | CHECK_RESULT(ReadIndex(&depth, "br_on_non_null depth")); |
844 | 1.45k | CALLBACK(OnBrOnNonNullExpr, depth); |
845 | 1.45k | CALLBACK(OnOpcodeIndex, depth); |
846 | 1.45k | break; |
847 | 1.45k | } |
848 | | |
849 | 1.45k | case Opcode::BrOnNull: { |
850 | 977 | Index depth; |
851 | 977 | CHECK_RESULT(ReadIndex(&depth, "br_on_null depth")); |
852 | 939 | CALLBACK(OnBrOnNullExpr, depth); |
853 | 937 | CALLBACK(OnOpcodeIndex, depth); |
854 | 937 | break; |
855 | 937 | } |
856 | | |
857 | 160k | case Opcode::BrTable: { |
858 | 160k | Index num_targets; |
859 | 160k | CHECK_RESULT(ReadCount(&num_targets, "br_table target count")); |
860 | 160k | target_depths_.resize(num_targets); |
861 | | |
862 | 18.0M | for (Index i = 0; i < num_targets; ++i) { |
863 | 17.8M | Index target_depth; |
864 | 17.8M | CHECK_RESULT(ReadIndex(&target_depth, "br_table target depth")); |
865 | 17.8M | target_depths_[i] = target_depth; |
866 | 17.8M | } |
867 | | |
868 | 159k | Index default_target_depth; |
869 | 159k | CHECK_RESULT( |
870 | 159k | ReadIndex(&default_target_depth, "br_table default target depth")); |
871 | | |
872 | 159k | Index* target_depths = num_targets ? target_depths_.data() : nullptr; |
873 | | |
874 | 159k | CALLBACK(OnBrTableExpr, num_targets, target_depths, |
875 | 159k | default_target_depth); |
876 | 159k | break; |
877 | 159k | } |
878 | | |
879 | 159k | case Opcode::Return: |
880 | 29.9k | CALLBACK0(OnReturnExpr); |
881 | 29.9k | CALLBACK0(OnOpcodeBare); |
882 | 29.9k | break; |
883 | | |
884 | 346k | case Opcode::Nop: |
885 | 346k | CALLBACK0(OnNopExpr); |
886 | 346k | CALLBACK0(OnOpcodeBare); |
887 | 346k | break; |
888 | | |
889 | 346k | case Opcode::Drop: |
890 | 12.8k | CALLBACK0(OnDropExpr); |
891 | 12.8k | CALLBACK0(OnOpcodeBare); |
892 | 12.8k | break; |
893 | | |
894 | 541k | case Opcode::End: |
895 | 541k | CALLBACK0(OnEndExpr); |
896 | 541k | if (nested_blocks.empty()) { |
897 | 86.1k | return Result::Ok; |
898 | 86.1k | } |
899 | 454k | nested_blocks.pop(); |
900 | 454k | break; |
901 | | |
902 | 73.1k | case Opcode::I32Const: { |
903 | 73.1k | uint32_t value; |
904 | 73.1k | CHECK_RESULT(ReadS32Leb128(&value, "i32.const value")); |
905 | 73.0k | CALLBACK(OnI32ConstExpr, value); |
906 | 73.0k | CALLBACK(OnOpcodeUint32, value); |
907 | 73.0k | break; |
908 | 73.0k | } |
909 | | |
910 | 91.2k | case Opcode::I64Const: { |
911 | 91.2k | uint64_t value; |
912 | 91.2k | CHECK_RESULT(ReadS64Leb128(&value, "i64.const value")); |
913 | 91.0k | CALLBACK(OnI64ConstExpr, value); |
914 | 91.0k | CALLBACK(OnOpcodeUint64, value); |
915 | 91.0k | break; |
916 | 91.0k | } |
917 | | |
918 | 91.0k | case Opcode::F32Const: { |
919 | 59.9k | uint32_t value_bits = 0; |
920 | 59.9k | CHECK_RESULT(ReadF32(&value_bits, "f32.const value")); |
921 | 59.7k | CALLBACK(OnF32ConstExpr, value_bits); |
922 | 59.7k | CALLBACK(OnOpcodeF32, value_bits); |
923 | 59.7k | break; |
924 | 59.7k | } |
925 | | |
926 | 59.7k | case Opcode::F64Const: { |
927 | 26.6k | uint64_t value_bits = 0; |
928 | 26.6k | CHECK_RESULT(ReadF64(&value_bits, "f64.const value")); |
929 | 26.4k | CALLBACK(OnF64ConstExpr, value_bits); |
930 | 26.4k | CALLBACK(OnOpcodeF64, value_bits); |
931 | 26.4k | break; |
932 | 26.4k | } |
933 | | |
934 | 26.4k | case Opcode::V128Const: { |
935 | 4.03k | v128 value_bits; |
936 | 4.03k | ZeroMemory(value_bits); |
937 | 4.03k | CHECK_RESULT(ReadV128(&value_bits, "v128.const value")); |
938 | 3.98k | CALLBACK(OnV128ConstExpr, value_bits); |
939 | 3.98k | CALLBACK(OnOpcodeV128, value_bits); |
940 | 3.98k | break; |
941 | 3.98k | } |
942 | | |
943 | 63.8k | case Opcode::GlobalGet: { |
944 | 63.8k | Index global_index; |
945 | 63.8k | CHECK_RESULT(ReadIndex(&global_index, "global.get global index")); |
946 | 63.7k | CALLBACK(OnGlobalGetExpr, global_index); |
947 | 63.7k | CALLBACK(OnOpcodeIndex, global_index); |
948 | 63.7k | break; |
949 | 63.7k | } |
950 | | |
951 | 99.6k | case Opcode::LocalGet: { |
952 | 99.6k | Index local_index; |
953 | 99.6k | CHECK_RESULT(ReadIndex(&local_index, "local.get local index")); |
954 | 99.5k | CALLBACK(OnLocalGetExpr, local_index); |
955 | 99.5k | CALLBACK(OnOpcodeIndex, local_index); |
956 | 99.5k | break; |
957 | 99.5k | } |
958 | | |
959 | 99.5k | case Opcode::GlobalSet: { |
960 | 48.6k | Index global_index; |
961 | 48.6k | CHECK_RESULT(ReadIndex(&global_index, "global.set global index")); |
962 | 48.5k | CALLBACK(OnGlobalSetExpr, global_index); |
963 | 48.5k | CALLBACK(OnOpcodeIndex, global_index); |
964 | 48.5k | break; |
965 | 48.5k | } |
966 | | |
967 | 63.0k | case Opcode::LocalSet: { |
968 | 63.0k | Index local_index; |
969 | 63.0k | CHECK_RESULT(ReadIndex(&local_index, "local.set local index")); |
970 | 62.9k | CALLBACK(OnLocalSetExpr, local_index); |
971 | 62.9k | CALLBACK(OnOpcodeIndex, local_index); |
972 | 62.9k | break; |
973 | 62.9k | } |
974 | | |
975 | 62.9k | case Opcode::Call: { |
976 | 31.9k | Index func_index; |
977 | 31.9k | CHECK_RESULT(ReadIndex(&func_index, "call function index")); |
978 | 31.9k | CALLBACK(OnCallExpr, func_index); |
979 | 31.9k | CALLBACK(OnOpcodeIndex, func_index); |
980 | 31.9k | break; |
981 | 31.9k | } |
982 | | |
983 | 31.9k | case Opcode::CallIndirect: { |
984 | 24.5k | Index sig_index; |
985 | 24.5k | CHECK_RESULT(ReadIndex(&sig_index, "call_indirect signature index")); |
986 | 24.5k | Index table_index = 0; |
987 | 24.5k | if (options_.features.reference_types_enabled()) { |
988 | 24.5k | CHECK_RESULT(ReadIndex(&table_index, "call_indirect table index")); |
989 | 24.5k | } else { |
990 | 0 | uint8_t reserved; |
991 | 0 | CHECK_RESULT(ReadU8(&reserved, "call_indirect reserved")); |
992 | 0 | ERROR_UNLESS(reserved == 0, "call_indirect reserved value must be 0"); |
993 | 0 | } |
994 | 24.4k | CALLBACK(OnCallIndirectExpr, sig_index, table_index); |
995 | 24.4k | CALLBACK(OnOpcodeUint32Uint32, sig_index, table_index); |
996 | 24.4k | break; |
997 | 24.4k | } |
998 | | |
999 | 24.4k | case Opcode::ReturnCall: { |
1000 | 5.43k | Index func_index; |
1001 | 5.43k | CHECK_RESULT(ReadIndex(&func_index, "return_call")); |
1002 | 5.34k | CALLBACK(OnReturnCallExpr, func_index); |
1003 | 5.34k | CALLBACK(OnOpcodeIndex, func_index); |
1004 | 5.34k | break; |
1005 | 5.34k | } |
1006 | | |
1007 | 5.34k | case Opcode::ReturnCallIndirect: { |
1008 | 3.27k | Index sig_index; |
1009 | 3.27k | CHECK_RESULT(ReadIndex(&sig_index, "return_call_indirect")); |
1010 | 3.20k | Index table_index = 0; |
1011 | 3.20k | if (options_.features.reference_types_enabled()) { |
1012 | 3.20k | CHECK_RESULT( |
1013 | 3.20k | ReadIndex(&table_index, "return_call_indirect table index")); |
1014 | 3.20k | } else { |
1015 | 0 | uint8_t reserved; |
1016 | 0 | CHECK_RESULT(ReadU8(&reserved, "return_call_indirect reserved")); |
1017 | 0 | ERROR_UNLESS(reserved == 0, |
1018 | 0 | "return_call_indirect reserved value must be 0"); |
1019 | 0 | } |
1020 | 3.15k | CALLBACK(OnReturnCallIndirectExpr, sig_index, table_index); |
1021 | 3.15k | CALLBACK(OnOpcodeUint32Uint32, sig_index, table_index); |
1022 | 3.15k | break; |
1023 | 3.15k | } |
1024 | | |
1025 | 8.27k | case Opcode::LocalTee: { |
1026 | 8.27k | Index local_index; |
1027 | 8.27k | CHECK_RESULT(ReadIndex(&local_index, "local.tee local index")); |
1028 | 8.21k | CALLBACK(OnLocalTeeExpr, local_index); |
1029 | 8.20k | CALLBACK(OnOpcodeIndex, local_index); |
1030 | 8.20k | break; |
1031 | 8.20k | } |
1032 | | |
1033 | 10.7k | case Opcode::I32Load8S: |
1034 | 16.4k | case Opcode::I32Load8U: |
1035 | 22.2k | case Opcode::I32Load16S: |
1036 | 28.9k | case Opcode::I32Load16U: |
1037 | 38.2k | case Opcode::I64Load8S: |
1038 | 45.2k | case Opcode::I64Load8U: |
1039 | 51.1k | case Opcode::I64Load16S: |
1040 | 53.9k | case Opcode::I64Load16U: |
1041 | 60.6k | case Opcode::I64Load32S: |
1042 | 64.1k | case Opcode::I64Load32U: |
1043 | 75.2k | case Opcode::I32Load: |
1044 | 81.6k | case Opcode::I64Load: |
1045 | 106k | case Opcode::F32Load: |
1046 | 112k | case Opcode::F64Load: |
1047 | 133k | case Opcode::V128Load: |
1048 | 138k | case Opcode::V128Load8X8S: |
1049 | 141k | case Opcode::V128Load8X8U: |
1050 | 143k | case Opcode::V128Load16X4S: |
1051 | 146k | case Opcode::V128Load16X4U: |
1052 | 148k | case Opcode::V128Load32X2S: |
1053 | 149k | case Opcode::V128Load32X2U: { |
1054 | 149k | Address alignment_log2; |
1055 | 149k | Index memidx; |
1056 | 149k | Address offset; |
1057 | 149k | CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset, |
1058 | 149k | "load alignment", "load memidx", |
1059 | 149k | "load offset")); |
1060 | 146k | CALLBACK(OnLoadExpr, opcode, memidx, alignment_log2, offset); |
1061 | 146k | CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset)); |
1062 | 146k | break; |
1063 | 146k | } |
1064 | | |
1065 | 146k | case Opcode::I32Store8: |
1066 | 13.5k | case Opcode::I32Store16: |
1067 | 15.2k | case Opcode::I64Store8: |
1068 | 20.1k | case Opcode::I64Store16: |
1069 | 22.4k | case Opcode::I64Store32: |
1070 | 24.8k | case Opcode::I32Store: |
1071 | 26.4k | case Opcode::I64Store: |
1072 | 29.4k | case Opcode::F32Store: |
1073 | 32.3k | case Opcode::F64Store: |
1074 | 59.0k | case Opcode::V128Store: { |
1075 | 59.0k | Address alignment_log2; |
1076 | 59.0k | Index memidx; |
1077 | 59.0k | Address offset; |
1078 | 59.0k | CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset, |
1079 | 59.0k | "store alignment", "store memidx", |
1080 | 59.0k | "store offset")); |
1081 | 58.3k | CALLBACK(OnStoreExpr, opcode, memidx, alignment_log2, offset); |
1082 | 58.3k | CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset)); |
1083 | 58.3k | break; |
1084 | 58.3k | } |
1085 | | |
1086 | 58.3k | case Opcode::MemorySize: { |
1087 | 13.7k | Index memidx = 0; |
1088 | 13.7k | if (!options_.features.multi_memory_enabled()) { |
1089 | 5.26k | uint8_t reserved; |
1090 | 5.26k | CHECK_RESULT(ReadU8(&reserved, "memory.size reserved")); |
1091 | 5.24k | ERROR_UNLESS(reserved == 0, "memory.size reserved value must be 0"); |
1092 | 8.52k | } else { |
1093 | 8.52k | CHECK_RESULT(ReadMemidx(&memidx, "memory.size memidx")); |
1094 | 8.52k | } |
1095 | 13.6k | CALLBACK(OnMemorySizeExpr, memidx); |
1096 | 13.6k | CALLBACK(OnOpcodeUint32, memidx); |
1097 | 13.6k | break; |
1098 | 13.6k | } |
1099 | | |
1100 | 19.0k | case Opcode::MemoryGrow: { |
1101 | 19.0k | Index memidx = 0; |
1102 | 19.0k | if (!options_.features.multi_memory_enabled()) { |
1103 | 7.30k | uint8_t reserved; |
1104 | 7.30k | CHECK_RESULT(ReadU8(&reserved, "memory.grow reserved")); |
1105 | 7.27k | ERROR_UNLESS(reserved == 0, "memory.grow reserved value must be 0"); |
1106 | 11.7k | } else { |
1107 | 11.7k | CHECK_RESULT(ReadMemidx(&memidx, "memory.grow memidx")); |
1108 | 11.7k | } |
1109 | 18.8k | CALLBACK(OnMemoryGrowExpr, memidx); |
1110 | 18.8k | CALLBACK(OnOpcodeUint32, memidx); |
1111 | 18.8k | break; |
1112 | 18.8k | } |
1113 | | |
1114 | 18.8k | case Opcode::I32Add: |
1115 | 30.5k | case Opcode::I32Sub: |
1116 | 82.3k | case Opcode::I32Mul: |
1117 | 125k | case Opcode::I32DivS: |
1118 | 143k | case Opcode::I32DivU: |
1119 | 206k | case Opcode::I32RemS: |
1120 | 215k | case Opcode::I32RemU: |
1121 | 221k | case Opcode::I32And: |
1122 | 234k | case Opcode::I32Or: |
1123 | 284k | case Opcode::I32Xor: |
1124 | 301k | case Opcode::I32Shl: |
1125 | 308k | case Opcode::I32ShrU: |
1126 | 319k | case Opcode::I32ShrS: |
1127 | 329k | case Opcode::I32Rotr: |
1128 | 337k | case Opcode::I32Rotl: |
1129 | 1.30M | case Opcode::I64Add: |
1130 | 1.31M | case Opcode::I64Sub: |
1131 | 1.33M | case Opcode::I64Mul: |
1132 | 1.36M | case Opcode::I64DivS: |
1133 | 1.38M | case Opcode::I64DivU: |
1134 | 1.39M | case Opcode::I64RemS: |
1135 | 1.40M | case Opcode::I64RemU: |
1136 | 1.42M | case Opcode::I64And: |
1137 | 1.43M | case Opcode::I64Or: |
1138 | 1.44M | case Opcode::I64Xor: |
1139 | 1.45M | case Opcode::I64Shl: |
1140 | 1.46M | case Opcode::I64ShrU: |
1141 | 1.47M | case Opcode::I64ShrS: |
1142 | 1.47M | case Opcode::I64Rotr: |
1143 | 1.48M | case Opcode::I64Rotl: |
1144 | 1.49M | case Opcode::F32Add: |
1145 | 1.49M | case Opcode::F32Sub: |
1146 | 1.49M | case Opcode::F32Mul: |
1147 | 1.51M | case Opcode::F32Div: |
1148 | 1.52M | case Opcode::F32Min: |
1149 | 1.53M | case Opcode::F32Max: |
1150 | 1.53M | case Opcode::F32Copysign: |
1151 | 1.55M | case Opcode::F64Add: |
1152 | 1.56M | case Opcode::F64Sub: |
1153 | 1.57M | case Opcode::F64Mul: |
1154 | 1.58M | case Opcode::F64Div: |
1155 | 1.59M | case Opcode::F64Min: |
1156 | 1.59M | case Opcode::F64Max: |
1157 | 1.60M | case Opcode::F64Copysign: |
1158 | 1.60M | case Opcode::I8X16Add: |
1159 | 1.60M | case Opcode::I16X8Add: |
1160 | 1.60M | case Opcode::I32X4Add: |
1161 | 1.60M | case Opcode::I64X2Add: |
1162 | 1.60M | case Opcode::I8X16Sub: |
1163 | 1.60M | case Opcode::I16X8Sub: |
1164 | 1.60M | case Opcode::I32X4Sub: |
1165 | 1.61M | case Opcode::I64X2Sub: |
1166 | 1.61M | case Opcode::I16X8Mul: |
1167 | 1.61M | case Opcode::I32X4Mul: |
1168 | 1.61M | case Opcode::I64X2Mul: |
1169 | 1.62M | case Opcode::I8X16AddSatS: |
1170 | 1.62M | case Opcode::I8X16AddSatU: |
1171 | 1.62M | case Opcode::I16X8AddSatS: |
1172 | 1.62M | case Opcode::I16X8AddSatU: |
1173 | 1.62M | case Opcode::I8X16SubSatS: |
1174 | 1.63M | case Opcode::I8X16SubSatU: |
1175 | 1.63M | case Opcode::I16X8SubSatS: |
1176 | 1.63M | case Opcode::I16X8SubSatU: |
1177 | 1.63M | case Opcode::I8X16MinS: |
1178 | 1.63M | case Opcode::I16X8MinS: |
1179 | 1.64M | case Opcode::I32X4MinS: |
1180 | 1.64M | case Opcode::I8X16MinU: |
1181 | 1.64M | case Opcode::I16X8MinU: |
1182 | 1.64M | case Opcode::I32X4MinU: |
1183 | 1.64M | case Opcode::I8X16MaxS: |
1184 | 1.64M | case Opcode::I16X8MaxS: |
1185 | 1.64M | case Opcode::I32X4MaxS: |
1186 | 1.65M | case Opcode::I8X16MaxU: |
1187 | 1.65M | case Opcode::I16X8MaxU: |
1188 | 1.65M | case Opcode::I32X4MaxU: |
1189 | 1.65M | case Opcode::I8X16Shl: |
1190 | 1.65M | case Opcode::I16X8Shl: |
1191 | 1.66M | case Opcode::I32X4Shl: |
1192 | 1.66M | case Opcode::I64X2Shl: |
1193 | 1.66M | case Opcode::I8X16ShrS: |
1194 | 1.67M | case Opcode::I8X16ShrU: |
1195 | 1.67M | case Opcode::I16X8ShrS: |
1196 | 1.67M | case Opcode::I16X8ShrU: |
1197 | 1.67M | case Opcode::I32X4ShrS: |
1198 | 1.67M | case Opcode::I32X4ShrU: |
1199 | 1.68M | case Opcode::I64X2ShrS: |
1200 | 1.68M | case Opcode::I64X2ShrU: |
1201 | 1.68M | case Opcode::V128And: |
1202 | 1.68M | case Opcode::V128Or: |
1203 | 1.69M | case Opcode::V128Xor: |
1204 | 1.69M | case Opcode::F32X4Min: |
1205 | 1.69M | case Opcode::F32X4PMin: |
1206 | 1.69M | case Opcode::F64X2Min: |
1207 | 1.69M | case Opcode::F64X2PMin: |
1208 | 1.69M | case Opcode::F32X4Max: |
1209 | 1.69M | case Opcode::F32X4PMax: |
1210 | 1.70M | case Opcode::F64X2Max: |
1211 | 1.70M | case Opcode::F64X2PMax: |
1212 | 1.70M | case Opcode::F32X4Add: |
1213 | 1.70M | case Opcode::F64X2Add: |
1214 | 1.70M | case Opcode::F32X4Sub: |
1215 | 1.70M | case Opcode::F64X2Sub: |
1216 | 1.70M | case Opcode::F32X4Div: |
1217 | 1.71M | case Opcode::F64X2Div: |
1218 | 1.71M | case Opcode::F32X4Mul: |
1219 | 1.71M | case Opcode::F64X2Mul: |
1220 | 1.71M | case Opcode::I8X16Swizzle: |
1221 | 1.73M | case Opcode::I8X16NarrowI16X8S: |
1222 | 1.74M | case Opcode::I8X16NarrowI16X8U: |
1223 | 1.74M | case Opcode::I16X8NarrowI32X4S: |
1224 | 1.74M | case Opcode::I16X8NarrowI32X4U: |
1225 | 1.75M | case Opcode::V128Andnot: |
1226 | 1.75M | case Opcode::I8X16AvgrU: |
1227 | 1.75M | case Opcode::I16X8AvgrU: |
1228 | 1.75M | case Opcode::I16X8ExtmulLowI8X16S: |
1229 | 1.76M | case Opcode::I16X8ExtmulHighI8X16S: |
1230 | 1.76M | case Opcode::I16X8ExtmulLowI8X16U: |
1231 | 1.76M | case Opcode::I16X8ExtmulHighI8X16U: |
1232 | 1.76M | case Opcode::I32X4ExtmulLowI16X8S: |
1233 | 1.76M | case Opcode::I32X4ExtmulHighI16X8S: |
1234 | 1.77M | case Opcode::I32X4ExtmulLowI16X8U: |
1235 | 1.77M | case Opcode::I32X4ExtmulHighI16X8U: |
1236 | 1.77M | case Opcode::I64X2ExtmulLowI32X4S: |
1237 | 1.78M | case Opcode::I64X2ExtmulHighI32X4S: |
1238 | 1.78M | case Opcode::I64X2ExtmulLowI32X4U: |
1239 | 1.78M | case Opcode::I64X2ExtmulHighI32X4U: |
1240 | 1.78M | case Opcode::I16X8Q15mulrSatS: |
1241 | 1.78M | case Opcode::I32X4DotI16X8S: |
1242 | 1.78M | case Opcode::I8X16RelaxedSwizzle: |
1243 | 1.78M | case Opcode::F32X4RelaxedMin: |
1244 | 1.78M | case Opcode::F32X4RelaxedMax: |
1245 | 1.78M | case Opcode::F64X2RelaxedMin: |
1246 | 1.78M | case Opcode::F64X2RelaxedMax: |
1247 | 1.78M | case Opcode::I16X8RelaxedQ15mulrS: |
1248 | 1.78M | case Opcode::I16X8DotI8X16I7X16S: |
1249 | 1.78M | CALLBACK(OnBinaryExpr, opcode); |
1250 | 1.78M | CALLBACK0(OnOpcodeBare); |
1251 | 1.78M | break; |
1252 | | |
1253 | 1.78M | case Opcode::I32Eq: |
1254 | 28.5k | case Opcode::I32Ne: |
1255 | 52.8k | case Opcode::I32LtS: |
1256 | 63.8k | case Opcode::I32LeS: |
1257 | 68.0k | case Opcode::I32LtU: |
1258 | 77.1k | case Opcode::I32LeU: |
1259 | 93.8k | case Opcode::I32GtS: |
1260 | 107k | case Opcode::I32GeS: |
1261 | 128k | case Opcode::I32GtU: |
1262 | 136k | case Opcode::I32GeU: |
1263 | 142k | case Opcode::I64Eq: |
1264 | 155k | case Opcode::I64Ne: |
1265 | 168k | case Opcode::I64LtS: |
1266 | 177k | case Opcode::I64LeS: |
1267 | 187k | case Opcode::I64LtU: |
1268 | 202k | case Opcode::I64LeU: |
1269 | 238k | case Opcode::I64GtS: |
1270 | 256k | case Opcode::I64GeS: |
1271 | 273k | case Opcode::I64GtU: |
1272 | 280k | case Opcode::I64GeU: |
1273 | 310k | case Opcode::F32Eq: |
1274 | 319k | case Opcode::F32Ne: |
1275 | 338k | case Opcode::F32Lt: |
1276 | 350k | case Opcode::F32Le: |
1277 | 361k | case Opcode::F32Gt: |
1278 | 379k | case Opcode::F32Ge: |
1279 | 433k | case Opcode::F64Eq: |
1280 | 440k | case Opcode::F64Ne: |
1281 | 453k | case Opcode::F64Lt: |
1282 | 467k | case Opcode::F64Le: |
1283 | 530k | case Opcode::F64Gt: |
1284 | 546k | case Opcode::F64Ge: |
1285 | 548k | case Opcode::I8X16Eq: |
1286 | 551k | case Opcode::I16X8Eq: |
1287 | 553k | case Opcode::I32X4Eq: |
1288 | 553k | case Opcode::I64X2Eq: |
1289 | 558k | case Opcode::F32X4Eq: |
1290 | 560k | case Opcode::F64X2Eq: |
1291 | 561k | case Opcode::I8X16Ne: |
1292 | 562k | case Opcode::I16X8Ne: |
1293 | 564k | case Opcode::I32X4Ne: |
1294 | 565k | case Opcode::I64X2Ne: |
1295 | 567k | case Opcode::F32X4Ne: |
1296 | 568k | case Opcode::F64X2Ne: |
1297 | 569k | case Opcode::I8X16LtS: |
1298 | 573k | case Opcode::I8X16LtU: |
1299 | 575k | case Opcode::I16X8LtS: |
1300 | 578k | case Opcode::I16X8LtU: |
1301 | 579k | case Opcode::I32X4LtS: |
1302 | 585k | case Opcode::I32X4LtU: |
1303 | 586k | case Opcode::I64X2LtS: |
1304 | 588k | case Opcode::F32X4Lt: |
1305 | 590k | case Opcode::F64X2Lt: |
1306 | 593k | case Opcode::I8X16LeS: |
1307 | 596k | case Opcode::I8X16LeU: |
1308 | 598k | case Opcode::I16X8LeS: |
1309 | 601k | case Opcode::I16X8LeU: |
1310 | 602k | case Opcode::I32X4LeS: |
1311 | 604k | case Opcode::I32X4LeU: |
1312 | 604k | case Opcode::I64X2LeS: |
1313 | 606k | case Opcode::F32X4Le: |
1314 | 607k | case Opcode::F64X2Le: |
1315 | 608k | case Opcode::I8X16GtS: |
1316 | 610k | case Opcode::I8X16GtU: |
1317 | 614k | case Opcode::I16X8GtS: |
1318 | 616k | case Opcode::I16X8GtU: |
1319 | 620k | case Opcode::I32X4GtS: |
1320 | 621k | case Opcode::I32X4GtU: |
1321 | 623k | case Opcode::I64X2GtS: |
1322 | 627k | case Opcode::F32X4Gt: |
1323 | 629k | case Opcode::F64X2Gt: |
1324 | 646k | case Opcode::I8X16GeS: |
1325 | 648k | case Opcode::I8X16GeU: |
1326 | 650k | case Opcode::I16X8GeS: |
1327 | 652k | case Opcode::I16X8GeU: |
1328 | 654k | case Opcode::I32X4GeS: |
1329 | 655k | case Opcode::I32X4GeU: |
1330 | 657k | case Opcode::I64X2GeS: |
1331 | 663k | case Opcode::F32X4Ge: |
1332 | 665k | case Opcode::F64X2Ge: |
1333 | 665k | CALLBACK(OnCompareExpr, opcode); |
1334 | 665k | CALLBACK0(OnOpcodeBare); |
1335 | 665k | break; |
1336 | | |
1337 | 665k | case Opcode::I32Clz: |
1338 | 32.0k | case Opcode::I32Ctz: |
1339 | 51.4k | case Opcode::I32Popcnt: |
1340 | 66.2k | case Opcode::I64Clz: |
1341 | 85.2k | case Opcode::I64Ctz: |
1342 | 133k | case Opcode::I64Popcnt: |
1343 | 142k | case Opcode::F32Abs: |
1344 | 146k | case Opcode::F32Neg: |
1345 | 171k | case Opcode::F32Ceil: |
1346 | 180k | case Opcode::F32Floor: |
1347 | 190k | case Opcode::F32Trunc: |
1348 | 200k | case Opcode::F32Nearest: |
1349 | 208k | case Opcode::F32Sqrt: |
1350 | 219k | case Opcode::F64Abs: |
1351 | 225k | case Opcode::F64Neg: |
1352 | 230k | case Opcode::F64Ceil: |
1353 | 236k | case Opcode::F64Floor: |
1354 | 241k | case Opcode::F64Trunc: |
1355 | 246k | case Opcode::F64Nearest: |
1356 | 252k | case Opcode::F64Sqrt: |
1357 | 254k | case Opcode::I8X16Splat: |
1358 | 255k | case Opcode::I16X8Splat: |
1359 | 258k | case Opcode::I32X4Splat: |
1360 | 260k | case Opcode::I64X2Splat: |
1361 | 261k | case Opcode::F32X4Splat: |
1362 | 267k | case Opcode::F64X2Splat: |
1363 | 271k | case Opcode::I8X16Neg: |
1364 | 273k | case Opcode::I16X8Neg: |
1365 | 283k | case Opcode::I32X4Neg: |
1366 | 285k | case Opcode::I64X2Neg: |
1367 | 288k | case Opcode::V128Not: |
1368 | 289k | case Opcode::V128AnyTrue: |
1369 | 300k | case Opcode::I8X16Bitmask: |
1370 | 302k | case Opcode::I16X8Bitmask: |
1371 | 303k | case Opcode::I32X4Bitmask: |
1372 | 307k | case Opcode::I64X2Bitmask: |
1373 | 308k | case Opcode::I8X16AllTrue: |
1374 | 313k | case Opcode::I16X8AllTrue: |
1375 | 315k | case Opcode::I32X4AllTrue: |
1376 | 316k | case Opcode::I64X2AllTrue: |
1377 | 319k | case Opcode::F32X4Ceil: |
1378 | 321k | case Opcode::F64X2Ceil: |
1379 | 323k | case Opcode::F32X4Floor: |
1380 | 327k | case Opcode::F64X2Floor: |
1381 | 329k | case Opcode::F32X4Trunc: |
1382 | 343k | case Opcode::F64X2Trunc: |
1383 | 344k | case Opcode::F32X4Nearest: |
1384 | 345k | case Opcode::F64X2Nearest: |
1385 | 349k | case Opcode::F32X4Neg: |
1386 | 350k | case Opcode::F64X2Neg: |
1387 | 351k | case Opcode::F32X4Abs: |
1388 | 353k | case Opcode::F64X2Abs: |
1389 | 355k | case Opcode::F32X4Sqrt: |
1390 | 357k | case Opcode::F64X2Sqrt: |
1391 | 360k | case Opcode::I16X8ExtendLowI8X16S: |
1392 | 361k | case Opcode::I16X8ExtendHighI8X16S: |
1393 | 363k | case Opcode::I16X8ExtendLowI8X16U: |
1394 | 364k | case Opcode::I16X8ExtendHighI8X16U: |
1395 | 366k | case Opcode::I32X4ExtendLowI16X8S: |
1396 | 368k | case Opcode::I32X4ExtendHighI16X8S: |
1397 | 369k | case Opcode::I32X4ExtendLowI16X8U: |
1398 | 370k | case Opcode::I32X4ExtendHighI16X8U: |
1399 | 373k | case Opcode::I64X2ExtendLowI32X4S: |
1400 | 376k | case Opcode::I64X2ExtendHighI32X4S: |
1401 | 378k | case Opcode::I64X2ExtendLowI32X4U: |
1402 | 380k | case Opcode::I64X2ExtendHighI32X4U: |
1403 | 383k | case Opcode::I8X16Abs: |
1404 | 385k | case Opcode::I16X8Abs: |
1405 | 386k | case Opcode::I32X4Abs: |
1406 | 387k | case Opcode::I64X2Abs: |
1407 | 388k | case Opcode::I8X16Popcnt: |
1408 | 393k | case Opcode::I16X8ExtaddPairwiseI8X16S: |
1409 | 395k | case Opcode::I16X8ExtaddPairwiseI8X16U: |
1410 | 400k | case Opcode::I32X4ExtaddPairwiseI16X8S: |
1411 | 403k | case Opcode::I32X4ExtaddPairwiseI16X8U: |
1412 | 403k | case Opcode::I32X4RelaxedTruncF32X4S: |
1413 | 403k | case Opcode::I32X4RelaxedTruncF32X4U: |
1414 | 404k | case Opcode::I32X4RelaxedTruncF64X2SZero: |
1415 | 404k | case Opcode::I32X4RelaxedTruncF64X2UZero: |
1416 | 404k | CALLBACK(OnUnaryExpr, opcode); |
1417 | 404k | CALLBACK0(OnOpcodeBare); |
1418 | 404k | break; |
1419 | | |
1420 | 404k | case Opcode::V128BitSelect: |
1421 | 2.23k | case Opcode::F32X4RelaxedMadd: |
1422 | 2.89k | case Opcode::F32X4RelaxedNmadd: |
1423 | 3.45k | case Opcode::F64X2RelaxedMadd: |
1424 | 3.81k | case Opcode::F64X2RelaxedNmadd: |
1425 | 4.42k | case Opcode::I8X16RelaxedLaneSelect: |
1426 | 4.77k | case Opcode::I16X8RelaxedLaneSelect: |
1427 | 5.24k | case Opcode::I32X4RelaxedLaneSelect: |
1428 | 5.81k | case Opcode::I64X2RelaxedLaneSelect: |
1429 | 6.71k | case Opcode::I32X4DotI8X16I7X16AddS: |
1430 | 6.71k | CALLBACK(OnTernaryExpr, opcode); |
1431 | 6.71k | CALLBACK0(OnOpcodeBare); |
1432 | 6.71k | break; |
1433 | | |
1434 | 6.71k | case Opcode::I8X16ExtractLaneS: |
1435 | 2.60k | case Opcode::I8X16ExtractLaneU: |
1436 | 5.12k | case Opcode::I16X8ExtractLaneS: |
1437 | 6.77k | case Opcode::I16X8ExtractLaneU: |
1438 | 7.80k | case Opcode::I32X4ExtractLane: |
1439 | 9.45k | case Opcode::I64X2ExtractLane: |
1440 | 12.0k | case Opcode::F32X4ExtractLane: |
1441 | 19.8k | case Opcode::F64X2ExtractLane: |
1442 | 20.8k | case Opcode::I8X16ReplaceLane: |
1443 | 27.0k | case Opcode::I16X8ReplaceLane: |
1444 | 31.7k | case Opcode::I32X4ReplaceLane: |
1445 | 33.4k | case Opcode::I64X2ReplaceLane: |
1446 | 35.2k | case Opcode::F32X4ReplaceLane: |
1447 | 36.7k | case Opcode::F64X2ReplaceLane: { |
1448 | 36.7k | uint8_t lane_val; |
1449 | 36.7k | CHECK_RESULT(ReadU8(&lane_val, "Lane idx")); |
1450 | 36.5k | CALLBACK(OnSimdLaneOpExpr, opcode, lane_val); |
1451 | 36.5k | CALLBACK(OnOpcodeUint64, lane_val); |
1452 | 36.5k | break; |
1453 | 36.5k | } |
1454 | | |
1455 | 36.5k | case Opcode::I8X16Shuffle: { |
1456 | 20.4k | v128 value; |
1457 | 20.4k | CHECK_RESULT(ReadV128(&value, "Lane idx [16]")); |
1458 | 20.3k | CALLBACK(OnSimdShuffleOpExpr, opcode, value); |
1459 | 20.3k | CALLBACK(OnOpcodeV128, value); |
1460 | 20.3k | break; |
1461 | 20.3k | } |
1462 | | |
1463 | 20.3k | case Opcode::V128Load8Splat: |
1464 | 5.54k | case Opcode::V128Load16Splat: |
1465 | 6.93k | case Opcode::V128Load32Splat: |
1466 | 7.95k | case Opcode::V128Load64Splat: { |
1467 | 7.95k | Address alignment_log2; |
1468 | 7.95k | Index memidx; |
1469 | 7.95k | Address offset; |
1470 | 7.95k | CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset, |
1471 | 7.95k | "load alignment", "load memidx", |
1472 | 7.95k | "load offset")); |
1473 | 7.84k | CALLBACK(OnLoadSplatExpr, opcode, memidx, alignment_log2, offset); |
1474 | 7.84k | CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset)); |
1475 | 7.84k | break; |
1476 | 7.84k | } |
1477 | 7.84k | case Opcode::V128Load8Lane: |
1478 | 3.12k | case Opcode::V128Load16Lane: |
1479 | 6.45k | case Opcode::V128Load32Lane: |
1480 | 10.2k | case Opcode::V128Load64Lane: { |
1481 | 10.2k | Address alignment_log2; |
1482 | 10.2k | Index memidx; |
1483 | 10.2k | Address offset; |
1484 | 10.2k | uint8_t lane_val; |
1485 | 10.2k | CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset, |
1486 | 10.2k | "load alignment", "load memidx", |
1487 | 10.2k | "load offset", &lane_val)); |
1488 | 10.1k | CALLBACK(OnSimdLoadLaneExpr, opcode, memidx, alignment_log2, offset, |
1489 | 10.1k | lane_val); |
1490 | 10.1k | CHECK_RESULT( |
1491 | 10.1k | CallbackMemLocation(&alignment_log2, &memidx, &offset, &lane_val)); |
1492 | 10.1k | break; |
1493 | 10.1k | } |
1494 | 10.1k | case Opcode::V128Store8Lane: |
1495 | 6.43k | case Opcode::V128Store16Lane: |
1496 | 10.2k | case Opcode::V128Store32Lane: |
1497 | 12.1k | case Opcode::V128Store64Lane: { |
1498 | 12.1k | Address alignment_log2; |
1499 | 12.1k | Index memidx; |
1500 | 12.1k | Address offset; |
1501 | 12.1k | uint8_t lane_val; |
1502 | 12.1k | CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset, |
1503 | 12.1k | "store alignment", "store memidx", |
1504 | 12.1k | "store offset", &lane_val)); |
1505 | 12.0k | CALLBACK(OnSimdStoreLaneExpr, opcode, memidx, alignment_log2, offset, |
1506 | 12.0k | lane_val); |
1507 | 12.0k | CHECK_RESULT( |
1508 | 12.0k | CallbackMemLocation(&alignment_log2, &memidx, &offset, &lane_val)); |
1509 | 12.0k | break; |
1510 | 12.0k | } |
1511 | 12.0k | case Opcode::V128Load32Zero: |
1512 | 5.78k | case Opcode::V128Load64Zero: { |
1513 | 5.78k | Address alignment_log2; |
1514 | 5.78k | Index memidx; |
1515 | 5.78k | Address offset; |
1516 | 5.78k | CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset, |
1517 | 5.78k | "load alignment", "load memidx", |
1518 | 5.78k | "load offset")); |
1519 | 5.72k | CALLBACK(OnLoadZeroExpr, opcode, memidx, alignment_log2, offset); |
1520 | 5.72k | CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset)); |
1521 | 5.72k | break; |
1522 | 5.72k | } |
1523 | 11.8k | case Opcode::I32TruncF32S: |
1524 | 38.6k | case Opcode::I32TruncF64S: |
1525 | 45.6k | case Opcode::I32TruncF32U: |
1526 | 55.9k | case Opcode::I32TruncF64U: |
1527 | 62.0k | case Opcode::I32WrapI64: |
1528 | 67.3k | case Opcode::I64TruncF32S: |
1529 | 81.6k | case Opcode::I64TruncF64S: |
1530 | 90.3k | case Opcode::I64TruncF32U: |
1531 | 123k | case Opcode::I64TruncF64U: |
1532 | 131k | case Opcode::I64ExtendI32S: |
1533 | 143k | case Opcode::I64ExtendI32U: |
1534 | 166k | case Opcode::F32ConvertI32S: |
1535 | 185k | case Opcode::F32ConvertI32U: |
1536 | 191k | case Opcode::F32ConvertI64S: |
1537 | 198k | case Opcode::F32ConvertI64U: |
1538 | 207k | case Opcode::F32DemoteF64: |
1539 | 212k | case Opcode::F32ReinterpretI32: |
1540 | 218k | case Opcode::F64ConvertI32S: |
1541 | 234k | case Opcode::F64ConvertI32U: |
1542 | 248k | case Opcode::F64ConvertI64S: |
1543 | 265k | case Opcode::F64ConvertI64U: |
1544 | 275k | case Opcode::F64PromoteF32: |
1545 | 285k | case Opcode::F64ReinterpretI64: |
1546 | 299k | case Opcode::I32ReinterpretF32: |
1547 | 342k | case Opcode::I64ReinterpretF64: |
1548 | 361k | case Opcode::I32Eqz: |
1549 | 373k | case Opcode::I64Eqz: |
1550 | 378k | case Opcode::F32X4ConvertI32X4S: |
1551 | 379k | case Opcode::F32X4ConvertI32X4U: |
1552 | 381k | case Opcode::I32X4TruncSatF32X4S: |
1553 | 382k | case Opcode::I32X4TruncSatF32X4U: |
1554 | 384k | case Opcode::F32X4DemoteF64X2Zero: |
1555 | 388k | case Opcode::F64X2PromoteLowF32X4: |
1556 | 396k | case Opcode::I32X4TruncSatF64X2SZero: |
1557 | 397k | case Opcode::I32X4TruncSatF64X2UZero: |
1558 | 398k | case Opcode::F64X2ConvertLowI32X4S: |
1559 | 400k | case Opcode::F64X2ConvertLowI32X4U: |
1560 | 400k | CALLBACK(OnConvertExpr, opcode); |
1561 | 400k | CALLBACK0(OnOpcodeBare); |
1562 | 400k | break; |
1563 | | |
1564 | 459k | case Opcode::Try: { |
1565 | 459k | nested_blocks.push(opcode); |
1566 | 459k | Type sig_type; |
1567 | 459k | CHECK_RESULT(ReadType(&sig_type, "try signature type")); |
1568 | 458k | ERROR_UNLESS(IsBlockType(sig_type), |
1569 | 458k | "expected valid block signature type"); |
1570 | 458k | CALLBACK(OnTryExpr, sig_type); |
1571 | 458k | CALLBACK(OnOpcodeBlockSig, sig_type); |
1572 | 458k | break; |
1573 | 458k | } |
1574 | | |
1575 | 458k | case Opcode::TryTable: { |
1576 | 9.40k | nested_blocks.push(opcode); |
1577 | 9.40k | Type sig_type; |
1578 | 9.40k | CHECK_RESULT(ReadType(&sig_type, "try_table signature type")); |
1579 | 9.30k | ERROR_UNLESS(IsBlockType(sig_type), |
1580 | 9.27k | "expected valid block signature type"); |
1581 | 9.27k | Index count; |
1582 | 9.27k | CHECK_RESULT(ReadCount(&count, "catch count")); |
1583 | | |
1584 | 9.18k | catches_.resize(count); |
1585 | 21.3k | for (Index i = 0; i < count; i++) { |
1586 | 12.5k | uint8_t handler; |
1587 | 12.5k | CHECK_RESULT(ReadU8(&handler, "catch handler")); |
1588 | 12.5k | ERROR_UNLESS(handler < 4, "expected valid catch handler"); |
1589 | 12.2k | bool is_catch_all = handler & 2; |
1590 | 12.2k | Index tag = kInvalidIndex; |
1591 | 12.2k | if (!(is_catch_all)) { |
1592 | 8.60k | CHECK_RESULT(ReadIndex(&tag, "catch tag")); |
1593 | 8.60k | } |
1594 | 12.2k | Index depth; |
1595 | 12.2k | CHECK_RESULT(ReadIndex(&depth, "catch depth")); |
1596 | 12.1k | CatchClause catch_; |
1597 | 12.1k | catch_.kind = CatchKind(handler); |
1598 | 12.1k | catch_.tag = tag; |
1599 | 12.1k | catch_.depth = depth; |
1600 | 12.1k | catches_[i] = catch_; |
1601 | 12.1k | } |
1602 | | |
1603 | 8.84k | CALLBACK(OnTryTableExpr, sig_type, catches_); |
1604 | 8.84k | break; |
1605 | 8.84k | } |
1606 | | |
1607 | 14.2k | case Opcode::Catch: { |
1608 | 14.2k | Index index; |
1609 | 14.2k | CHECK_RESULT(ReadIndex(&index, "tag index")); |
1610 | 14.1k | CALLBACK(OnCatchExpr, index); |
1611 | 14.1k | CALLBACK(OnOpcodeIndex, index); |
1612 | 14.1k | break; |
1613 | 14.1k | } |
1614 | | |
1615 | 14.1k | case Opcode::CatchAll: { |
1616 | 10.8k | CALLBACK(OnCatchAllExpr); |
1617 | 10.8k | CALLBACK(OnOpcodeBare); |
1618 | 10.8k | break; |
1619 | 10.8k | } |
1620 | | |
1621 | 10.8k | case Opcode::Delegate: { |
1622 | 1.22k | ERROR_IF(nested_blocks.empty() || (nested_blocks.top() != Opcode::Try), |
1623 | 1.22k | "delegate outside try block"); |
1624 | 1.07k | nested_blocks.pop(); |
1625 | 1.07k | Index index; |
1626 | 1.07k | CHECK_RESULT(ReadIndex(&index, "depth")); |
1627 | 1.04k | CALLBACK(OnDelegateExpr, index); |
1628 | 1.04k | CALLBACK(OnOpcodeIndex, index); |
1629 | 1.04k | break; |
1630 | 1.04k | } |
1631 | | |
1632 | 19.3k | case Opcode::Rethrow: { |
1633 | 19.3k | Index depth; |
1634 | 19.3k | CHECK_RESULT(ReadIndex(&depth, "catch depth")); |
1635 | 19.2k | CALLBACK(OnRethrowExpr, depth); |
1636 | 19.2k | CALLBACK(OnOpcodeIndex, depth); |
1637 | 19.2k | break; |
1638 | 19.2k | } |
1639 | | |
1640 | 19.2k | case Opcode::Throw: { |
1641 | 11.5k | Index index; |
1642 | 11.5k | CHECK_RESULT(ReadIndex(&index, "tag index")); |
1643 | 11.4k | CALLBACK(OnThrowExpr, index); |
1644 | 11.4k | CALLBACK(OnOpcodeIndex, index); |
1645 | 11.4k | break; |
1646 | 11.4k | } |
1647 | | |
1648 | 12.6k | case Opcode::ThrowRef: { |
1649 | 12.6k | CALLBACK(OnThrowRefExpr); |
1650 | 12.6k | CALLBACK(OnOpcodeBare); |
1651 | 12.6k | break; |
1652 | 12.6k | } |
1653 | | |
1654 | 12.6k | case Opcode::I32Extend8S: |
1655 | 12.0k | case Opcode::I32Extend16S: |
1656 | 20.7k | case Opcode::I64Extend8S: |
1657 | 28.2k | case Opcode::I64Extend16S: |
1658 | 38.3k | case Opcode::I64Extend32S: |
1659 | 38.3k | CALLBACK(OnUnaryExpr, opcode); |
1660 | 38.3k | CALLBACK0(OnOpcodeBare); |
1661 | 38.3k | break; |
1662 | | |
1663 | 38.3k | case Opcode::I32TruncSatF32S: |
1664 | 9.60k | case Opcode::I32TruncSatF32U: |
1665 | 11.4k | case Opcode::I32TruncSatF64S: |
1666 | 14.9k | case Opcode::I32TruncSatF64U: |
1667 | 18.5k | case Opcode::I64TruncSatF32S: |
1668 | 19.9k | case Opcode::I64TruncSatF32U: |
1669 | 21.5k | case Opcode::I64TruncSatF64S: |
1670 | 25.1k | case Opcode::I64TruncSatF64U: |
1671 | 25.1k | CALLBACK(OnConvertExpr, opcode); |
1672 | 25.1k | CALLBACK0(OnOpcodeBare); |
1673 | 25.1k | break; |
1674 | | |
1675 | 25.1k | case Opcode::MemoryAtomicNotify: { |
1676 | 2.73k | Address alignment_log2; |
1677 | 2.73k | Index memidx; |
1678 | 2.73k | Address offset; |
1679 | 2.73k | CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset, |
1680 | 2.73k | "notify alignment", "notify memidx", |
1681 | 2.73k | "notify offset")); |
1682 | 2.71k | CALLBACK(OnAtomicNotifyExpr, opcode, memidx, alignment_log2, offset); |
1683 | 2.71k | CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset)); |
1684 | 2.71k | break; |
1685 | 2.71k | } |
1686 | | |
1687 | 2.71k | case Opcode::MemoryAtomicWait32: |
1688 | 1.24k | case Opcode::MemoryAtomicWait64: { |
1689 | 1.24k | Address alignment_log2; |
1690 | 1.24k | Index memidx; |
1691 | 1.24k | Address offset; |
1692 | 1.24k | CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset, |
1693 | 1.24k | "wait alignment", "wait memidx", |
1694 | 1.24k | "wait offset")); |
1695 | 1.18k | CALLBACK(OnAtomicWaitExpr, opcode, memidx, alignment_log2, offset); |
1696 | 1.18k | CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset)); |
1697 | 1.18k | break; |
1698 | 1.18k | } |
1699 | | |
1700 | 1.18k | case Opcode::AtomicFence: { |
1701 | 537 | uint8_t consistency_model; |
1702 | 537 | CHECK_RESULT(ReadU8(&consistency_model, "consistency model")); |
1703 | 520 | ERROR_UNLESS(consistency_model == 0, |
1704 | 473 | "atomic.fence consistency model must be 0"); |
1705 | 473 | CALLBACK(OnAtomicFenceExpr, consistency_model); |
1706 | 473 | CALLBACK(OnOpcodeUint32, consistency_model); |
1707 | 473 | break; |
1708 | 473 | } |
1709 | | |
1710 | 900 | case Opcode::I32AtomicLoad8U: |
1711 | 1.63k | case Opcode::I32AtomicLoad16U: |
1712 | 2.52k | case Opcode::I64AtomicLoad8U: |
1713 | 2.91k | case Opcode::I64AtomicLoad16U: |
1714 | 3.38k | case Opcode::I64AtomicLoad32U: |
1715 | 3.73k | case Opcode::I32AtomicLoad: |
1716 | 4.48k | case Opcode::I64AtomicLoad: { |
1717 | 4.48k | Address alignment_log2; |
1718 | 4.48k | Index memidx; |
1719 | 4.48k | Address offset; |
1720 | 4.48k | CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset, |
1721 | 4.48k | "load alignment", "load memidx", |
1722 | 4.48k | "load offset")); |
1723 | 4.34k | CALLBACK(OnAtomicLoadExpr, opcode, memidx, alignment_log2, offset); |
1724 | 4.34k | CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset)); |
1725 | 4.34k | break; |
1726 | 4.34k | } |
1727 | | |
1728 | 4.34k | case Opcode::I32AtomicStore8: |
1729 | 865 | case Opcode::I32AtomicStore16: |
1730 | 1.25k | case Opcode::I64AtomicStore8: |
1731 | 1.72k | case Opcode::I64AtomicStore16: |
1732 | 2.04k | case Opcode::I64AtomicStore32: |
1733 | 2.33k | case Opcode::I32AtomicStore: |
1734 | 2.75k | case Opcode::I64AtomicStore: { |
1735 | 2.75k | Address alignment_log2; |
1736 | 2.75k | Index memidx; |
1737 | 2.75k | Address offset; |
1738 | 2.75k | CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset, |
1739 | 2.75k | "store alignment", "store memidx", |
1740 | 2.75k | "store offset")); |
1741 | 2.65k | CALLBACK(OnAtomicStoreExpr, opcode, memidx, alignment_log2, offset); |
1742 | 2.65k | CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset)); |
1743 | 2.65k | break; |
1744 | 2.65k | } |
1745 | | |
1746 | 2.65k | case Opcode::I32AtomicRmwAdd: |
1747 | 1.36k | case Opcode::I64AtomicRmwAdd: |
1748 | 1.80k | case Opcode::I32AtomicRmw8AddU: |
1749 | 2.29k | case Opcode::I32AtomicRmw16AddU: |
1750 | 2.77k | case Opcode::I64AtomicRmw8AddU: |
1751 | 3.50k | case Opcode::I64AtomicRmw16AddU: |
1752 | 4.41k | case Opcode::I64AtomicRmw32AddU: |
1753 | 5.24k | case Opcode::I32AtomicRmwSub: |
1754 | 5.71k | case Opcode::I64AtomicRmwSub: |
1755 | 6.21k | case Opcode::I32AtomicRmw8SubU: |
1756 | 6.62k | case Opcode::I32AtomicRmw16SubU: |
1757 | 6.98k | case Opcode::I64AtomicRmw8SubU: |
1758 | 7.54k | case Opcode::I64AtomicRmw16SubU: |
1759 | 8.35k | case Opcode::I64AtomicRmw32SubU: |
1760 | 8.93k | case Opcode::I32AtomicRmwAnd: |
1761 | 9.35k | case Opcode::I64AtomicRmwAnd: |
1762 | 9.80k | case Opcode::I32AtomicRmw8AndU: |
1763 | 10.2k | case Opcode::I32AtomicRmw16AndU: |
1764 | 11.8k | case Opcode::I64AtomicRmw8AndU: |
1765 | 12.4k | case Opcode::I64AtomicRmw16AndU: |
1766 | 12.9k | case Opcode::I64AtomicRmw32AndU: |
1767 | 13.4k | case Opcode::I32AtomicRmwOr: |
1768 | 14.3k | case Opcode::I64AtomicRmwOr: |
1769 | 14.7k | case Opcode::I32AtomicRmw8OrU: |
1770 | 15.1k | case Opcode::I32AtomicRmw16OrU: |
1771 | 15.5k | case Opcode::I64AtomicRmw8OrU: |
1772 | 16.1k | case Opcode::I64AtomicRmw16OrU: |
1773 | 16.6k | case Opcode::I64AtomicRmw32OrU: |
1774 | 17.1k | case Opcode::I32AtomicRmwXor: |
1775 | 18.4k | case Opcode::I64AtomicRmwXor: |
1776 | 18.7k | case Opcode::I32AtomicRmw8XorU: |
1777 | 19.1k | case Opcode::I32AtomicRmw16XorU: |
1778 | 19.6k | case Opcode::I64AtomicRmw8XorU: |
1779 | 19.9k | case Opcode::I64AtomicRmw16XorU: |
1780 | 20.5k | case Opcode::I64AtomicRmw32XorU: |
1781 | 21.2k | case Opcode::I32AtomicRmwXchg: |
1782 | 21.7k | case Opcode::I64AtomicRmwXchg: |
1783 | 22.3k | case Opcode::I32AtomicRmw8XchgU: |
1784 | 22.8k | case Opcode::I32AtomicRmw16XchgU: |
1785 | 23.7k | case Opcode::I64AtomicRmw8XchgU: |
1786 | 24.3k | case Opcode::I64AtomicRmw16XchgU: |
1787 | 24.8k | case Opcode::I64AtomicRmw32XchgU: { |
1788 | 24.8k | Address alignment_log2; |
1789 | 24.8k | Index memidx; |
1790 | 24.8k | Address offset; |
1791 | 24.8k | CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset, |
1792 | 24.8k | "memory alignment", "memory memidx", |
1793 | 24.8k | "memory offset")); |
1794 | 24.1k | CALLBACK(OnAtomicRmwExpr, opcode, memidx, alignment_log2, offset); |
1795 | 24.1k | CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset)); |
1796 | 24.1k | break; |
1797 | 24.1k | } |
1798 | | |
1799 | 24.1k | case Opcode::I32AtomicRmwCmpxchg: |
1800 | 990 | case Opcode::I64AtomicRmwCmpxchg: |
1801 | 1.61k | case Opcode::I32AtomicRmw8CmpxchgU: |
1802 | 1.94k | case Opcode::I32AtomicRmw16CmpxchgU: |
1803 | 2.25k | case Opcode::I64AtomicRmw8CmpxchgU: |
1804 | 2.53k | case Opcode::I64AtomicRmw16CmpxchgU: |
1805 | 2.88k | case Opcode::I64AtomicRmw32CmpxchgU: { |
1806 | 2.88k | Address alignment_log2; |
1807 | 2.88k | Index memidx; |
1808 | 2.88k | Address offset; |
1809 | 2.88k | CHECK_RESULT(ReadMemLocation(&alignment_log2, &memidx, &offset, |
1810 | 2.88k | "memory alignment", "memory memidx", |
1811 | 2.88k | "memory offset")); |
1812 | 2.75k | CALLBACK(OnAtomicRmwCmpxchgExpr, opcode, memidx, alignment_log2, |
1813 | 2.75k | offset); |
1814 | 2.75k | CHECK_RESULT(CallbackMemLocation(&alignment_log2, &memidx, &offset)); |
1815 | 2.75k | break; |
1816 | 2.75k | } |
1817 | | |
1818 | 2.75k | case Opcode::TableInit: { |
1819 | 1.35k | Index segment; |
1820 | 1.35k | CHECK_RESULT(ReadIndex(&segment, "elem segment index")); |
1821 | 1.34k | Index table_index; |
1822 | 1.34k | CHECK_RESULT(ReadIndex(&table_index, "reserved table index")); |
1823 | 1.32k | CALLBACK(OnTableInitExpr, segment, table_index); |
1824 | 1.32k | CALLBACK(OnOpcodeUint32Uint32, segment, table_index); |
1825 | 1.32k | break; |
1826 | 1.32k | } |
1827 | | |
1828 | 1.32k | case Opcode::MemoryInit: { |
1829 | 426 | Index segment; |
1830 | 426 | ERROR_IF(data_count_ == kInvalidIndex, |
1831 | 426 | "memory.init requires data count section"); |
1832 | 406 | CHECK_RESULT(ReadIndex(&segment, "elem segment index")); |
1833 | 286 | Index memidx = 0; |
1834 | 286 | if (!options_.features.multi_memory_enabled()) { |
1835 | 102 | uint8_t reserved; |
1836 | 102 | CHECK_RESULT(ReadU8(&reserved, "reserved memory index")); |
1837 | 99 | ERROR_UNLESS(reserved == 0, "reserved value must be 0"); |
1838 | 184 | } else { |
1839 | 184 | CHECK_RESULT(ReadMemidx(&memidx, "memory.init memidx")); |
1840 | 184 | } |
1841 | 262 | CALLBACK(OnMemoryInitExpr, segment, memidx); |
1842 | 262 | CALLBACK(OnOpcodeUint32Uint32, segment, memidx); |
1843 | 262 | break; |
1844 | 262 | } |
1845 | | |
1846 | 826 | case Opcode::DataDrop: |
1847 | 826 | ERROR_IF(data_count_ == kInvalidIndex, |
1848 | 826 | "data.drop requires data count section"); |
1849 | 812 | [[fallthrough]]; |
1850 | 4.55k | case Opcode::ElemDrop: { |
1851 | 4.55k | Index segment; |
1852 | 4.55k | CHECK_RESULT(ReadIndex(&segment, "segment index")); |
1853 | 4.52k | if (opcode == Opcode::DataDrop) { |
1854 | 804 | CALLBACK(OnDataDropExpr, segment); |
1855 | 3.72k | } else { |
1856 | 3.72k | CALLBACK(OnElemDropExpr, segment); |
1857 | 3.72k | } |
1858 | 4.52k | CALLBACK(OnOpcodeUint32, segment); |
1859 | 4.52k | break; |
1860 | 4.52k | } |
1861 | | |
1862 | 12.6k | case Opcode::MemoryFill: { |
1863 | 12.6k | Index memidx = 0; |
1864 | 12.6k | if (!options_.features.multi_memory_enabled()) { |
1865 | 2.96k | uint8_t reserved; |
1866 | 2.96k | CHECK_RESULT(ReadU8(&reserved, "memory.fill reserved")); |
1867 | 2.95k | ERROR_UNLESS(reserved == 0, "memory.fill reserved value must be 0"); |
1868 | 9.66k | } else { |
1869 | 9.66k | CHECK_RESULT(ReadMemidx(&memidx, "memory.fill memidx")); |
1870 | 9.66k | } |
1871 | 12.5k | CALLBACK(OnMemoryFillExpr, memidx); |
1872 | 12.5k | CALLBACK(OnOpcodeUint32, memidx); |
1873 | 12.5k | break; |
1874 | 12.5k | } |
1875 | | |
1876 | 12.5k | case Opcode::MemoryCopy: { |
1877 | 3.38k | Index destmemidx = 0; |
1878 | 3.38k | Index srcmemidx = 0; |
1879 | 3.38k | if (!options_.features.multi_memory_enabled()) { |
1880 | 1.38k | uint8_t reserved; |
1881 | 1.38k | CHECK_RESULT(ReadU8(&reserved, "reserved memory index")); |
1882 | 1.37k | ERROR_UNLESS(reserved == 0, "reserved value must be 0"); |
1883 | 1.36k | CHECK_RESULT(ReadU8(&reserved, "reserved memory index")); |
1884 | 1.35k | ERROR_UNLESS(reserved == 0, "reserved value must be 0"); |
1885 | 2.00k | } else { |
1886 | 2.00k | CHECK_RESULT(ReadMemidx(&destmemidx, "memory.copy destmemindex")); |
1887 | 1.98k | CHECK_RESULT(ReadMemidx(&srcmemidx, "memory.copy srcmemidx")); |
1888 | 1.98k | } |
1889 | 3.31k | CALLBACK(OnMemoryCopyExpr, destmemidx, srcmemidx); |
1890 | 3.31k | CALLBACK(OnOpcodeUint32Uint32, destmemidx, srcmemidx); |
1891 | 3.31k | break; |
1892 | 3.31k | } |
1893 | | |
1894 | 3.31k | case Opcode::TableCopy: { |
1895 | 1.91k | Index table_dst; |
1896 | 1.91k | Index table_src; |
1897 | 1.91k | CHECK_RESULT(ReadIndex(&table_dst, "reserved table index")); |
1898 | 1.89k | CHECK_RESULT(ReadIndex(&table_src, "table src")); |
1899 | 1.88k | CALLBACK(OnTableCopyExpr, table_dst, table_src); |
1900 | 1.88k | CALLBACK(OnOpcodeUint32Uint32, table_dst, table_src); |
1901 | 1.88k | break; |
1902 | 1.88k | } |
1903 | | |
1904 | 16.0k | case Opcode::TableGet: { |
1905 | 16.0k | Index table; |
1906 | 16.0k | CHECK_RESULT(ReadIndex(&table, "table index")); |
1907 | 15.9k | CALLBACK(OnTableGetExpr, table); |
1908 | 15.9k | CALLBACK(OnOpcodeUint32, table); |
1909 | 15.9k | break; |
1910 | 15.9k | } |
1911 | | |
1912 | 15.9k | case Opcode::TableSet: { |
1913 | 15.1k | Index table; |
1914 | 15.1k | CHECK_RESULT(ReadIndex(&table, "table index")); |
1915 | 15.1k | CALLBACK(OnTableSetExpr, table); |
1916 | 15.1k | CALLBACK(OnOpcodeUint32, table); |
1917 | 15.1k | break; |
1918 | 15.1k | } |
1919 | | |
1920 | 15.1k | case Opcode::TableGrow: { |
1921 | 3.95k | Index table; |
1922 | 3.95k | CHECK_RESULT(ReadIndex(&table, "table index")); |
1923 | 3.92k | CALLBACK(OnTableGrowExpr, table); |
1924 | 3.92k | CALLBACK(OnOpcodeUint32, table); |
1925 | 3.92k | break; |
1926 | 3.92k | } |
1927 | | |
1928 | 3.92k | case Opcode::TableSize: { |
1929 | 1.35k | Index table; |
1930 | 1.35k | CHECK_RESULT(ReadIndex(&table, "table index")); |
1931 | 1.32k | CALLBACK(OnTableSizeExpr, table); |
1932 | 1.32k | CALLBACK(OnOpcodeUint32, table); |
1933 | 1.32k | break; |
1934 | 1.32k | } |
1935 | | |
1936 | 5.56k | case Opcode::TableFill: { |
1937 | 5.56k | Index table; |
1938 | 5.56k | CHECK_RESULT(ReadIndex(&table, "table index")); |
1939 | 5.55k | CALLBACK(OnTableFillExpr, table); |
1940 | 5.55k | CALLBACK(OnOpcodeUint32, table); |
1941 | 5.55k | break; |
1942 | 5.55k | } |
1943 | | |
1944 | 5.55k | case Opcode::RefAsNonNull: |
1945 | 1.41k | CALLBACK(OnRefAsNonNullExpr); |
1946 | 1.41k | CALLBACK(OnOpcodeBare); |
1947 | 1.41k | break; |
1948 | | |
1949 | 4.73k | case Opcode::RefFunc: { |
1950 | 4.73k | Index func; |
1951 | 4.73k | CHECK_RESULT(ReadIndex(&func, "func index")); |
1952 | 4.70k | CALLBACK(OnRefFuncExpr, func); |
1953 | 4.69k | CALLBACK(OnOpcodeUint32, func); |
1954 | 4.69k | break; |
1955 | 4.69k | } |
1956 | | |
1957 | 13.1k | case Opcode::RefNull: { |
1958 | 13.1k | uint64_t heap_type; |
1959 | 13.1k | Type type; |
1960 | 13.1k | CHECK_RESULT(ReadS64Leb128(&heap_type, "ref.null type")); |
1961 | | |
1962 | 12.9k | if (static_cast<int64_t>(heap_type) < 0 || |
1963 | 9.15k | static_cast<int64_t>(heap_type) >= kInvalidIndex) { |
1964 | 9.15k | Type::Enum type_code = static_cast<Type::Enum>(heap_type); |
1965 | 9.15k | ERROR_UNLESS(IsConcreteReferenceType(type_code), |
1966 | 8.31k | "expected valid ref.null type (got " PRItypecode ")", |
1967 | 8.31k | WABT_PRINTF_TYPE_CODE(type_code)); |
1968 | 8.31k | type = Type(type_code); |
1969 | 8.31k | } else { |
1970 | 3.80k | ERROR_UNLESS(options_.features.function_references_enabled(), |
1971 | 3.72k | "function references are not enabled for ref.null"); |
1972 | 3.72k | type = Type(Type::RefNull, static_cast<Index>(heap_type)); |
1973 | 3.72k | } |
1974 | | |
1975 | 12.0k | CALLBACK(OnRefNullExpr, type); |
1976 | 12.0k | CALLBACK(OnOpcodeType, type); |
1977 | 12.0k | break; |
1978 | 12.0k | } |
1979 | | |
1980 | 12.0k | case Opcode::RefIsNull: |
1981 | 4.25k | CALLBACK(OnRefIsNullExpr); |
1982 | 4.25k | CALLBACK(OnOpcodeBare); |
1983 | 4.25k | break; |
1984 | | |
1985 | 4.79k | case Opcode::CallRef: { |
1986 | 4.79k | uint32_t type; |
1987 | 4.79k | CHECK_RESULT(ReadU32Leb128(&type, "call_ref type")); |
1988 | | |
1989 | 4.73k | Type sig_type(Type::RefNull, type); |
1990 | 4.73k | CALLBACK(OnCallRefExpr, sig_type); |
1991 | 4.73k | CALLBACK(OnOpcodeType, sig_type); |
1992 | 4.73k | break; |
1993 | 4.73k | } |
1994 | | |
1995 | 4.73k | case Opcode::ReturnCallRef: { |
1996 | 4.32k | uint32_t type; |
1997 | 4.32k | CHECK_RESULT(ReadU32Leb128(&type, "return_call_ref type")); |
1998 | | |
1999 | 4.28k | Type sig_type(Type::RefNull, type); |
2000 | 4.28k | CALLBACK(OnReturnCallRefExpr, sig_type); |
2001 | 4.28k | CALLBACK(OnOpcodeType, sig_type); |
2002 | 4.28k | break; |
2003 | 4.28k | } |
2004 | | |
2005 | 4.60k | default: |
2006 | 4.60k | return ReportUnexpectedOpcode(opcode); |
2007 | 14.6M | } |
2008 | 14.6M | } |
2009 | | |
2010 | 15.0k | PrintError("%s must end with END opcode", context); |
2011 | 15.0k | return Result::Error; |
2012 | 122k | } |
2013 | | |
2014 | 183k | Result BinaryReader::ReadNameSection(Offset section_size) { |
2015 | 183k | CALLBACK(BeginNamesSection, section_size); |
2016 | 183k | Index i = 0; |
2017 | 183k | uint32_t previous_subsection_type = 0; |
2018 | 567k | while (state_.offset < read_end_) { |
2019 | 553k | uint32_t name_type; |
2020 | 553k | Offset subsection_size; |
2021 | 553k | CHECK_RESULT(ReadU32Leb128(&name_type, "name type")); |
2022 | 552k | if (i != 0) { |
2023 | 369k | ERROR_UNLESS(name_type != previous_subsection_type, |
2024 | 361k | "duplicate sub-section"); |
2025 | 361k | ERROR_UNLESS(name_type >= previous_subsection_type, |
2026 | 361k | "out-of-order sub-section"); |
2027 | 361k | } |
2028 | 455k | previous_subsection_type = name_type; |
2029 | 455k | CHECK_RESULT(ReadOffset(&subsection_size, "subsection size")); |
2030 | 434k | size_t subsection_end = state_.offset + subsection_size; |
2031 | 434k | ERROR_UNLESS(subsection_end <= read_end_, |
2032 | 432k | "invalid sub-section size: extends past end"); |
2033 | 432k | ReadEndRestoreGuard guard(this); |
2034 | 432k | read_end_ = subsection_end; |
2035 | | |
2036 | 432k | NameSectionSubsection type = static_cast<NameSectionSubsection>(name_type); |
2037 | 432k | if (type <= NameSectionSubsection::Last) { |
2038 | 169k | CALLBACK(OnNameSubsection, i, type, subsection_size); |
2039 | 169k | } |
2040 | | |
2041 | 432k | switch (type) { |
2042 | 117k | case NameSectionSubsection::Module: |
2043 | 117k | CALLBACK(OnModuleNameSubsection, i, name_type, subsection_size); |
2044 | 117k | if (subsection_size) { |
2045 | 106k | std::string_view name; |
2046 | 106k | CHECK_RESULT(ReadStr(&name, "module name")); |
2047 | 99.9k | CALLBACK(OnModuleName, name); |
2048 | 99.9k | } |
2049 | 110k | break; |
2050 | 110k | case NameSectionSubsection::Function: |
2051 | 4.72k | CALLBACK(OnFunctionNameSubsection, i, name_type, subsection_size); |
2052 | 4.72k | if (subsection_size) { |
2053 | 3.82k | Index num_names; |
2054 | 3.82k | CHECK_RESULT(ReadCount(&num_names, "name count")); |
2055 | 3.72k | CALLBACK(OnFunctionNamesCount, num_names); |
2056 | 3.72k | Index last_function_index = kInvalidIndex; |
2057 | | |
2058 | 12.0k | for (Index j = 0; j < num_names; ++j) { |
2059 | 11.8k | Index function_index; |
2060 | 11.8k | std::string_view function_name; |
2061 | | |
2062 | 11.8k | CHECK_RESULT(ReadIndex(&function_index, "function index")); |
2063 | 11.6k | ERROR_UNLESS(function_index != last_function_index, |
2064 | 11.6k | "duplicate function name: %u", function_index); |
2065 | 11.6k | ERROR_UNLESS(last_function_index == kInvalidIndex || |
2066 | 9.33k | function_index > last_function_index, |
2067 | 9.33k | "function index out of order: %u", function_index); |
2068 | 9.33k | last_function_index = function_index; |
2069 | 9.33k | ERROR_UNLESS(function_index < NumTotalFuncs(), |
2070 | 8.76k | "invalid function index: %" PRIindex, function_index); |
2071 | 8.76k | CHECK_RESULT(ReadStr(&function_name, "function name")); |
2072 | 8.37k | CALLBACK(OnFunctionName, function_index, function_name); |
2073 | 8.37k | } |
2074 | 3.72k | } |
2075 | 1.14k | break; |
2076 | 24.9k | case NameSectionSubsection::Local: |
2077 | 24.9k | CALLBACK(OnLocalNameSubsection, i, name_type, subsection_size); |
2078 | 24.9k | if (subsection_size) { |
2079 | 24.5k | Index num_funcs; |
2080 | 24.5k | CHECK_RESULT(ReadCount(&num_funcs, "function count")); |
2081 | 24.2k | CALLBACK(OnLocalNameFunctionCount, num_funcs); |
2082 | 24.2k | Index last_function_index = kInvalidIndex; |
2083 | 51.2k | for (Index j = 0; j < num_funcs; ++j) { |
2084 | 48.5k | Index function_index; |
2085 | 48.5k | CHECK_RESULT(ReadIndex(&function_index, "function index")); |
2086 | 44.9k | ERROR_UNLESS(function_index < NumTotalFuncs(), |
2087 | 41.5k | "invalid function index: %u", function_index); |
2088 | 41.5k | ERROR_UNLESS(last_function_index == kInvalidIndex || |
2089 | 40.2k | function_index > last_function_index, |
2090 | 40.2k | "locals function index out of order: %u", |
2091 | 40.2k | function_index); |
2092 | 40.2k | last_function_index = function_index; |
2093 | 40.2k | Index num_locals; |
2094 | 40.2k | CHECK_RESULT(ReadCount(&num_locals, "local count")); |
2095 | 36.0k | CALLBACK(OnLocalNameLocalCount, function_index, num_locals); |
2096 | 36.0k | Index last_local_index = kInvalidIndex; |
2097 | 66.6k | for (Index k = 0; k < num_locals; ++k) { |
2098 | 39.6k | Index local_index; |
2099 | 39.6k | std::string_view local_name; |
2100 | | |
2101 | 39.6k | CHECK_RESULT(ReadIndex(&local_index, "named index")); |
2102 | 38.0k | ERROR_UNLESS(local_index != last_local_index, |
2103 | 36.5k | "duplicate local index: %u", local_index); |
2104 | 36.5k | ERROR_UNLESS(last_local_index == kInvalidIndex || |
2105 | 31.1k | local_index > last_local_index, |
2106 | 31.1k | "local index out of order: %u", local_index); |
2107 | 31.1k | last_local_index = local_index; |
2108 | 31.1k | CHECK_RESULT(ReadStr(&local_name, "name")); |
2109 | 30.6k | CALLBACK(OnLocalName, function_index, local_index, local_name); |
2110 | 30.6k | } |
2111 | 36.0k | } |
2112 | 24.2k | } |
2113 | 3.20k | break; |
2114 | 3.20k | case NameSectionSubsection::Label: |
2115 | | // TODO(sbc): Implement label names. These are slightly more complicated |
2116 | | // since they refer to offsets in the code section / instruction stream. |
2117 | 270 | state_.offset = subsection_end; |
2118 | 270 | break; |
2119 | 4.77k | case NameSectionSubsection::Type: |
2120 | 9.50k | case NameSectionSubsection::Table: |
2121 | 9.71k | case NameSectionSubsection::Memory: |
2122 | 10.7k | case NameSectionSubsection::Global: |
2123 | 14.4k | case NameSectionSubsection::ElemSegment: |
2124 | 20.9k | case NameSectionSubsection::DataSegment: |
2125 | 21.5k | case NameSectionSubsection::Tag: |
2126 | 21.5k | if (subsection_size) { |
2127 | 16.7k | Index num_names; |
2128 | 16.7k | CHECK_RESULT(ReadCount(&num_names, "name count")); |
2129 | 12.4k | CALLBACK(OnNameCount, num_names); |
2130 | 53.9k | for (Index j = 0; j < num_names; ++j) { |
2131 | 50.0k | Index index; |
2132 | 50.0k | std::string_view name; |
2133 | | |
2134 | 50.0k | CHECK_RESULT(ReadIndex(&index, "index")); |
2135 | 48.1k | CHECK_RESULT(ReadStr(&name, "name")); |
2136 | 41.4k | CALLBACK(OnNameEntry, type, index, name); |
2137 | 41.4k | } |
2138 | 12.4k | } |
2139 | 8.69k | state_.offset = subsection_end; |
2140 | 8.69k | break; |
2141 | 263k | default: |
2142 | | // Unknown subsection, skip it. |
2143 | 263k | state_.offset = subsection_end; |
2144 | 263k | break; |
2145 | 432k | } |
2146 | 387k | ++i; |
2147 | 387k | ERROR_UNLESS(state_.offset == subsection_end, |
2148 | 387k | "unfinished sub-section (expected end: 0x%" PRIzx ")", |
2149 | 387k | subsection_end); |
2150 | 387k | } |
2151 | 14.6k | CALLBACK0(EndNamesSection); |
2152 | 14.6k | return Result::Ok; |
2153 | 14.6k | } |
2154 | | |
2155 | 43.7k | Result BinaryReader::ReadRelocSection(Offset section_size) { |
2156 | 43.7k | CALLBACK(BeginRelocSection, section_size); |
2157 | 43.7k | uint32_t section_index; |
2158 | 43.7k | CHECK_RESULT(ReadU32Leb128(§ion_index, "section index")); |
2159 | 43.2k | Index num_relocs; |
2160 | 43.2k | CHECK_RESULT(ReadCount(&num_relocs, "relocation count")); |
2161 | 41.8k | CALLBACK(OnRelocCount, num_relocs, section_index); |
2162 | 179k | for (Index i = 0; i < num_relocs; ++i) { |
2163 | 165k | Offset offset; |
2164 | 165k | Index index; |
2165 | 165k | uint32_t reloc_type, addend = 0; |
2166 | 165k | CHECK_RESULT(ReadU32Leb128(&reloc_type, "relocation type")); |
2167 | 164k | CHECK_RESULT(ReadOffset(&offset, "offset")); |
2168 | 162k | CHECK_RESULT(ReadIndex(&index, "index")); |
2169 | 154k | RelocType type = static_cast<RelocType>(reloc_type); |
2170 | 154k | switch (type) { |
2171 | 1.39k | case RelocType::MemoryAddressLEB: |
2172 | 5.41k | case RelocType::MemoryAddressLEB64: |
2173 | 7.67k | case RelocType::MemoryAddressSLEB: |
2174 | 10.5k | case RelocType::MemoryAddressSLEB64: |
2175 | 17.3k | case RelocType::MemoryAddressRelSLEB: |
2176 | 20.3k | case RelocType::MemoryAddressRelSLEB64: |
2177 | 21.4k | case RelocType::MemoryAddressI32: |
2178 | 23.0k | case RelocType::MemoryAddressI64: |
2179 | 24.3k | case RelocType::MemoryAddressLocRelI32: |
2180 | 25.7k | case RelocType::FunctionOffsetI32: |
2181 | 26.7k | case RelocType::FunctionOffsetI64: |
2182 | 29.1k | case RelocType::SectionOffsetI32: |
2183 | 32.3k | case RelocType::MemoryAddressTLSSLEB: |
2184 | 33.2k | case RelocType::MemoryAddressTLSSLEB64: |
2185 | 33.2k | CHECK_RESULT(ReadS32Leb128(&addend, "addend")); |
2186 | 29.9k | break; |
2187 | | |
2188 | 69.0k | case RelocType::FuncIndexLEB: |
2189 | 70.2k | case RelocType::FuncIndexI32: |
2190 | 72.3k | case RelocType::TableIndexSLEB: |
2191 | 73.4k | case RelocType::TableIndexSLEB64: |
2192 | 74.3k | case RelocType::TableIndexI32: |
2193 | 77.1k | case RelocType::TableIndexI64: |
2194 | 78.5k | case RelocType::TypeIndexLEB: |
2195 | 80.4k | case RelocType::GlobalIndexLEB: |
2196 | 81.6k | case RelocType::GlobalIndexI32: |
2197 | 83.4k | case RelocType::TagIndexLEB: |
2198 | 84.7k | case RelocType::TableIndexRelSLEB: |
2199 | 85.5k | case RelocType::TableIndexRelSLEB64: |
2200 | 111k | case RelocType::TableNumberLEB: |
2201 | 111k | break; |
2202 | | |
2203 | 9.76k | default: |
2204 | 9.76k | PrintError("unknown reloc type: %s", GetRelocTypeName(type)); |
2205 | 9.76k | return Result::Error; |
2206 | 154k | } |
2207 | 141k | CALLBACK(OnReloc, type, offset, index, addend); |
2208 | 141k | } |
2209 | 14.0k | CALLBACK0(EndRelocSection); |
2210 | 14.0k | return Result::Ok; |
2211 | 14.0k | } |
2212 | | |
2213 | 49.8k | Result BinaryReader::ReadDylink0Section(Offset section_size) { |
2214 | 49.8k | CALLBACK(BeginDylinkSection, section_size); |
2215 | | |
2216 | 215k | while (state_.offset < read_end_) { |
2217 | 213k | uint32_t dylink_type; |
2218 | 213k | Offset subsection_size; |
2219 | 213k | CHECK_RESULT(ReadU32Leb128(&dylink_type, "type")); |
2220 | 206k | CHECK_RESULT(ReadOffset(&subsection_size, "subsection size")); |
2221 | 193k | size_t subsection_end = state_.offset + subsection_size; |
2222 | 193k | ERROR_UNLESS(subsection_end <= read_end_, |
2223 | 191k | "invalid sub-section size: extends past end"); |
2224 | 191k | ReadEndRestoreGuard guard(this); |
2225 | 191k | read_end_ = subsection_end; |
2226 | | |
2227 | 191k | uint32_t count; |
2228 | 191k | switch (static_cast<DylinkEntryType>(dylink_type)) { |
2229 | 4.57k | case DylinkEntryType::MemInfo: { |
2230 | 4.57k | uint32_t mem_size; |
2231 | 4.57k | uint32_t mem_align; |
2232 | 4.57k | uint32_t table_size; |
2233 | 4.57k | uint32_t table_align; |
2234 | | |
2235 | 4.57k | CHECK_RESULT(ReadU32Leb128(&mem_size, "mem_size")); |
2236 | 4.03k | CHECK_RESULT(ReadU32Leb128(&mem_align, "mem_align")); |
2237 | 3.43k | CHECK_RESULT(ReadU32Leb128(&table_size, "table_size")); |
2238 | 2.91k | CHECK_RESULT(ReadU32Leb128(&table_align, "table_align")); |
2239 | 1.94k | CALLBACK(OnDylinkInfo, mem_size, mem_align, table_size, table_align); |
2240 | 1.94k | break; |
2241 | 1.94k | } |
2242 | 6.37k | case DylinkEntryType::Needed: |
2243 | 6.37k | CHECK_RESULT(ReadU32Leb128(&count, "needed_dynlibs")); |
2244 | 5.48k | CALLBACK(OnDylinkNeededCount, count); |
2245 | 9.82k | while (count--) { |
2246 | 6.88k | std::string_view so_name; |
2247 | 6.88k | CHECK_RESULT(ReadStr(&so_name, "dylib so_name")); |
2248 | 4.34k | CALLBACK(OnDylinkNeeded, so_name); |
2249 | 4.34k | } |
2250 | 2.93k | break; |
2251 | 27.3k | case DylinkEntryType::ImportInfo: |
2252 | 27.3k | CHECK_RESULT(ReadU32Leb128(&count, "count")); |
2253 | 26.6k | CALLBACK(OnDylinkImportCount, count); |
2254 | 58.8k | for (Index i = 0; i < count; ++i) { |
2255 | 44.3k | uint32_t flags = 0; |
2256 | 44.3k | std::string_view module; |
2257 | 44.3k | std::string_view field; |
2258 | 44.3k | CHECK_RESULT(ReadStr(&module, "module")); |
2259 | 35.9k | CHECK_RESULT(ReadStr(&field, "field")); |
2260 | 33.3k | CHECK_RESULT(ReadU32Leb128(&flags, "flags")); |
2261 | 32.6k | CALLBACK(OnDylinkImport, module, field, flags); |
2262 | 32.6k | } |
2263 | 14.5k | break; |
2264 | 14.5k | case DylinkEntryType::ExportInfo: |
2265 | 6.31k | CHECK_RESULT(ReadU32Leb128(&count, "count")); |
2266 | 5.88k | CALLBACK(OnDylinkExportCount, count); |
2267 | 12.1k | for (Index i = 0; i < count; ++i) { |
2268 | 9.07k | uint32_t flags = 0; |
2269 | 9.07k | std::string_view name; |
2270 | 9.07k | CHECK_RESULT(ReadStr(&name, "name")); |
2271 | 7.74k | CHECK_RESULT(ReadU32Leb128(&flags, "flags")); |
2272 | 6.35k | CALLBACK(OnDylinkExport, name, flags); |
2273 | 6.35k | } |
2274 | 3.07k | break; |
2275 | 146k | default: |
2276 | | // Unknown subsection, skip it. |
2277 | 146k | state_.offset = subsection_end; |
2278 | 146k | break; |
2279 | 191k | } |
2280 | 169k | ERROR_UNLESS(state_.offset == subsection_end, |
2281 | 169k | "unfinished sub-section (expected end: 0x%" PRIzx ")", |
2282 | 169k | subsection_end); |
2283 | 169k | } |
2284 | | |
2285 | 2.37k | CALLBACK0(EndDylinkSection); |
2286 | 2.37k | return Result::Ok; |
2287 | 2.37k | } |
2288 | | |
2289 | 15.0k | Result BinaryReader::ReadDylinkSection(Offset section_size) { |
2290 | 15.0k | CALLBACK(BeginDylinkSection, section_size); |
2291 | 15.0k | uint32_t mem_size; |
2292 | 15.0k | uint32_t mem_align; |
2293 | 15.0k | uint32_t table_size; |
2294 | 15.0k | uint32_t table_align; |
2295 | | |
2296 | 15.0k | CHECK_RESULT(ReadU32Leb128(&mem_size, "mem_size")); |
2297 | 14.6k | CHECK_RESULT(ReadU32Leb128(&mem_align, "mem_align")); |
2298 | 14.3k | CHECK_RESULT(ReadU32Leb128(&table_size, "table_size")); |
2299 | 13.9k | CHECK_RESULT(ReadU32Leb128(&table_align, "table_align")); |
2300 | 13.5k | CALLBACK(OnDylinkInfo, mem_size, mem_align, table_size, table_align); |
2301 | | |
2302 | 13.5k | uint32_t count; |
2303 | 13.5k | CHECK_RESULT(ReadU32Leb128(&count, "needed_dynlibs")); |
2304 | 11.6k | CALLBACK(OnDylinkNeededCount, count); |
2305 | 17.6k | while (count--) { |
2306 | 7.75k | std::string_view so_name; |
2307 | 7.75k | CHECK_RESULT(ReadStr(&so_name, "dylib so_name")); |
2308 | 6.00k | CALLBACK(OnDylinkNeeded, so_name); |
2309 | 6.00k | } |
2310 | | |
2311 | 9.88k | CALLBACK0(EndDylinkSection); |
2312 | 9.88k | return Result::Ok; |
2313 | 9.88k | } |
2314 | | |
2315 | 35.1k | Result BinaryReader::ReadTargetFeaturesSections(Offset section_size) { |
2316 | 35.1k | CALLBACK(BeginTargetFeaturesSection, section_size); |
2317 | 35.1k | uint32_t count; |
2318 | 35.1k | CHECK_RESULT(ReadU32Leb128(&count, "sym count")); |
2319 | 34.1k | CALLBACK(OnFeatureCount, count); |
2320 | 138k | while (count--) { |
2321 | 126k | uint8_t prefix; |
2322 | 126k | std::string_view name; |
2323 | 126k | CHECK_RESULT(ReadU8(&prefix, "prefix")); |
2324 | 111k | CHECK_RESULT(ReadStr(&name, "feature name")); |
2325 | 104k | CALLBACK(OnFeature, prefix, name); |
2326 | 104k | } |
2327 | 11.8k | CALLBACK0(EndTargetFeaturesSection); |
2328 | 11.8k | return Result::Ok; |
2329 | 11.8k | } |
2330 | | |
2331 | | Result BinaryReader::ReadGenericCustomSection(std::string_view name, |
2332 | 2.43M | Offset section_size) { |
2333 | 2.43M | CALLBACK(BeginGenericCustomSection, section_size); |
2334 | 2.43M | const void* data; |
2335 | 2.43M | Offset custom_data_size = read_end_ - state_.offset; |
2336 | 2.43M | CHECK_RESULT( |
2337 | 2.43M | ReadBytesWithSize(&data, custom_data_size, "custom section data")); |
2338 | 2.43M | CALLBACK(OnGenericCustomSection, name, data, custom_data_size); |
2339 | 2.43M | CALLBACK0(EndGenericCustomSection); |
2340 | 2.43M | return Result::Ok; |
2341 | 2.43M | } |
2342 | | |
2343 | 192k | Result BinaryReader::ReadLinkingSection(Offset section_size) { |
2344 | 192k | CALLBACK(BeginLinkingSection, section_size); |
2345 | 192k | uint32_t version; |
2346 | 192k | CHECK_RESULT(ReadU32Leb128(&version, "version")); |
2347 | 191k | ERROR_UNLESS(version == 2, "invalid linking metadata version: %u", version); |
2348 | 357k | while (state_.offset < read_end_) { |
2349 | 306k | uint32_t linking_type; |
2350 | 306k | Offset subsection_size; |
2351 | 306k | CHECK_RESULT(ReadU32Leb128(&linking_type, "type")); |
2352 | 305k | CHECK_RESULT(ReadOffset(&subsection_size, "subsection size")); |
2353 | 301k | size_t subsection_end = state_.offset + subsection_size; |
2354 | 301k | ERROR_UNLESS(subsection_end <= read_end_, |
2355 | 299k | "invalid sub-section size: extends past end"); |
2356 | 299k | ReadEndRestoreGuard guard(this); |
2357 | 299k | read_end_ = subsection_end; |
2358 | | |
2359 | 299k | uint32_t count; |
2360 | 299k | switch (static_cast<LinkingEntryType>(linking_type)) { |
2361 | 153k | case LinkingEntryType::SymbolTable: |
2362 | 153k | CHECK_RESULT(ReadU32Leb128(&count, "sym count")); |
2363 | 153k | CALLBACK(OnSymbolCount, count); |
2364 | 714k | for (Index i = 0; i < count; ++i) { |
2365 | 654k | std::string_view name; |
2366 | 654k | uint32_t flags = 0; |
2367 | 654k | uint32_t kind = 0; |
2368 | 654k | CHECK_RESULT(ReadU32Leb128(&kind, "sym type")); |
2369 | 625k | CHECK_RESULT(ReadU32Leb128(&flags, "sym flags")); |
2370 | 611k | SymbolType sym_type = static_cast<SymbolType>(kind); |
2371 | 611k | switch (sym_type) { |
2372 | 177k | case SymbolType::Function: |
2373 | 250k | case SymbolType::Global: |
2374 | 296k | case SymbolType::Tag: |
2375 | 415k | case SymbolType::Table: { |
2376 | 415k | uint32_t index = 0; |
2377 | 415k | CHECK_RESULT(ReadU32Leb128(&index, "index")); |
2378 | 409k | if ((flags & WABT_SYMBOL_FLAG_UNDEFINED) == 0 || |
2379 | 117k | (flags & WABT_SYMBOL_FLAG_EXPLICIT_NAME) != 0) |
2380 | 370k | CHECK_RESULT(ReadStr(&name, "symbol name")); |
2381 | 389k | switch (sym_type) { |
2382 | 153k | case SymbolType::Function: |
2383 | 153k | CALLBACK(OnFunctionSymbol, i, flags, name, index); |
2384 | 152k | break; |
2385 | 152k | case SymbolType::Global: |
2386 | 72.5k | CALLBACK(OnGlobalSymbol, i, flags, name, index); |
2387 | 71.2k | break; |
2388 | 71.2k | case SymbolType::Tag: |
2389 | 44.8k | CALLBACK(OnTagSymbol, i, flags, name, index); |
2390 | 43.3k | break; |
2391 | 118k | case SymbolType::Table: |
2392 | 118k | CALLBACK(OnTableSymbol, i, flags, name, index); |
2393 | 114k | break; |
2394 | 114k | default: |
2395 | 0 | WABT_UNREACHABLE; |
2396 | 389k | } |
2397 | 381k | break; |
2398 | 389k | } |
2399 | 381k | case SymbolType::Data: { |
2400 | 53.3k | uint32_t segment = 0; |
2401 | 53.3k | uint32_t offset = 0; |
2402 | 53.3k | uint32_t size = 0; |
2403 | 53.3k | CHECK_RESULT(ReadStr(&name, "symbol name")); |
2404 | 50.1k | if ((flags & WABT_SYMBOL_FLAG_UNDEFINED) == 0) { |
2405 | 37.0k | CHECK_RESULT(ReadU32Leb128(&segment, "segment")); |
2406 | 36.3k | CHECK_RESULT(ReadU32Leb128(&offset, "offset")); |
2407 | 34.0k | CHECK_RESULT(ReadU32Leb128(&size, "size")); |
2408 | 34.0k | } |
2409 | 44.5k | CALLBACK(OnDataSymbol, i, flags, name, segment, offset, size); |
2410 | 40.5k | break; |
2411 | 44.5k | } |
2412 | 40.5k | case SymbolType::Section: { |
2413 | 13.8k | uint32_t index = 0; |
2414 | 13.8k | CHECK_RESULT(ReadU32Leb128(&index, "index")); |
2415 | 11.8k | CALLBACK(OnSectionSymbol, i, flags, index); |
2416 | 10.3k | break; |
2417 | 11.8k | } |
2418 | 611k | } |
2419 | 611k | } |
2420 | 59.9k | break; |
2421 | 59.9k | case LinkingEntryType::SegmentInfo: |
2422 | 20.3k | CHECK_RESULT(ReadU32Leb128(&count, "info count")); |
2423 | 19.6k | CALLBACK(OnSegmentInfoCount, count); |
2424 | 40.9k | for (Index i = 0; i < count; i++) { |
2425 | 31.8k | std::string_view name; |
2426 | 31.8k | Address alignment_log2; |
2427 | 31.8k | uint32_t flags; |
2428 | 31.8k | CHECK_RESULT(ReadStr(&name, "segment name")); |
2429 | 28.8k | CHECK_RESULT(ReadAlignment(&alignment_log2, "segment alignment")); |
2430 | 28.4k | CHECK_RESULT(CheckAlignment(&alignment_log2, "segment alignment")); |
2431 | 26.9k | CHECK_RESULT(ReadU32Leb128(&flags, "segment flags")); |
2432 | 26.6k | CALLBACK(OnSegmentInfo, i, name, alignment_log2, flags); |
2433 | 26.6k | } |
2434 | 9.09k | break; |
2435 | 15.9k | case LinkingEntryType::InitFunctions: |
2436 | 15.9k | CHECK_RESULT(ReadU32Leb128(&count, "info count")); |
2437 | 14.5k | CALLBACK(OnInitFunctionCount, count); |
2438 | 35.3k | while (count--) { |
2439 | 25.5k | uint32_t priority; |
2440 | 25.5k | uint32_t symbol; |
2441 | 25.5k | CHECK_RESULT(ReadU32Leb128(&priority, "priority")); |
2442 | 23.1k | CHECK_RESULT(ReadU32Leb128(&symbol, "symbol index")); |
2443 | 20.8k | CALLBACK(OnInitFunction, priority, symbol); |
2444 | 20.8k | } |
2445 | 9.86k | break; |
2446 | 13.0k | case LinkingEntryType::ComdatInfo: |
2447 | 13.0k | CHECK_RESULT(ReadU32Leb128(&count, "count")); |
2448 | 12.4k | CALLBACK(OnComdatCount, count); |
2449 | 19.1k | while (count--) { |
2450 | 16.2k | uint32_t flags; |
2451 | 16.2k | uint32_t entry_count; |
2452 | 16.2k | std::string_view name; |
2453 | 16.2k | CHECK_RESULT(ReadStr(&name, "comdat name")); |
2454 | 13.8k | CHECK_RESULT(ReadU32Leb128(&flags, "flags")); |
2455 | 12.8k | CHECK_RESULT(ReadU32Leb128(&entry_count, "entry count")); |
2456 | 12.3k | CALLBACK(OnComdatBegin, name, flags, entry_count); |
2457 | 64.9k | while (entry_count--) { |
2458 | 58.1k | uint32_t kind; |
2459 | 58.1k | uint32_t index; |
2460 | 58.1k | CHECK_RESULT(ReadU32Leb128(&kind, "kind")); |
2461 | 56.1k | CHECK_RESULT(ReadU32Leb128(&index, "index")); |
2462 | 52.5k | ComdatType comdat_type = static_cast<ComdatType>(kind); |
2463 | 52.5k | CALLBACK(OnComdatEntry, comdat_type, index); |
2464 | 52.5k | } |
2465 | 12.3k | } |
2466 | 2.95k | break; |
2467 | 96.1k | default: |
2468 | | // Unknown subsection, skip it. |
2469 | 96.1k | state_.offset = subsection_end; |
2470 | 96.1k | break; |
2471 | 299k | } |
2472 | 178k | ERROR_UNLESS(state_.offset == subsection_end, |
2473 | 178k | "unfinished sub-section (expected end: 0x%" PRIzx ")", |
2474 | 178k | subsection_end); |
2475 | 178k | } |
2476 | 50.9k | CALLBACK0(EndLinkingSection); |
2477 | 50.9k | return Result::Ok; |
2478 | 50.9k | } |
2479 | | |
2480 | 9.62k | Result BinaryReader::ReadTagType(Index* out_sig_index) { |
2481 | 9.62k | uint8_t attribute; |
2482 | 9.62k | CHECK_RESULT(ReadU8(&attribute, "tag attribute")); |
2483 | 9.57k | ERROR_UNLESS(attribute == 0, "tag attribute must be 0"); |
2484 | 9.43k | CHECK_RESULT(ReadIndex(out_sig_index, "tag signature index")); |
2485 | 9.40k | return Result::Ok; |
2486 | 9.43k | } |
2487 | | |
2488 | 731 | Result BinaryReader::ReadTagSection(Offset section_size) { |
2489 | 731 | CALLBACK(BeginTagSection, section_size); |
2490 | 731 | Index num_tags; |
2491 | 731 | CHECK_RESULT(ReadCount(&num_tags, "tag count")); |
2492 | 311 | CALLBACK(OnTagCount, num_tags); |
2493 | | |
2494 | 3.68k | for (Index i = 0; i < num_tags; ++i) { |
2495 | 3.55k | Index tag_index = num_tag_imports_ + i; |
2496 | 3.55k | Index sig_index; |
2497 | 3.55k | CHECK_RESULT(ReadTagType(&sig_index)); |
2498 | 3.37k | CALLBACK(OnTagType, tag_index, sig_index); |
2499 | 3.37k | } |
2500 | | |
2501 | 125 | CALLBACK(EndTagSection); |
2502 | 125 | return Result::Ok; |
2503 | 125 | } |
2504 | | |
2505 | | Result BinaryReader::ReadCodeMetadataSection(std::string_view name, |
2506 | 452k | Offset section_size) { |
2507 | 452k | CALLBACK(BeginCodeMetadataSection, name, section_size); |
2508 | | |
2509 | 452k | Index num_functions; |
2510 | 452k | CHECK_RESULT(ReadCount(&num_functions, "function count")); |
2511 | 449k | CALLBACK(OnCodeMetadataFuncCount, num_functions); |
2512 | | |
2513 | 449k | Index last_function_index = kInvalidIndex; |
2514 | 1.51M | for (Index i = 0; i < num_functions; ++i) { |
2515 | 1.38M | Index function_index; |
2516 | 1.38M | CHECK_RESULT(ReadIndex(&function_index, "function index")); |
2517 | 1.37M | ERROR_UNLESS(function_index >= num_func_imports_, |
2518 | 1.37M | "function import can't have metadata (got %" PRIindex ")", |
2519 | 1.37M | function_index); |
2520 | 1.37M | ERROR_UNLESS(function_index < NumTotalFuncs(), |
2521 | 1.28M | "invalid function index: %" PRIindex, function_index); |
2522 | 1.28M | ERROR_UNLESS(function_index != last_function_index, |
2523 | 1.26M | "duplicate function index: %" PRIindex, function_index); |
2524 | 1.26M | ERROR_UNLESS(last_function_index == kInvalidIndex || |
2525 | 1.12M | function_index > last_function_index, |
2526 | 1.12M | "function index out of order: %" PRIindex, function_index); |
2527 | 1.12M | last_function_index = function_index; |
2528 | | |
2529 | 1.12M | Index num_metadata; |
2530 | 1.12M | CHECK_RESULT(ReadCount(&num_metadata, "metadata instances count")); |
2531 | | |
2532 | 1.12M | CALLBACK(OnCodeMetadataCount, function_index, num_metadata); |
2533 | | |
2534 | 1.12M | Offset last_code_offset = kInvalidOffset; |
2535 | 1.46M | for (Index j = 0; j < num_metadata; ++j) { |
2536 | 393k | Offset code_offset; |
2537 | 393k | CHECK_RESULT(ReadOffset(&code_offset, "code offset")); |
2538 | 354k | ERROR_UNLESS(code_offset != last_code_offset, |
2539 | 352k | "duplicate code offset: %" PRIzx, code_offset); |
2540 | 352k | ERROR_UNLESS( |
2541 | 348k | last_code_offset == kInvalidOffset || code_offset > last_code_offset, |
2542 | 348k | "code offset out of order: %" PRIzx, code_offset); |
2543 | 348k | last_code_offset = code_offset; |
2544 | | |
2545 | 348k | Address data_size; |
2546 | 348k | const void* data; |
2547 | 348k | CHECK_RESULT(ReadBytes(&data, &data_size, "instance data")); |
2548 | 338k | CALLBACK(OnCodeMetadata, code_offset, data, data_size); |
2549 | 338k | } |
2550 | 1.12M | } |
2551 | | |
2552 | 138k | CALLBACK(EndCodeMetadataSection); |
2553 | 138k | return Result::Ok; |
2554 | 138k | } |
2555 | | |
2556 | | Result BinaryReader::ReadCustomSection(Index section_index, |
2557 | 12.4M | Offset section_size) { |
2558 | 12.4M | std::string_view section_name; |
2559 | 12.4M | CHECK_RESULT(ReadStr(§ion_name, "section name")); |
2560 | 2.43M | CALLBACK(BeginCustomSection, section_index, section_size, section_name); |
2561 | 2.43M | ValueRestoreGuard<bool, &BinaryReader::reading_custom_section_> guard(this); |
2562 | 2.43M | reading_custom_section_ = true; |
2563 | | |
2564 | 2.43M | { |
2565 | | // Backtrack parser when scope ends |
2566 | 2.43M | ValueRestoreGuard<BinaryReaderDelegate::State, &BinaryReader::state_> guard( |
2567 | 2.43M | this); |
2568 | 2.43M | CHECK_RESULT(ReadGenericCustomSection(section_name, section_size)); |
2569 | 2.43M | } |
2570 | | |
2571 | 2.43M | if (options_.read_debug_names && section_name == WABT_BINARY_SECTION_NAME) { |
2572 | 183k | CHECK_RESULT(ReadNameSection(section_size)); |
2573 | 14.6k | did_read_names_section_ = true; |
2574 | 2.24M | } else if (section_name == WABT_BINARY_SECTION_DYLINK0) { |
2575 | 49.8k | CHECK_RESULT(ReadDylink0Section(section_size)); |
2576 | 2.19M | } else if (section_name == WABT_BINARY_SECTION_DYLINK) { |
2577 | 15.0k | CHECK_RESULT(ReadDylinkSection(section_size)); |
2578 | 2.18M | } else if (section_name.rfind(WABT_BINARY_SECTION_RELOC, 0) == 0) { |
2579 | | // Reloc sections always begin with "reloc." |
2580 | 43.7k | CHECK_RESULT(ReadRelocSection(section_size)); |
2581 | 2.13M | } else if (section_name == WABT_BINARY_SECTION_TARGET_FEATURES) { |
2582 | 35.1k | CHECK_RESULT(ReadTargetFeaturesSections(section_size)); |
2583 | 2.10M | } else if (section_name == WABT_BINARY_SECTION_LINKING) { |
2584 | 192k | CHECK_RESULT(ReadLinkingSection(section_size)); |
2585 | 1.91M | } else if (options_.features.code_metadata_enabled() && |
2586 | 1.05M | section_name.find(WABT_BINARY_SECTION_CODE_METADATA) == 0) { |
2587 | 452k | std::string_view metadata_name = section_name; |
2588 | 452k | metadata_name.remove_prefix(sizeof(WABT_BINARY_SECTION_CODE_METADATA) - 1); |
2589 | 452k | CHECK_RESULT(ReadCodeMetadataSection(metadata_name, section_size)); |
2590 | 1.45M | } else { |
2591 | | // Skip. This is a generic custom section, and is handled above. |
2592 | 1.45M | state_.offset = read_end_; |
2593 | 1.45M | } |
2594 | 1.70M | CALLBACK0(EndCustomSection); |
2595 | 1.70M | return Result::Ok; |
2596 | 1.70M | } |
2597 | | |
2598 | 7.79k | Result BinaryReader::ReadTypeSection(Offset section_size) { |
2599 | 7.79k | CALLBACK(BeginTypeSection, section_size); |
2600 | 7.79k | Index num_signatures; |
2601 | 7.79k | CHECK_RESULT(ReadCount(&num_signatures, "type count")); |
2602 | 5.61k | CALLBACK(OnTypeCount, num_signatures); |
2603 | | |
2604 | 13.2k | for (Index i = 0; i < num_signatures; ++i) { |
2605 | 12.2k | Type form; |
2606 | 12.2k | if (options_.features.gc_enabled()) { |
2607 | 8.44k | CHECK_RESULT(ReadType(&form, "type form")); |
2608 | 8.44k | } else { |
2609 | 3.79k | uint8_t type; |
2610 | 3.79k | CHECK_RESULT(ReadU8(&type, "type form")); |
2611 | 3.63k | ERROR_UNLESS(type == 0x60, "unexpected type form (got %#x)", type); |
2612 | 3.43k | form = Type::Func; |
2613 | 3.43k | } |
2614 | | |
2615 | 11.4k | switch (form) { |
2616 | 8.02k | case Type::Func: { |
2617 | 8.02k | Index num_params; |
2618 | 8.02k | CHECK_RESULT(ReadCount(&num_params, "function param count")); |
2619 | | |
2620 | 7.80k | param_types_.resize(num_params); |
2621 | | |
2622 | 38.8k | for (Index j = 0; j < num_params; ++j) { |
2623 | 31.8k | Type param_type; |
2624 | 31.8k | CHECK_RESULT(ReadType(¶m_type, "function param type")); |
2625 | 31.7k | ERROR_UNLESS(IsConcreteType(param_type), |
2626 | 31.0k | "expected valid param type (got " PRItypecode ")", |
2627 | 31.0k | WABT_PRINTF_TYPE_CODE(param_type)); |
2628 | 31.0k | param_types_[j] = param_type; |
2629 | 31.0k | } |
2630 | | |
2631 | 7.04k | Index num_results; |
2632 | 7.04k | CHECK_RESULT(ReadCount(&num_results, "function result count")); |
2633 | | |
2634 | 6.64k | result_types_.resize(num_results); |
2635 | | |
2636 | 66.8k | for (Index j = 0; j < num_results; ++j) { |
2637 | 60.9k | Type result_type; |
2638 | 60.9k | CHECK_RESULT(ReadType(&result_type, "function result type")); |
2639 | 60.9k | ERROR_UNLESS(IsConcreteType(result_type), |
2640 | 60.1k | "expected valid result type (got " PRItypecode ")", |
2641 | 60.1k | WABT_PRINTF_TYPE_CODE(result_type)); |
2642 | 60.1k | result_types_[j] = result_type; |
2643 | 60.1k | } |
2644 | | |
2645 | 5.82k | Type* param_types = num_params ? param_types_.data() : nullptr; |
2646 | 5.82k | Type* result_types = num_results ? result_types_.data() : nullptr; |
2647 | | |
2648 | 5.82k | CALLBACK(OnFuncType, i, num_params, param_types, num_results, |
2649 | 5.82k | result_types); |
2650 | 5.82k | break; |
2651 | 5.82k | } |
2652 | | |
2653 | 5.82k | case Type::Struct: { |
2654 | 1.94k | ERROR_UNLESS(options_.features.gc_enabled(), |
2655 | 1.94k | "invalid type form: struct not allowed"); |
2656 | 1.94k | Index num_fields; |
2657 | 1.94k | CHECK_RESULT(ReadCount(&num_fields, "field count")); |
2658 | | |
2659 | 1.78k | fields_.resize(num_fields); |
2660 | 3.28k | for (Index j = 0; j < num_fields; ++j) { |
2661 | 1.73k | CHECK_RESULT(ReadField(&fields_[j])); |
2662 | 1.73k | } |
2663 | | |
2664 | 1.55k | CALLBACK(OnStructType, i, fields_.size(), fields_.data()); |
2665 | 1.55k | break; |
2666 | 1.55k | } |
2667 | | |
2668 | 1.55k | case Type::Array: { |
2669 | 638 | ERROR_UNLESS(options_.features.gc_enabled(), |
2670 | 638 | "invalid type form: array not allowed"); |
2671 | | |
2672 | 638 | TypeMut field; |
2673 | 638 | CHECK_RESULT(ReadField(&field)); |
2674 | 289 | CALLBACK(OnArrayType, i, field); |
2675 | 289 | break; |
2676 | 289 | }; |
2677 | |
|
2678 | 845 | default: |
2679 | 845 | PrintError("unexpected type form (got " PRItypecode ")", |
2680 | 845 | WABT_PRINTF_TYPE_CODE(form)); |
2681 | 845 | return Result::Error; |
2682 | 11.4k | } |
2683 | 11.4k | } |
2684 | 1.03k | CALLBACK0(EndTypeSection); |
2685 | 1.03k | return Result::Ok; |
2686 | 1.03k | } |
2687 | | |
2688 | 4.67k | Result BinaryReader::ReadImportSection(Offset section_size) { |
2689 | 4.67k | CALLBACK(BeginImportSection, section_size); |
2690 | 4.67k | Index num_imports; |
2691 | 4.67k | CHECK_RESULT(ReadCount(&num_imports, "import count")); |
2692 | 3.55k | CALLBACK(OnImportCount, num_imports); |
2693 | 1.54M | for (Index i = 0; i < num_imports; ++i) { |
2694 | 1.54M | std::string_view module_name; |
2695 | 1.54M | CHECK_RESULT(ReadStr(&module_name, "import module name")); |
2696 | 1.53M | std::string_view field_name; |
2697 | 1.53M | CHECK_RESULT(ReadStr(&field_name, "import field name")); |
2698 | | |
2699 | 1.53M | uint8_t kind; |
2700 | 1.53M | CHECK_RESULT(ReadU8(&kind, "import kind")); |
2701 | 1.53M | CALLBACK(OnImport, i, static_cast<ExternalKind>(kind), module_name, |
2702 | 1.53M | field_name); |
2703 | 1.53M | switch (static_cast<ExternalKind>(kind)) { |
2704 | 1.21M | case ExternalKind::Func: { |
2705 | 1.21M | Index sig_index; |
2706 | 1.21M | CHECK_RESULT(ReadIndex(&sig_index, "import signature index")); |
2707 | 1.21M | CALLBACK(OnImportFunc, i, module_name, field_name, num_func_imports_, |
2708 | 1.21M | sig_index); |
2709 | 1.21M | num_func_imports_++; |
2710 | 1.21M | break; |
2711 | 1.21M | } |
2712 | | |
2713 | 150k | case ExternalKind::Table: { |
2714 | 150k | Type elem_type; |
2715 | 150k | Limits elem_limits; |
2716 | 150k | CHECK_RESULT(ReadRefType(&elem_type, "table elem type")); |
2717 | 150k | CHECK_RESULT(ReadTable(&elem_limits)); |
2718 | 150k | CALLBACK(OnImportTable, i, module_name, field_name, num_table_imports_, |
2719 | 150k | elem_type, &elem_limits); |
2720 | 150k | num_table_imports_++; |
2721 | 150k | break; |
2722 | 150k | } |
2723 | | |
2724 | 154k | case ExternalKind::Memory: { |
2725 | 154k | Limits page_limits; |
2726 | 154k | uint32_t page_size; |
2727 | 154k | CHECK_RESULT(ReadMemory(&page_limits, &page_size)); |
2728 | 154k | CALLBACK(OnImportMemory, i, module_name, field_name, |
2729 | 154k | num_memory_imports_, &page_limits, page_size); |
2730 | 154k | num_memory_imports_++; |
2731 | 154k | break; |
2732 | 154k | } |
2733 | | |
2734 | 15.0k | case ExternalKind::Global: { |
2735 | 15.0k | Type type; |
2736 | 15.0k | bool mutable_; |
2737 | 15.0k | CHECK_RESULT(ReadGlobalHeader(&type, &mutable_)); |
2738 | 14.9k | CALLBACK(OnImportGlobal, i, module_name, field_name, |
2739 | 14.9k | num_global_imports_, type, mutable_); |
2740 | 14.9k | num_global_imports_++; |
2741 | 14.9k | break; |
2742 | 14.9k | } |
2743 | | |
2744 | 6.07k | case ExternalKind::Tag: { |
2745 | 6.07k | ERROR_UNLESS(options_.features.exceptions_enabled(), |
2746 | 6.06k | "invalid import tag kind: exceptions not allowed"); |
2747 | 6.06k | Index sig_index; |
2748 | 6.06k | CHECK_RESULT(ReadTagType(&sig_index)); |
2749 | 6.03k | CALLBACK(OnImportTag, i, module_name, field_name, num_tag_imports_, |
2750 | 6.03k | sig_index); |
2751 | 6.03k | num_tag_imports_++; |
2752 | 6.03k | break; |
2753 | 6.03k | } |
2754 | | |
2755 | 304 | default: |
2756 | 304 | PrintError("malformed import kind: %d", kind); |
2757 | 304 | return Result::Error; |
2758 | 1.53M | } |
2759 | 1.53M | } |
2760 | | |
2761 | 1.11k | CALLBACK0(EndImportSection); |
2762 | 1.11k | return Result::Ok; |
2763 | 1.11k | } |
2764 | | |
2765 | 22.5k | Result BinaryReader::ReadFunctionSection(Offset section_size) { |
2766 | 22.5k | CALLBACK(BeginFunctionSection, section_size); |
2767 | 22.5k | CHECK_RESULT( |
2768 | 22.5k | ReadCount(&num_function_signatures_, "function signature count")); |
2769 | 7.69k | CALLBACK(OnFunctionCount, num_function_signatures_); |
2770 | 2.69M | for (Index i = 0; i < num_function_signatures_; ++i) { |
2771 | 2.68M | Index func_index = num_func_imports_ + i; |
2772 | 2.68M | Index sig_index; |
2773 | 2.68M | CHECK_RESULT(ReadIndex(&sig_index, "function signature index")); |
2774 | 2.68M | CALLBACK(OnFunction, func_index, sig_index); |
2775 | 2.68M | } |
2776 | 4.65k | CALLBACK0(EndFunctionSection); |
2777 | 4.65k | return Result::Ok; |
2778 | 4.65k | } |
2779 | | |
2780 | 3.47k | Result BinaryReader::ReadTableSection(Offset section_size) { |
2781 | 3.47k | CALLBACK(BeginTableSection, section_size); |
2782 | 3.47k | Index num_tables; |
2783 | 3.47k | CHECK_RESULT(ReadCount(&num_tables, "table count")); |
2784 | 2.56k | CALLBACK(OnTableCount, num_tables); |
2785 | 5.12k | for (Index i = 0; i < num_tables; ++i) { |
2786 | 4.52k | Index table_index = num_table_imports_ + i; |
2787 | 4.52k | Type elem_type; |
2788 | 4.52k | Limits elem_limits; |
2789 | 4.52k | TableInitExprStatus init_provided = |
2790 | 4.52k | TableInitExprStatus::TableWithoutInitExpression; |
2791 | | |
2792 | 4.52k | CHECK_RESULT(ReadType(&elem_type, "table elem type")); |
2793 | | |
2794 | | // Type::Void will never represent a valid type, so it was |
2795 | | // choosen to represent the availability of the init expression. |
2796 | 4.07k | if (options_.features.function_references_enabled() && |
2797 | 2.54k | elem_type == Type::Void) { |
2798 | 511 | init_provided = TableInitExprStatus::TableWithInitExpression; |
2799 | | |
2800 | 511 | uint8_t value; |
2801 | 511 | CHECK_RESULT(ReadU8(&value, "table init")); |
2802 | | // This zero value is reserved for future |
2803 | | // extensions, and currently unused. |
2804 | 504 | if (value != 0) { |
2805 | 36 | PrintError("unsupported table intializer: 0x%x\n", |
2806 | 36 | static_cast<int>(value)); |
2807 | 36 | return Result::Error; |
2808 | 36 | } |
2809 | | |
2810 | 468 | CHECK_RESULT(ReadType(&elem_type, "table elem type")); |
2811 | 468 | } |
2812 | | |
2813 | 4.02k | ERROR_UNLESS(elem_type.IsRef(), "table elem type must be a reference type"); |
2814 | | |
2815 | 3.13k | CHECK_RESULT(ReadTable(&elem_limits)); |
2816 | 2.85k | CALLBACK(BeginTable, table_index, elem_type, &elem_limits, init_provided); |
2817 | | |
2818 | 2.84k | if (init_provided == TableInitExprStatus::TableWithInitExpression) { |
2819 | 431 | CALLBACK(BeginTableInitExpr, table_index); |
2820 | 431 | CHECK_RESULT(ReadInitExpr(table_index)); |
2821 | 145 | CALLBACK(EndTableInitExpr, table_index); |
2822 | 145 | } |
2823 | | |
2824 | 2.56k | CALLBACK(EndTable, table_index); |
2825 | 2.56k | } |
2826 | 602 | CALLBACK0(EndTableSection); |
2827 | 602 | return Result::Ok; |
2828 | 602 | } |
2829 | | |
2830 | 2.49k | Result BinaryReader::ReadMemorySection(Offset section_size) { |
2831 | 2.49k | CALLBACK(BeginMemorySection, section_size); |
2832 | 2.49k | Index num_memories; |
2833 | 2.49k | CHECK_RESULT(ReadCount(&num_memories, "memory count")); |
2834 | 1.97k | CALLBACK(OnMemoryCount, num_memories); |
2835 | 33.6k | for (Index i = 0; i < num_memories; ++i) { |
2836 | 32.7k | Index memory_index = num_memory_imports_ + i; |
2837 | 32.7k | Limits page_limits; |
2838 | 32.7k | uint32_t page_size; |
2839 | 32.7k | CHECK_RESULT(ReadMemory(&page_limits, &page_size)); |
2840 | 31.7k | CALLBACK(OnMemory, memory_index, &page_limits, page_size); |
2841 | 31.7k | } |
2842 | 941 | CALLBACK0(EndMemorySection); |
2843 | 941 | return Result::Ok; |
2844 | 941 | } |
2845 | | |
2846 | 4.92k | Result BinaryReader::ReadGlobalSection(Offset section_size) { |
2847 | 4.92k | CALLBACK(BeginGlobalSection, section_size); |
2848 | 4.92k | Index num_globals; |
2849 | 4.92k | CHECK_RESULT(ReadCount(&num_globals, "global count")); |
2850 | 4.44k | CALLBACK(OnGlobalCount, num_globals); |
2851 | 17.7k | for (Index i = 0; i < num_globals; ++i) { |
2852 | 16.9k | Index global_index = num_global_imports_ + i; |
2853 | 16.9k | Type global_type; |
2854 | 16.9k | bool mutable_; |
2855 | 16.9k | CHECK_RESULT(ReadGlobalHeader(&global_type, &mutable_)); |
2856 | 15.5k | CALLBACK(BeginGlobal, global_index, global_type, mutable_); |
2857 | 15.5k | CALLBACK(BeginGlobalInitExpr, global_index); |
2858 | 15.5k | CHECK_RESULT(ReadInitExpr(global_index)); |
2859 | 13.2k | CALLBACK(EndGlobalInitExpr, global_index); |
2860 | 13.2k | CALLBACK(EndGlobal, global_index); |
2861 | 13.2k | } |
2862 | 781 | CALLBACK0(EndGlobalSection); |
2863 | 781 | return Result::Ok; |
2864 | 781 | } |
2865 | | |
2866 | 5.34k | Result BinaryReader::ReadExportSection(Offset section_size) { |
2867 | 5.34k | CALLBACK(BeginExportSection, section_size); |
2868 | 5.34k | Index num_exports; |
2869 | 5.34k | CHECK_RESULT(ReadCount(&num_exports, "export count")); |
2870 | 4.68k | CALLBACK(OnExportCount, num_exports); |
2871 | 139k | for (Index i = 0; i < num_exports; ++i) { |
2872 | 138k | std::string_view name; |
2873 | 138k | CHECK_RESULT(ReadStr(&name, "export item name")); |
2874 | | |
2875 | 136k | ExternalKind kind; |
2876 | 136k | CHECK_RESULT(ReadExternalKind(&kind, "export kind")); |
2877 | | |
2878 | 135k | Index item_index; |
2879 | 135k | CHECK_RESULT(ReadIndex(&item_index, "export item index")); |
2880 | 135k | if (kind == ExternalKind::Tag) { |
2881 | 552 | ERROR_UNLESS(options_.features.exceptions_enabled(), |
2882 | 552 | "invalid export tag kind: exceptions not allowed"); |
2883 | 552 | } |
2884 | | |
2885 | 134k | CALLBACK(OnExport, i, static_cast<ExternalKind>(kind), item_index, name); |
2886 | 134k | } |
2887 | 689 | CALLBACK0(EndExportSection); |
2888 | 689 | return Result::Ok; |
2889 | 689 | } |
2890 | | |
2891 | 1.22k | Result BinaryReader::ReadStartSection(Offset section_size) { |
2892 | 1.22k | CALLBACK(BeginStartSection, section_size); |
2893 | 1.22k | Index func_index; |
2894 | 1.22k | CHECK_RESULT(ReadIndex(&func_index, "start function index")); |
2895 | 986 | CALLBACK(OnStartFunction, func_index); |
2896 | 964 | CALLBACK0(EndStartSection); |
2897 | 964 | return Result::Ok; |
2898 | 964 | } |
2899 | | |
2900 | 22.8k | Result BinaryReader::ReadElemSection(Offset section_size) { |
2901 | 22.8k | CALLBACK(BeginElemSection, section_size); |
2902 | 22.8k | Index num_elem_segments; |
2903 | 22.8k | CHECK_RESULT(ReadCount(&num_elem_segments, "elem segment count")); |
2904 | 22.4k | CALLBACK(OnElemSegmentCount, num_elem_segments); |
2905 | 62.9k | for (Index i = 0; i < num_elem_segments; ++i) { |
2906 | 62.6k | uint32_t flags; |
2907 | 62.6k | CHECK_RESULT(ReadU32Leb128(&flags, "elem segment flags")); |
2908 | 62.2k | ERROR_IF(flags > SegFlagMax, "invalid elem segment flags: %#x", flags); |
2909 | 61.4k | Index table_index(0); |
2910 | 61.4k | if ((flags & (SegPassive | SegExplicitIndex)) == SegExplicitIndex) { |
2911 | 10.9k | CHECK_RESULT(ReadIndex(&table_index, "elem segment table index")); |
2912 | 10.9k | } |
2913 | 61.4k | Type elem_type = Type::FuncRef; |
2914 | | |
2915 | 61.4k | if (options_.features.function_references_enabled() && |
2916 | 32.0k | !(flags & SegUseElemExprs)) { |
2917 | 26.5k | elem_type = Type(Type::FuncRef, Type::ReferenceNonNull); |
2918 | 26.5k | } |
2919 | | |
2920 | 61.4k | CALLBACK(BeginElemSegment, i, table_index, flags); |
2921 | | |
2922 | 61.4k | if (!(flags & SegPassive)) { |
2923 | 53.1k | CALLBACK(BeginElemSegmentInitExpr, i); |
2924 | 53.1k | CHECK_RESULT(ReadInitExpr(i)); |
2925 | 35.3k | CALLBACK(EndElemSegmentInitExpr, i); |
2926 | 35.3k | } |
2927 | | |
2928 | | // For backwards compat we support not declaring the element kind. |
2929 | 43.6k | if (flags & (SegPassive | SegExplicitIndex)) { |
2930 | 16.8k | if (flags & SegUseElemExprs) { |
2931 | 5.71k | CHECK_RESULT(ReadRefType(&elem_type, "table elem type")); |
2932 | 11.1k | } else { |
2933 | 11.1k | ExternalKind kind; |
2934 | 11.1k | CHECK_RESULT(ReadExternalKind(&kind, "export kind")); |
2935 | 11.0k | ERROR_UNLESS(kind == ExternalKind::Func, |
2936 | 11.0k | "segment elem type must be func (%s)", |
2937 | 11.0k | elem_type.GetName().c_str()); |
2938 | 11.0k | } |
2939 | 16.8k | } |
2940 | | |
2941 | 42.9k | CALLBACK(OnElemSegmentElemType, i, elem_type); |
2942 | | |
2943 | 42.9k | Index num_elem_exprs; |
2944 | 42.9k | CHECK_RESULT(ReadCount(&num_elem_exprs, "elem count")); |
2945 | | |
2946 | 42.4k | CALLBACK(OnElemSegmentElemExprCount, i, num_elem_exprs); |
2947 | 1.15M | for (Index j = 0; j < num_elem_exprs; ++j) { |
2948 | 1.11M | CALLBACK(BeginElemExpr, i, j); |
2949 | 1.11M | if (flags & SegUseElemExprs) { |
2950 | 20.4k | CHECK_RESULT(ReadInitExpr(j)); |
2951 | 1.08M | } else { |
2952 | 1.08M | Index func_index; |
2953 | 1.08M | CHECK_RESULT(ReadIndex(&func_index, "elem expr func index")); |
2954 | 1.08M | CALLBACK(OnOpcode, Opcode::RefFunc); |
2955 | 1.08M | CALLBACK(OnRefFuncExpr, func_index); |
2956 | 1.08M | CALLBACK(OnOpcodeUint32, func_index); |
2957 | 1.08M | CALLBACK0(OnEndExpr); |
2958 | 1.08M | } |
2959 | 1.10M | CALLBACK(EndElemExpr, i, j); |
2960 | 1.10M | } |
2961 | 40.5k | CALLBACK(EndElemSegment, i); |
2962 | 40.5k | } |
2963 | 355 | CALLBACK0(EndElemSection); |
2964 | 355 | return Result::Ok; |
2965 | 355 | } |
2966 | | |
2967 | 17.3k | Result BinaryReader::ReadCodeSection(Offset section_size) { |
2968 | 17.3k | CALLBACK(BeginCodeSection, section_size); |
2969 | 17.3k | CHECK_RESULT(ReadCount(&num_function_bodies_, "function body count")); |
2970 | 16.8k | ERROR_UNLESS(num_function_signatures_ == num_function_bodies_, |
2971 | 16.4k | "function signature count != function body count"); |
2972 | 16.4k | CALLBACK(OnFunctionBodyCount, num_function_bodies_); |
2973 | 34.4k | for (Index i = 0; i < num_function_bodies_; ++i) { |
2974 | 33.6k | Index func_index = num_func_imports_ + i; |
2975 | 33.6k | Offset func_offset = state_.offset; |
2976 | 33.6k | state_.offset = func_offset; |
2977 | 33.6k | uint32_t body_size; |
2978 | 33.6k | CHECK_RESULT(ReadU32Leb128(&body_size, "function body size")); |
2979 | 24.6k | Offset body_start_offset = state_.offset; |
2980 | 24.6k | Offset end_offset = body_start_offset + body_size; |
2981 | 24.6k | CALLBACK(BeginFunctionBody, func_index, body_size); |
2982 | | |
2983 | 24.6k | uint64_t total_locals = 0; |
2984 | 24.6k | Index num_local_decls; |
2985 | 24.6k | CHECK_RESULT(ReadCount(&num_local_decls, "local declaration count")); |
2986 | 23.4k | CALLBACK(OnLocalDeclCount, num_local_decls); |
2987 | 41.8k | for (Index k = 0; k < num_local_decls; ++k) { |
2988 | 19.8k | Index num_local_types; |
2989 | 19.8k | CHECK_RESULT(ReadIndex(&num_local_types, "local type count")); |
2990 | 19.6k | total_locals += num_local_types; |
2991 | 19.6k | ERROR_UNLESS(total_locals <= UINT32_MAX, "local count must be <= 0x%x", |
2992 | 19.6k | UINT32_MAX); |
2993 | 19.6k | Type local_type; |
2994 | 19.6k | CHECK_RESULT(ReadType(&local_type, "local type")); |
2995 | 19.3k | ERROR_UNLESS(IsConcreteType(local_type), "expected valid local type"); |
2996 | 18.4k | CALLBACK(OnLocalDecl, k, num_local_types, local_type); |
2997 | 18.4k | } |
2998 | 22.0k | CALLBACK(EndLocalDecls); |
2999 | | |
3000 | 22.0k | if (options_.skip_function_bodies) { |
3001 | 15.6k | state_.offset = end_offset; |
3002 | 15.6k | } else { |
3003 | 6.39k | CHECK_RESULT(ReadFunctionBody(end_offset)); |
3004 | 6.39k | } |
3005 | | |
3006 | 18.0k | CALLBACK(EndFunctionBody, func_index); |
3007 | 18.0k | } |
3008 | 772 | CALLBACK0(EndCodeSection); |
3009 | 772 | return Result::Ok; |
3010 | 772 | } |
3011 | | |
3012 | 13.4k | Result BinaryReader::ReadDataSection(Offset section_size) { |
3013 | 13.4k | CALLBACK(BeginDataSection, section_size); |
3014 | 13.4k | CHECK_RESULT(ReadCount(&num_data_segments_, "data segment count")); |
3015 | 12.8k | CALLBACK(OnDataSegmentCount, num_data_segments_); |
3016 | | // If the DataCount section is not present, then data_count_ will be invalid. |
3017 | 12.8k | ERROR_UNLESS( |
3018 | 12.5k | data_count_ == kInvalidIndex || data_count_ == num_data_segments_, |
3019 | 12.5k | "data segment count does not equal count in DataCount section"); |
3020 | 32.2k | for (Index i = 0; i < num_data_segments_; ++i) { |
3021 | 32.0k | uint32_t flags; |
3022 | 32.0k | CHECK_RESULT(ReadU32Leb128(&flags, "data segment flags")); |
3023 | 31.7k | ERROR_IF(flags != 0 && !options_.features.bulk_memory_enabled(), |
3024 | 31.7k | "invalid memory index %d: bulk memory not allowed", flags); |
3025 | 31.7k | ERROR_IF(flags > SegFlagMax, "invalid data segment flags: %#x", flags); |
3026 | 31.0k | Index memory_index(0); |
3027 | 31.0k | if (flags & SegExplicitIndex) { |
3028 | 3.50k | CHECK_RESULT(ReadIndex(&memory_index, "data segment memory index")); |
3029 | 3.50k | } |
3030 | 30.9k | CALLBACK(BeginDataSegment, i, memory_index, flags); |
3031 | 30.9k | if (!(flags & SegPassive)) { |
3032 | 26.5k | CALLBACK(BeginDataSegmentInitExpr, i); |
3033 | 26.5k | CHECK_RESULT(ReadInitExpr(i)); |
3034 | 15.7k | CALLBACK(EndDataSegmentInitExpr, i); |
3035 | 15.7k | } |
3036 | | |
3037 | 20.2k | Address data_size; |
3038 | 20.2k | const void* data; |
3039 | 20.2k | CHECK_RESULT(ReadBytes(&data, &data_size, "data segment data")); |
3040 | 19.7k | CALLBACK(OnDataSegmentData, i, data, data_size); |
3041 | 19.7k | CALLBACK(EndDataSegment, i); |
3042 | 19.7k | } |
3043 | 197 | CALLBACK0(EndDataSection); |
3044 | 197 | return Result::Ok; |
3045 | 197 | } |
3046 | | |
3047 | 1.50k | Result BinaryReader::ReadDataCountSection(Offset section_size) { |
3048 | 1.50k | CALLBACK(BeginDataCountSection, section_size); |
3049 | 1.50k | Index data_count; |
3050 | 1.50k | CHECK_RESULT(ReadIndex(&data_count, "data count")); |
3051 | 1.43k | CALLBACK(OnDataCount, data_count); |
3052 | 1.43k | CALLBACK0(EndDataCountSection); |
3053 | 1.43k | data_count_ = data_count; |
3054 | 1.43k | return Result::Ok; |
3055 | 1.43k | } |
3056 | | |
3057 | 92.7k | Result BinaryReader::ReadSections(const ReadSectionsOptions& options) { |
3058 | 92.7k | Result result = Result::Ok; |
3059 | 92.7k | Index section_index = 0; |
3060 | 92.7k | bool seen_section_code[static_cast<int>(BinarySection::Last) + 1] = {false}; |
3061 | | |
3062 | 13.2M | for (; state_.offset < state_.size; ++section_index) { |
3063 | 13.1M | uint8_t section_code; |
3064 | 13.1M | Offset section_size; |
3065 | 13.1M | CHECK_RESULT(ReadU8(§ion_code, "section code")); |
3066 | 13.1M | CHECK_RESULT(ReadOffset(§ion_size, "section size")); |
3067 | 13.1M | ReadEndRestoreGuard guard(this); |
3068 | 13.1M | read_end_ = state_.offset + section_size; |
3069 | 13.1M | if (section_code >= kBinarySectionCount) { |
3070 | 558k | PrintError("invalid section code: %u", section_code); |
3071 | 558k | if (options.stop_on_first_error) { |
3072 | 28 | return Result::Error; |
3073 | 28 | } |
3074 | | // If we don't have to stop on first error, continue reading |
3075 | | // sections, because although we could not understand the |
3076 | | // current section, we can continue and correctly parse |
3077 | | // subsequent sections, so we can give back as much information |
3078 | | // as we can understand. |
3079 | 558k | result = Result::Error; |
3080 | 558k | state_.offset = read_end_; |
3081 | 558k | continue; |
3082 | 558k | } |
3083 | | |
3084 | 12.5M | BinarySection section = static_cast<BinarySection>(section_code); |
3085 | 12.5M | if (section != BinarySection::Custom) { |
3086 | 116k | if (seen_section_code[section_code]) { |
3087 | 1.97k | PrintError("multiple %s sections", GetSectionName(section)); |
3088 | 1.97k | return Result::Error; |
3089 | 1.97k | } |
3090 | 114k | seen_section_code[section_code] = true; |
3091 | 114k | } |
3092 | | |
3093 | 12.5M | ERROR_UNLESS(read_end_ <= state_.size, |
3094 | 12.5M | "invalid section size: extends past end"); |
3095 | | |
3096 | 12.5M | ERROR_UNLESS( |
3097 | 12.5M | last_known_section_ == BinarySection::Invalid || |
3098 | 12.5M | section == BinarySection::Custom || |
3099 | 12.5M | GetSectionOrder(section) > GetSectionOrder(last_known_section_), |
3100 | 12.5M | "section %s out of order", GetSectionName(section)); |
3101 | | |
3102 | 12.5M | ERROR_UNLESS(!did_read_names_section_ || section == BinarySection::Custom, |
3103 | 12.5M | "%s section can not occur after Name section", |
3104 | 12.5M | GetSectionName(section)); |
3105 | | |
3106 | 12.5M | CALLBACK(BeginSection, section_index, section, section_size); |
3107 | | |
3108 | 12.5M | bool stop_on_first_error = options_.stop_on_first_error; |
3109 | 12.5M | Result section_result = Result::Error; |
3110 | 12.5M | switch (section) { |
3111 | 12.4M | case BinarySection::Custom: |
3112 | 12.4M | section_result = ReadCustomSection(section_index, section_size); |
3113 | 12.4M | if (options_.fail_on_custom_section_error) { |
3114 | 785k | result |= section_result; |
3115 | 11.6M | } else { |
3116 | 11.6M | stop_on_first_error = false; |
3117 | 11.6M | } |
3118 | 12.4M | break; |
3119 | 7.79k | case BinarySection::Type: |
3120 | 7.79k | section_result = ReadTypeSection(section_size); |
3121 | 7.79k | result |= section_result; |
3122 | 7.79k | break; |
3123 | 4.67k | case BinarySection::Import: |
3124 | 4.67k | section_result = ReadImportSection(section_size); |
3125 | 4.67k | result |= section_result; |
3126 | 4.67k | break; |
3127 | 22.5k | case BinarySection::Function: |
3128 | 22.5k | section_result = ReadFunctionSection(section_size); |
3129 | 22.5k | result |= section_result; |
3130 | 22.5k | break; |
3131 | 3.47k | case BinarySection::Table: |
3132 | 3.47k | section_result = ReadTableSection(section_size); |
3133 | 3.47k | result |= section_result; |
3134 | 3.47k | break; |
3135 | 2.49k | case BinarySection::Memory: |
3136 | 2.49k | section_result = ReadMemorySection(section_size); |
3137 | 2.49k | result |= section_result; |
3138 | 2.49k | break; |
3139 | 4.92k | case BinarySection::Global: |
3140 | 4.92k | section_result = ReadGlobalSection(section_size); |
3141 | 4.92k | result |= section_result; |
3142 | 4.92k | break; |
3143 | 5.34k | case BinarySection::Export: |
3144 | 5.34k | section_result = ReadExportSection(section_size); |
3145 | 5.34k | result |= section_result; |
3146 | 5.34k | break; |
3147 | 1.22k | case BinarySection::Start: |
3148 | 1.22k | section_result = ReadStartSection(section_size); |
3149 | 1.22k | result |= section_result; |
3150 | 1.22k | break; |
3151 | 22.8k | case BinarySection::Elem: |
3152 | 22.8k | section_result = ReadElemSection(section_size); |
3153 | 22.8k | result |= section_result; |
3154 | 22.8k | break; |
3155 | 17.3k | case BinarySection::Code: |
3156 | 17.3k | section_result = ReadCodeSection(section_size); |
3157 | 17.3k | result |= section_result; |
3158 | 17.3k | break; |
3159 | 13.4k | case BinarySection::Data: |
3160 | 13.4k | section_result = ReadDataSection(section_size); |
3161 | 13.4k | result |= section_result; |
3162 | 13.4k | break; |
3163 | 737 | case BinarySection::Tag: |
3164 | 737 | ERROR_UNLESS(options_.features.exceptions_enabled(), |
3165 | 731 | "invalid section code: %u", |
3166 | 731 | static_cast<unsigned int>(section)); |
3167 | 731 | section_result = ReadTagSection(section_size); |
3168 | 731 | result |= section_result; |
3169 | 731 | break; |
3170 | 1.50k | case BinarySection::DataCount: |
3171 | 1.50k | ERROR_UNLESS(options_.features.bulk_memory_enabled(), |
3172 | 1.50k | "invalid section code: %u", |
3173 | 1.50k | static_cast<unsigned int>(section)); |
3174 | 1.50k | section_result = ReadDataCountSection(section_size); |
3175 | 1.50k | result |= section_result; |
3176 | 1.50k | break; |
3177 | 0 | case BinarySection::Invalid: |
3178 | 0 | WABT_UNREACHABLE; |
3179 | 12.5M | } |
3180 | | |
3181 | 12.5M | if (Succeeded(section_result) && state_.offset != read_end_) { |
3182 | 156k | PrintError("unfinished section (expected end: 0x%" PRIzx ")", read_end_); |
3183 | 156k | section_result = Result::Error; |
3184 | 156k | result |= section_result; |
3185 | 156k | } |
3186 | | |
3187 | 12.5M | if (Failed(section_result)) { |
3188 | 11.0M | if (stop_on_first_error) { |
3189 | 11.3k | return Result::Error; |
3190 | 11.3k | } |
3191 | | |
3192 | | // If we're continuing after failing to read this section, move the |
3193 | | // offset to the expected section end. This way we may be able to read |
3194 | | // further sections. |
3195 | 10.9M | state_.offset = read_end_; |
3196 | 10.9M | } |
3197 | | |
3198 | 12.5M | if (section != BinarySection::Custom) { |
3199 | 99.0k | last_known_section_ = section; |
3200 | 99.0k | } |
3201 | 12.5M | } |
3202 | | |
3203 | 55.3k | return result; |
3204 | 92.7k | } |
3205 | | |
3206 | 93.4k | Result BinaryReader::ReadModule(const ReadModuleOptions& options) { |
3207 | 93.4k | uint32_t magic = 0; |
3208 | 93.4k | CHECK_RESULT(ReadU32(&magic, "magic")); |
3209 | 93.3k | ERROR_UNLESS(magic == WABT_BINARY_MAGIC, "bad magic value"); |
3210 | | |
3211 | 92.8k | uint16_t version = 0, layer = 0; |
3212 | 92.8k | CHECK_RESULT(ReadU16(&version, "version")); |
3213 | 92.8k | CHECK_RESULT(ReadU16(&layer, "layer")); |
3214 | | |
3215 | 92.8k | switch (layer) { |
3216 | 92.8k | case WABT_BINARY_LAYER_MODULE: |
3217 | 92.8k | ERROR_UNLESS(version == WABT_BINARY_VERSION, |
3218 | 92.7k | "bad wasm file version: %#x (expected %#x)", version, |
3219 | 92.7k | WABT_BINARY_VERSION); |
3220 | 92.7k | break; |
3221 | 92.7k | case WABT_BINARY_LAYER_COMPONENT: |
3222 | 7 | ERROR("wasm components are not yet supported in this tool"); |
3223 | 0 | break; |
3224 | 27 | default: |
3225 | 27 | ERROR("unsupported wasm layer: %#x", layer); |
3226 | 0 | break; |
3227 | 92.8k | } |
3228 | | |
3229 | 92.7k | CALLBACK(BeginModule, version); |
3230 | 92.7k | CHECK_RESULT(ReadSections(ReadSectionsOptions{options.stop_on_first_error})); |
3231 | | // This is checked in ReadCodeSection, but it must be checked at the end too, |
3232 | | // in case the code section was omitted. |
3233 | 8.38k | ERROR_UNLESS(num_function_signatures_ == num_function_bodies_, |
3234 | 8.04k | "function signature count != function body count"); |
3235 | | // This is checked in ReadDataSection, but it must be checked at the end too, |
3236 | | // in case the data section was omitted. |
3237 | 8.04k | ERROR_IF(num_data_segments_ == 0 && data_count_ != kInvalidIndex && |
3238 | 8.04k | data_count_ != 0, |
3239 | 8.04k | "Data section missing but DataCount non-zero"); |
3240 | 7.78k | CALLBACK0(EndModule); |
3241 | | |
3242 | 7.78k | return Result::Ok; |
3243 | 7.78k | } |
3244 | | |
3245 | | } // end anonymous namespace |
3246 | | |
3247 | | Result ReadBinary(const void* data, |
3248 | | size_t size, |
3249 | | BinaryReaderDelegate* delegate, |
3250 | 93.4k | const ReadBinaryOptions& options) { |
3251 | 93.4k | BinaryReader reader(data, size, delegate, options); |
3252 | 93.4k | return reader.ReadModule( |
3253 | 93.4k | BinaryReader::ReadModuleOptions{options.stop_on_first_error}); |
3254 | 93.4k | } |
3255 | | |
3256 | | } // namespace wabt |