Bug 1882714 [wpt PR 44850] - Update wpt metadata, a=testonly
[gecko.git] / third_party / wasm2c / src / binary-reader-ir.cc
blob5736e3021ed1c910894ea3253599a89999811519
1 /*
2 * Copyright 2016 WebAssembly Community Group participants
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "wabt/binary-reader-ir.h"
19 #include <cassert>
20 #include <cinttypes>
21 #include <cstdarg>
22 #include <cstdint>
23 #include <cstdio>
24 #include <deque>
25 #include <vector>
27 #include "wabt/binary-reader-nop.h"
28 #include "wabt/cast.h"
29 #include "wabt/common.h"
30 #include "wabt/ir.h"
32 namespace wabt {
34 namespace {
36 struct LabelNode {
37 LabelNode(LabelType, ExprList* exprs, Expr* context = nullptr);
39 LabelType label_type;
40 ExprList* exprs;
41 Expr* context;
44 LabelNode::LabelNode(LabelType label_type, ExprList* exprs, Expr* context)
45 : label_type(label_type), exprs(exprs), context(context) {}
47 class CodeMetadataExprQueue {
48 private:
49 struct Entry {
50 Func* func;
51 std::deque<std::unique_ptr<CodeMetadataExpr>> func_queue;
52 Entry(Func* f) : func(f) {}
54 std::deque<Entry> entries;
56 public:
57 CodeMetadataExprQueue() {}
58 void push_func(Func* f) { entries.emplace_back(f); }
59 void push_metadata(std::unique_ptr<CodeMetadataExpr> meta) {
60 assert(!entries.empty());
61 entries.back().func_queue.push_back(std::move(meta));
64 std::unique_ptr<CodeMetadataExpr> pop_match(Func* f, Offset offset) {
65 std::unique_ptr<CodeMetadataExpr> ret;
66 if (entries.empty()) {
67 return ret;
70 auto& current_entry = entries.front();
72 if (current_entry.func != f)
73 return ret;
74 if (current_entry.func_queue.empty()) {
75 entries.pop_front();
76 return ret;
79 auto& current_metadata = current_entry.func_queue.front();
80 if (current_metadata->loc.offset + current_entry.func->loc.offset !=
81 offset) {
82 return ret;
85 current_metadata->loc = Location(offset);
86 ret = std::move(current_metadata);
87 current_entry.func_queue.pop_front();
89 return ret;
93 class BinaryReaderIR : public BinaryReaderNop {
94 static constexpr size_t kMaxNestingDepth = 16384; // max depth of label stack
95 static constexpr size_t kMaxFunctionLocals = 50000; // matches V8
96 static constexpr size_t kMaxFunctionParams = 1000; // matches V8
97 static constexpr size_t kMaxFunctionResults = 1000; // matches V8
99 public:
100 BinaryReaderIR(Module* out_module, const char* filename, Errors* errors);
102 bool OnError(const Error&) override;
104 Result OnTypeCount(Index count) override;
105 Result OnFuncType(Index index,
106 Index param_count,
107 Type* param_types,
108 Index result_count,
109 Type* result_types) override;
110 Result OnStructType(Index index, Index field_count, TypeMut* fields) override;
111 Result OnArrayType(Index index, TypeMut field) override;
113 Result OnImportCount(Index count) override;
114 Result OnImportFunc(Index import_index,
115 std::string_view module_name,
116 std::string_view field_name,
117 Index func_index,
118 Index sig_index) override;
119 Result OnImportTable(Index import_index,
120 std::string_view module_name,
121 std::string_view field_name,
122 Index table_index,
123 Type elem_type,
124 const Limits* elem_limits) override;
125 Result OnImportMemory(Index import_index,
126 std::string_view module_name,
127 std::string_view field_name,
128 Index memory_index,
129 const Limits* page_limits) override;
130 Result OnImportGlobal(Index import_index,
131 std::string_view module_name,
132 std::string_view field_name,
133 Index global_index,
134 Type type,
135 bool mutable_) override;
136 Result OnImportTag(Index import_index,
137 std::string_view module_name,
138 std::string_view field_name,
139 Index tag_index,
140 Index sig_index) override;
142 Result OnFunctionCount(Index count) override;
143 Result OnFunction(Index index, Index sig_index) override;
145 Result OnTableCount(Index count) override;
146 Result OnTable(Index index,
147 Type elem_type,
148 const Limits* elem_limits) override;
150 Result OnMemoryCount(Index count) override;
151 Result OnMemory(Index index, const Limits* limits) override;
153 Result OnGlobalCount(Index count) override;
154 Result BeginGlobal(Index index, Type type, bool mutable_) override;
155 Result BeginGlobalInitExpr(Index index) override;
156 Result EndGlobalInitExpr(Index index) override;
158 Result OnExportCount(Index count) override;
159 Result OnExport(Index index,
160 ExternalKind kind,
161 Index item_index,
162 std::string_view name) override;
164 Result OnStartFunction(Index func_index) override;
166 Result OnFunctionBodyCount(Index count) override;
167 Result BeginFunctionBody(Index index, Offset size) override;
168 Result OnLocalDecl(Index decl_index, Index count, Type type) override;
170 Result OnOpcode(Opcode opcode) override;
171 Result OnAtomicLoadExpr(Opcode opcode,
172 Index memidx,
173 Address alignment_log2,
174 Address offset) override;
175 Result OnAtomicStoreExpr(Opcode opcode,
176 Index memidx,
177 Address alignment_log2,
178 Address offset) override;
179 Result OnAtomicRmwExpr(Opcode opcode,
180 Index memidx,
181 Address alignment_log2,
182 Address offset) override;
183 Result OnAtomicRmwCmpxchgExpr(Opcode opcode,
184 Index memidx,
185 Address alignment_log2,
186 Address offset) override;
187 Result OnAtomicWaitExpr(Opcode opcode,
188 Index memidx,
189 Address alignment_log2,
190 Address offset) override;
191 Result OnAtomicFenceExpr(uint32_t consistency_model) override;
192 Result OnAtomicNotifyExpr(Opcode opcode,
193 Index memidx,
194 Address alignment_log2,
195 Address offset) override;
196 Result OnBinaryExpr(Opcode opcode) override;
197 Result OnBlockExpr(Type sig_type) override;
198 Result OnBrExpr(Index depth) override;
199 Result OnBrIfExpr(Index depth) override;
200 Result OnBrTableExpr(Index num_targets,
201 Index* target_depths,
202 Index default_target_depth) override;
203 Result OnCallExpr(Index func_index) override;
204 Result OnCatchExpr(Index tag_index) override;
205 Result OnCatchAllExpr() override;
206 Result OnCallIndirectExpr(Index sig_index, Index table_index) override;
207 Result OnCallRefExpr() override;
208 Result OnReturnCallExpr(Index func_index) override;
209 Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override;
210 Result OnCompareExpr(Opcode opcode) override;
211 Result OnConvertExpr(Opcode opcode) override;
212 Result OnDelegateExpr(Index depth) override;
213 Result OnDropExpr() override;
214 Result OnElseExpr() override;
215 Result OnEndExpr() override;
216 Result OnF32ConstExpr(uint32_t value_bits) override;
217 Result OnF64ConstExpr(uint64_t value_bits) override;
218 Result OnV128ConstExpr(v128 value_bits) override;
219 Result OnGlobalGetExpr(Index global_index) override;
220 Result OnGlobalSetExpr(Index global_index) override;
221 Result OnI32ConstExpr(uint32_t value) override;
222 Result OnI64ConstExpr(uint64_t value) override;
223 Result OnIfExpr(Type sig_type) override;
224 Result OnLoadExpr(Opcode opcode,
225 Index memidx,
226 Address alignment_log2,
227 Address offset) override;
228 Result OnLocalGetExpr(Index local_index) override;
229 Result OnLocalSetExpr(Index local_index) override;
230 Result OnLocalTeeExpr(Index local_index) override;
231 Result OnLoopExpr(Type sig_type) override;
232 Result OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) override;
233 Result OnDataDropExpr(Index segment_index) override;
234 Result OnMemoryFillExpr(Index memidx) override;
235 Result OnMemoryGrowExpr(Index memidx) override;
236 Result OnMemoryInitExpr(Index segment_index, Index memidx) override;
237 Result OnMemorySizeExpr(Index memidx) override;
238 Result OnTableCopyExpr(Index dst_index, Index src_index) override;
239 Result OnElemDropExpr(Index segment_index) override;
240 Result OnTableInitExpr(Index segment_index, Index table_index) override;
241 Result OnTableGetExpr(Index table_index) override;
242 Result OnTableSetExpr(Index table_index) override;
243 Result OnTableGrowExpr(Index table_index) override;
244 Result OnTableSizeExpr(Index table_index) override;
245 Result OnTableFillExpr(Index table_index) override;
246 Result OnRefFuncExpr(Index func_index) override;
247 Result OnRefNullExpr(Type type) override;
248 Result OnRefIsNullExpr() override;
249 Result OnNopExpr() override;
250 Result OnRethrowExpr(Index depth) override;
251 Result OnReturnExpr() override;
252 Result OnSelectExpr(Index result_count, Type* result_types) override;
253 Result OnStoreExpr(Opcode opcode,
254 Index memidx,
255 Address alignment_log2,
256 Address offset) override;
257 Result OnThrowExpr(Index tag_index) override;
258 Result OnTryExpr(Type sig_type) override;
259 Result OnUnaryExpr(Opcode opcode) override;
260 Result OnTernaryExpr(Opcode opcode) override;
261 Result OnUnreachableExpr() override;
262 Result EndFunctionBody(Index index) override;
263 Result OnSimdLaneOpExpr(Opcode opcode, uint64_t value) override;
264 Result OnSimdLoadLaneExpr(Opcode opcode,
265 Index memidx,
266 Address alignment_log2,
267 Address offset,
268 uint64_t value) override;
269 Result OnSimdStoreLaneExpr(Opcode opcode,
270 Index memidx,
271 Address alignment_log2,
272 Address offset,
273 uint64_t value) override;
274 Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) override;
275 Result OnLoadSplatExpr(Opcode opcode,
276 Index memidx,
277 Address alignment_log2,
278 Address offset) override;
279 Result OnLoadZeroExpr(Opcode opcode,
280 Index memidx,
281 Address alignment_log2,
282 Address offset) override;
284 Result OnElemSegmentCount(Index count) override;
285 Result BeginElemSegment(Index index,
286 Index table_index,
287 uint8_t flags) override;
288 Result BeginElemSegmentInitExpr(Index index) override;
289 Result EndElemSegmentInitExpr(Index index) override;
290 Result OnElemSegmentElemType(Index index, Type elem_type) override;
291 Result OnElemSegmentElemExprCount(Index index, Index count) override;
292 Result OnElemSegmentElemExpr_RefNull(Index segment_index, Type type) override;
293 Result OnElemSegmentElemExpr_RefFunc(Index segment_index,
294 Index func_index) override;
296 Result OnDataSegmentCount(Index count) override;
297 Result BeginDataSegment(Index index,
298 Index memory_index,
299 uint8_t flags) override;
300 Result BeginDataSegmentInitExpr(Index index) override;
301 Result EndDataSegmentInitExpr(Index index) override;
302 Result OnDataSegmentData(Index index,
303 const void* data,
304 Address size) override;
306 Result OnModuleName(std::string_view module_name) override;
307 Result OnFunctionNamesCount(Index num_functions) override;
308 Result OnFunctionName(Index function_index,
309 std::string_view function_name) override;
310 Result OnLocalNameLocalCount(Index function_index, Index num_locals) override;
311 Result OnLocalName(Index function_index,
312 Index local_index,
313 std::string_view local_name) override;
314 Result OnNameEntry(NameSectionSubsection type,
315 Index index,
316 std::string_view name) override;
318 Result BeginTagSection(Offset size) override { return Result::Ok; }
319 Result OnTagCount(Index count) override { return Result::Ok; }
320 Result OnTagType(Index index, Index sig_index) override;
321 Result EndTagSection() override { return Result::Ok; }
323 Result OnDataSymbol(Index index,
324 uint32_t flags,
325 std::string_view name,
326 Index segment,
327 uint32_t offset,
328 uint32_t size) override;
329 Result OnFunctionSymbol(Index index,
330 uint32_t flags,
331 std::string_view name,
332 Index func_index) override;
333 Result OnGlobalSymbol(Index index,
334 uint32_t flags,
335 std::string_view name,
336 Index global_index) override;
337 Result OnSectionSymbol(Index index,
338 uint32_t flags,
339 Index section_index) override;
340 /* Code Metadata sections */
341 Result BeginCodeMetadataSection(std::string_view name, Offset size) override;
342 Result OnCodeMetadataFuncCount(Index count) override;
343 Result OnCodeMetadataCount(Index function_index, Index count) override;
344 Result OnCodeMetadata(Offset offset, const void* data, Address size) override;
346 Result OnTagSymbol(Index index,
347 uint32_t flags,
348 std::string_view name,
349 Index tag_index) override;
350 Result OnTableSymbol(Index index,
351 uint32_t flags,
352 std::string_view name,
353 Index table_index) override;
355 private:
356 Location GetLocation() const;
357 void PrintError(const char* format, ...);
358 Result PushLabel(LabelType label_type,
359 ExprList* first,
360 Expr* context = nullptr);
361 Result BeginInitExpr(ExprList* init_expr);
362 Result EndInitExpr();
363 Result PopLabel();
364 Result GetLabelAt(LabelNode** label, Index depth);
365 Result TopLabel(LabelNode** label);
366 Result TopLabelExpr(LabelNode** label, Expr** expr);
367 Result AppendExpr(std::unique_ptr<Expr> expr);
368 Result AppendCatch(Catch&& catch_);
369 void SetFuncDeclaration(FuncDeclaration* decl, Var var);
370 void SetBlockDeclaration(BlockDeclaration* decl, Type sig_type);
371 Result SetMemoryName(Index index, std::string_view name);
372 Result SetTableName(Index index, std::string_view name);
373 Result SetFunctionName(Index index, std::string_view name);
374 Result SetTypeName(Index index, std::string_view name);
375 Result SetGlobalName(Index index, std::string_view name);
376 Result SetDataSegmentName(Index index, std::string_view name);
377 Result SetElemSegmentName(Index index, std::string_view name);
378 Result SetTagName(Index index, std::string_view name);
380 std::string GetUniqueName(BindingHash* bindings,
381 const std::string& original_name);
383 Errors* errors_ = nullptr;
384 Module* module_ = nullptr;
386 Func* current_func_ = nullptr;
387 std::vector<LabelNode> label_stack_;
388 const char* filename_;
390 CodeMetadataExprQueue code_metadata_queue_;
391 std::string_view current_metadata_name_;
394 BinaryReaderIR::BinaryReaderIR(Module* out_module,
395 const char* filename,
396 Errors* errors)
397 : errors_(errors), module_(out_module), filename_(filename) {}
399 Location BinaryReaderIR::GetLocation() const {
400 Location loc;
401 loc.filename = filename_;
402 loc.offset = state->offset;
403 return loc;
406 void WABT_PRINTF_FORMAT(2, 3) BinaryReaderIR::PrintError(const char* format,
407 ...) {
408 WABT_SNPRINTF_ALLOCA(buffer, length, format);
409 errors_->emplace_back(ErrorLevel::Error, Location(kInvalidOffset), buffer);
412 Result BinaryReaderIR::PushLabel(LabelType label_type,
413 ExprList* first,
414 Expr* context) {
415 if (label_stack_.size() >= kMaxNestingDepth) {
416 PrintError("label stack exceeds max nesting depth");
417 return Result::Error;
419 label_stack_.emplace_back(label_type, first, context);
420 return Result::Ok;
423 Result BinaryReaderIR::PopLabel() {
424 if (label_stack_.size() == 0) {
425 PrintError("popping empty label stack");
426 return Result::Error;
429 label_stack_.pop_back();
430 return Result::Ok;
433 Result BinaryReaderIR::GetLabelAt(LabelNode** label, Index depth) {
434 if (depth >= label_stack_.size()) {
435 PrintError("accessing stack depth: %" PRIindex " >= max: %" PRIzd, depth,
436 label_stack_.size());
437 return Result::Error;
440 *label = &label_stack_[label_stack_.size() - depth - 1];
441 return Result::Ok;
444 Result BinaryReaderIR::TopLabel(LabelNode** label) {
445 return GetLabelAt(label, 0);
448 Result BinaryReaderIR::TopLabelExpr(LabelNode** label, Expr** expr) {
449 CHECK_RESULT(TopLabel(label));
450 LabelNode* parent_label;
451 CHECK_RESULT(GetLabelAt(&parent_label, 1));
452 if (parent_label->exprs->empty()) {
453 PrintError("TopLabelExpr: parent label has empty expr list");
454 return Result::Error;
456 *expr = &parent_label->exprs->back();
457 return Result::Ok;
460 Result BinaryReaderIR::AppendExpr(std::unique_ptr<Expr> expr) {
461 expr->loc = GetLocation();
462 LabelNode* label;
463 CHECK_RESULT(TopLabel(&label));
464 label->exprs->push_back(std::move(expr));
465 return Result::Ok;
468 void BinaryReaderIR::SetFuncDeclaration(FuncDeclaration* decl, Var var) {
469 decl->has_func_type = true;
470 decl->type_var = var;
471 if (auto* func_type = module_->GetFuncType(var)) {
472 decl->sig = func_type->sig;
476 void BinaryReaderIR::SetBlockDeclaration(BlockDeclaration* decl,
477 Type sig_type) {
478 if (sig_type.IsIndex()) {
479 Index type_index = sig_type.GetIndex();
480 SetFuncDeclaration(decl, Var(type_index, GetLocation()));
481 } else {
482 decl->has_func_type = false;
483 decl->sig.param_types.clear();
484 decl->sig.result_types = sig_type.GetInlineVector();
488 std::string BinaryReaderIR::GetUniqueName(BindingHash* bindings,
489 const std::string& orig_name) {
490 int counter = 1;
491 std::string unique_name = orig_name;
492 while (bindings->count(unique_name) != 0) {
493 unique_name = orig_name + "." + std::to_string(counter++);
495 return unique_name;
498 bool BinaryReaderIR::OnError(const Error& error) {
499 errors_->push_back(error);
500 return true;
503 Result BinaryReaderIR::OnTypeCount(Index count) {
504 WABT_TRY
505 module_->types.reserve(count);
506 WABT_CATCH_BAD_ALLOC
507 return Result::Ok;
510 Result BinaryReaderIR::OnFuncType(Index index,
511 Index param_count,
512 Type* param_types,
513 Index result_count,
514 Type* result_types) {
515 if (param_count > kMaxFunctionParams) {
516 PrintError("FuncType param count exceeds maximum value");
517 return Result::Error;
520 if (result_count > kMaxFunctionResults) {
521 PrintError("FuncType result count exceeds maximum value");
522 return Result::Error;
525 auto field = std::make_unique<TypeModuleField>(GetLocation());
526 auto func_type = std::make_unique<FuncType>();
527 func_type->sig.param_types.assign(param_types, param_types + param_count);
528 func_type->sig.result_types.assign(result_types, result_types + result_count);
530 module_->features_used.simd |=
531 std::any_of(func_type->sig.param_types.begin(),
532 func_type->sig.param_types.end(),
533 [](auto x) { return x == Type::V128; }) ||
534 std::any_of(func_type->sig.result_types.begin(),
535 func_type->sig.result_types.end(),
536 [](auto x) { return x == Type::V128; });
538 field->type = std::move(func_type);
539 module_->AppendField(std::move(field));
540 return Result::Ok;
543 Result BinaryReaderIR::OnStructType(Index index,
544 Index field_count,
545 TypeMut* fields) {
546 auto field = std::make_unique<TypeModuleField>(GetLocation());
547 auto struct_type = std::make_unique<StructType>();
548 struct_type->fields.resize(field_count);
549 for (Index i = 0; i < field_count; ++i) {
550 struct_type->fields[i].type = fields[i].type;
551 struct_type->fields[i].mutable_ = fields[i].mutable_;
552 module_->features_used.simd |= (fields[i].type == Type::V128);
554 field->type = std::move(struct_type);
555 module_->AppendField(std::move(field));
556 return Result::Ok;
559 Result BinaryReaderIR::OnArrayType(Index index, TypeMut type_mut) {
560 auto field = std::make_unique<TypeModuleField>(GetLocation());
561 auto array_type = std::make_unique<ArrayType>();
562 array_type->field.type = type_mut.type;
563 array_type->field.mutable_ = type_mut.mutable_;
564 module_->features_used.simd |= (type_mut.type == Type::V128);
565 field->type = std::move(array_type);
566 module_->AppendField(std::move(field));
567 return Result::Ok;
570 Result BinaryReaderIR::OnImportCount(Index count) {
571 WABT_TRY
572 module_->imports.reserve(count);
573 WABT_CATCH_BAD_ALLOC
574 return Result::Ok;
577 Result BinaryReaderIR::OnImportFunc(Index import_index,
578 std::string_view module_name,
579 std::string_view field_name,
580 Index func_index,
581 Index sig_index) {
582 auto import = std::make_unique<FuncImport>();
583 import->module_name = module_name;
584 import->field_name = field_name;
585 SetFuncDeclaration(&import->func.decl, Var(sig_index, GetLocation()));
586 module_->AppendField(
587 std::make_unique<ImportModuleField>(std::move(import), GetLocation()));
588 return Result::Ok;
591 Result BinaryReaderIR::OnImportTable(Index import_index,
592 std::string_view module_name,
593 std::string_view field_name,
594 Index table_index,
595 Type elem_type,
596 const Limits* elem_limits) {
597 auto import = std::make_unique<TableImport>();
598 import->module_name = module_name;
599 import->field_name = field_name;
600 import->table.elem_limits = *elem_limits;
601 import->table.elem_type = elem_type;
602 module_->AppendField(
603 std::make_unique<ImportModuleField>(std::move(import), GetLocation()));
604 return Result::Ok;
607 Result BinaryReaderIR::OnImportMemory(Index import_index,
608 std::string_view module_name,
609 std::string_view field_name,
610 Index memory_index,
611 const Limits* page_limits) {
612 auto import = std::make_unique<MemoryImport>();
613 import->module_name = module_name;
614 import->field_name = field_name;
615 import->memory.page_limits = *page_limits;
616 module_->AppendField(
617 std::make_unique<ImportModuleField>(std::move(import), GetLocation()));
618 return Result::Ok;
621 Result BinaryReaderIR::OnImportGlobal(Index import_index,
622 std::string_view module_name,
623 std::string_view field_name,
624 Index global_index,
625 Type type,
626 bool mutable_) {
627 auto import = std::make_unique<GlobalImport>();
628 import->module_name = module_name;
629 import->field_name = field_name;
630 import->global.type = type;
631 import->global.mutable_ = mutable_;
632 module_->AppendField(
633 std::make_unique<ImportModuleField>(std::move(import), GetLocation()));
634 module_->features_used.simd |= (type == Type::V128);
635 return Result::Ok;
638 Result BinaryReaderIR::OnImportTag(Index import_index,
639 std::string_view module_name,
640 std::string_view field_name,
641 Index tag_index,
642 Index sig_index) {
643 auto import = std::make_unique<TagImport>();
644 import->module_name = module_name;
645 import->field_name = field_name;
646 SetFuncDeclaration(&import->tag.decl, Var(sig_index, GetLocation()));
647 module_->AppendField(
648 std::make_unique<ImportModuleField>(std::move(import), GetLocation()));
649 module_->features_used.exceptions = true;
650 return Result::Ok;
653 Result BinaryReaderIR::OnFunctionCount(Index count) {
654 WABT_TRY
655 module_->funcs.reserve(module_->num_func_imports + count);
656 WABT_CATCH_BAD_ALLOC
657 return Result::Ok;
660 Result BinaryReaderIR::OnFunction(Index index, Index sig_index) {
661 auto field = std::make_unique<FuncModuleField>(GetLocation());
662 Func& func = field->func;
663 SetFuncDeclaration(&func.decl, Var(sig_index, GetLocation()));
664 module_->AppendField(std::move(field));
665 return Result::Ok;
668 Result BinaryReaderIR::OnTableCount(Index count) {
669 WABT_TRY
670 module_->tables.reserve(module_->num_table_imports + count);
671 WABT_CATCH_BAD_ALLOC
672 return Result::Ok;
675 Result BinaryReaderIR::OnTable(Index index,
676 Type elem_type,
677 const Limits* elem_limits) {
678 auto field = std::make_unique<TableModuleField>(GetLocation());
679 Table& table = field->table;
680 table.elem_limits = *elem_limits;
681 table.elem_type = elem_type;
682 module_->AppendField(std::move(field));
683 return Result::Ok;
686 Result BinaryReaderIR::OnMemoryCount(Index count) {
687 WABT_TRY
688 module_->memories.reserve(module_->num_memory_imports + count);
689 WABT_CATCH_BAD_ALLOC
690 return Result::Ok;
693 Result BinaryReaderIR::OnMemory(Index index, const Limits* page_limits) {
694 auto field = std::make_unique<MemoryModuleField>(GetLocation());
695 Memory& memory = field->memory;
696 memory.page_limits = *page_limits;
697 module_->AppendField(std::move(field));
698 return Result::Ok;
701 Result BinaryReaderIR::OnGlobalCount(Index count) {
702 WABT_TRY
703 module_->globals.reserve(module_->num_global_imports + count);
704 WABT_CATCH_BAD_ALLOC
705 return Result::Ok;
708 Result BinaryReaderIR::BeginGlobal(Index index, Type type, bool mutable_) {
709 auto field = std::make_unique<GlobalModuleField>(GetLocation());
710 Global& global = field->global;
711 global.type = type;
712 global.mutable_ = mutable_;
713 module_->AppendField(std::move(field));
714 module_->features_used.simd |= (type == Type::V128);
715 return Result::Ok;
718 Result BinaryReaderIR::BeginGlobalInitExpr(Index index) {
719 assert(index == module_->globals.size() - 1);
720 Global* global = module_->globals[index];
721 return BeginInitExpr(&global->init_expr);
724 Result BinaryReaderIR::EndGlobalInitExpr(Index index) {
725 return EndInitExpr();
728 Result BinaryReaderIR::OnExportCount(Index count) {
729 WABT_TRY
730 module_->exports.reserve(count);
731 WABT_CATCH_BAD_ALLOC
732 return Result::Ok;
735 Result BinaryReaderIR::OnExport(Index index,
736 ExternalKind kind,
737 Index item_index,
738 std::string_view name) {
739 auto field = std::make_unique<ExportModuleField>(GetLocation());
740 Export& export_ = field->export_;
741 export_.name = name;
742 export_.var = Var(item_index, GetLocation());
743 export_.kind = kind;
744 module_->AppendField(std::move(field));
745 return Result::Ok;
748 Result BinaryReaderIR::OnStartFunction(Index func_index) {
749 Var start(func_index, GetLocation());
750 module_->AppendField(
751 std::make_unique<StartModuleField>(start, GetLocation()));
752 return Result::Ok;
755 Result BinaryReaderIR::OnFunctionBodyCount(Index count) {
756 // Can hit this case on a malformed module if we don't stop on first error.
757 if (module_->num_func_imports + count != module_->funcs.size()) {
758 PrintError(
759 "number of imported func + func count in code section does not match "
760 "actual number of funcs in module");
761 return Result::Error;
763 return Result::Ok;
766 Result BinaryReaderIR::BeginFunctionBody(Index index, Offset size) {
767 current_func_ = module_->funcs[index];
768 current_func_->loc = GetLocation();
769 return PushLabel(LabelType::Func, &current_func_->exprs);
772 Result BinaryReaderIR::OnLocalDecl(Index decl_index, Index count, Type type) {
773 current_func_->local_types.AppendDecl(type, count);
775 if (current_func_->GetNumLocals() > kMaxFunctionLocals) {
776 PrintError("function local count exceeds maximum value");
777 return Result::Error;
780 module_->features_used.simd |= (type == Type::V128);
781 return Result::Ok;
784 Result BinaryReaderIR::OnOpcode(Opcode opcode) {
785 std::unique_ptr<CodeMetadataExpr> metadata =
786 code_metadata_queue_.pop_match(current_func_, GetLocation().offset - 1);
787 if (metadata) {
788 return AppendExpr(std::move(metadata));
790 module_->features_used.simd |= (opcode.GetResultType() == Type::V128);
791 return Result::Ok;
794 Result BinaryReaderIR::OnAtomicLoadExpr(Opcode opcode,
795 Index memidx,
796 Address alignment_log2,
797 Address offset) {
798 return AppendExpr(std::make_unique<AtomicLoadExpr>(
799 opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset));
802 Result BinaryReaderIR::OnAtomicStoreExpr(Opcode opcode,
803 Index memidx,
804 Address alignment_log2,
805 Address offset) {
806 return AppendExpr(std::make_unique<AtomicStoreExpr>(
807 opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset));
810 Result BinaryReaderIR::OnAtomicRmwExpr(Opcode opcode,
811 Index memidx,
812 Address alignment_log2,
813 Address offset) {
814 return AppendExpr(std::make_unique<AtomicRmwExpr>(
815 opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset));
818 Result BinaryReaderIR::OnAtomicRmwCmpxchgExpr(Opcode opcode,
819 Index memidx,
820 Address alignment_log2,
821 Address offset) {
822 return AppendExpr(std::make_unique<AtomicRmwCmpxchgExpr>(
823 opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset));
826 Result BinaryReaderIR::OnAtomicWaitExpr(Opcode opcode,
827 Index memidx,
828 Address alignment_log2,
829 Address offset) {
830 return AppendExpr(std::make_unique<AtomicWaitExpr>(
831 opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset));
834 Result BinaryReaderIR::OnAtomicFenceExpr(uint32_t consistency_model) {
835 return AppendExpr(std::make_unique<AtomicFenceExpr>(consistency_model));
838 Result BinaryReaderIR::OnAtomicNotifyExpr(Opcode opcode,
839 Index memidx,
840 Address alignment_log2,
841 Address offset) {
842 return AppendExpr(std::make_unique<AtomicNotifyExpr>(
843 opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset));
846 Result BinaryReaderIR::OnBinaryExpr(Opcode opcode) {
847 return AppendExpr(std::make_unique<BinaryExpr>(opcode));
850 Result BinaryReaderIR::OnBlockExpr(Type sig_type) {
851 auto expr = std::make_unique<BlockExpr>();
852 SetBlockDeclaration(&expr->block.decl, sig_type);
853 ExprList* expr_list = &expr->block.exprs;
854 CHECK_RESULT(AppendExpr(std::move(expr)));
855 return PushLabel(LabelType::Block, expr_list);
858 Result BinaryReaderIR::OnBrExpr(Index depth) {
859 return AppendExpr(std::make_unique<BrExpr>(Var(depth, GetLocation())));
862 Result BinaryReaderIR::OnBrIfExpr(Index depth) {
863 return AppendExpr(std::make_unique<BrIfExpr>(Var(depth, GetLocation())));
866 Result BinaryReaderIR::OnBrTableExpr(Index num_targets,
867 Index* target_depths,
868 Index default_target_depth) {
869 auto expr = std::make_unique<BrTableExpr>();
870 expr->default_target = Var(default_target_depth, GetLocation());
871 expr->targets.resize(num_targets);
872 for (Index i = 0; i < num_targets; ++i) {
873 expr->targets[i] = Var(target_depths[i], GetLocation());
875 return AppendExpr(std::move(expr));
878 Result BinaryReaderIR::OnCallExpr(Index func_index) {
879 return AppendExpr(std::make_unique<CallExpr>(Var(func_index, GetLocation())));
882 Result BinaryReaderIR::OnCallIndirectExpr(Index sig_index, Index table_index) {
883 auto expr = std::make_unique<CallIndirectExpr>();
884 SetFuncDeclaration(&expr->decl, Var(sig_index, GetLocation()));
885 expr->table = Var(table_index, GetLocation());
886 return AppendExpr(std::move(expr));
889 Result BinaryReaderIR::OnCallRefExpr() {
890 return AppendExpr(std::make_unique<CallRefExpr>());
893 Result BinaryReaderIR::OnReturnCallExpr(Index func_index) {
894 return AppendExpr(
895 std::make_unique<ReturnCallExpr>(Var(func_index, GetLocation())));
898 Result BinaryReaderIR::OnReturnCallIndirectExpr(Index sig_index,
899 Index table_index) {
900 auto expr = std::make_unique<ReturnCallIndirectExpr>();
901 SetFuncDeclaration(&expr->decl, Var(sig_index, GetLocation()));
902 expr->table = Var(table_index, GetLocation());
903 return AppendExpr(std::move(expr));
906 Result BinaryReaderIR::OnCompareExpr(Opcode opcode) {
907 return AppendExpr(std::make_unique<CompareExpr>(opcode));
910 Result BinaryReaderIR::OnConvertExpr(Opcode opcode) {
911 return AppendExpr(std::make_unique<ConvertExpr>(opcode));
914 Result BinaryReaderIR::OnDropExpr() {
915 return AppendExpr(std::make_unique<DropExpr>());
918 Result BinaryReaderIR::OnElseExpr() {
919 LabelNode* label;
920 Expr* expr;
921 CHECK_RESULT(TopLabelExpr(&label, &expr));
923 if (label->label_type == LabelType::If) {
924 auto* if_expr = cast<IfExpr>(expr);
925 if_expr->true_.end_loc = GetLocation();
926 label->exprs = &if_expr->false_;
927 label->label_type = LabelType::Else;
928 } else {
929 PrintError("else expression without matching if");
930 return Result::Error;
933 return Result::Ok;
936 Result BinaryReaderIR::OnEndExpr() {
937 if (label_stack_.size() > 1) {
938 LabelNode* label;
939 Expr* expr;
940 CHECK_RESULT(TopLabelExpr(&label, &expr));
941 switch (label->label_type) {
942 case LabelType::Block:
943 cast<BlockExpr>(expr)->block.end_loc = GetLocation();
944 break;
945 case LabelType::Loop:
946 cast<LoopExpr>(expr)->block.end_loc = GetLocation();
947 break;
948 case LabelType::If:
949 cast<IfExpr>(expr)->true_.end_loc = GetLocation();
950 break;
951 case LabelType::Else:
952 cast<IfExpr>(expr)->false_end_loc = GetLocation();
953 break;
954 case LabelType::Try:
955 cast<TryExpr>(expr)->block.end_loc = GetLocation();
956 break;
958 case LabelType::InitExpr:
959 case LabelType::Func:
960 case LabelType::Catch:
961 break;
965 return PopLabel();
968 Result BinaryReaderIR::OnF32ConstExpr(uint32_t value_bits) {
969 return AppendExpr(
970 std::make_unique<ConstExpr>(Const::F32(value_bits, GetLocation())));
973 Result BinaryReaderIR::OnF64ConstExpr(uint64_t value_bits) {
974 return AppendExpr(
975 std::make_unique<ConstExpr>(Const::F64(value_bits, GetLocation())));
978 Result BinaryReaderIR::OnV128ConstExpr(v128 value_bits) {
979 return AppendExpr(
980 std::make_unique<ConstExpr>(Const::V128(value_bits, GetLocation())));
983 Result BinaryReaderIR::OnGlobalGetExpr(Index global_index) {
984 return AppendExpr(
985 std::make_unique<GlobalGetExpr>(Var(global_index, GetLocation())));
988 Result BinaryReaderIR::OnLocalGetExpr(Index local_index) {
989 return AppendExpr(
990 std::make_unique<LocalGetExpr>(Var(local_index, GetLocation())));
993 Result BinaryReaderIR::OnI32ConstExpr(uint32_t value) {
994 return AppendExpr(
995 std::make_unique<ConstExpr>(Const::I32(value, GetLocation())));
998 Result BinaryReaderIR::OnI64ConstExpr(uint64_t value) {
999 return AppendExpr(
1000 std::make_unique<ConstExpr>(Const::I64(value, GetLocation())));
1003 Result BinaryReaderIR::OnIfExpr(Type sig_type) {
1004 auto expr = std::make_unique<IfExpr>();
1005 SetBlockDeclaration(&expr->true_.decl, sig_type);
1006 ExprList* expr_list = &expr->true_.exprs;
1007 CHECK_RESULT(AppendExpr(std::move(expr)));
1008 return PushLabel(LabelType::If, expr_list);
1011 Result BinaryReaderIR::OnLoadExpr(Opcode opcode,
1012 Index memidx,
1013 Address alignment_log2,
1014 Address offset) {
1015 return AppendExpr(std::make_unique<LoadExpr>(
1016 opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset));
1019 Result BinaryReaderIR::OnLoopExpr(Type sig_type) {
1020 auto expr = std::make_unique<LoopExpr>();
1021 SetBlockDeclaration(&expr->block.decl, sig_type);
1022 ExprList* expr_list = &expr->block.exprs;
1023 CHECK_RESULT(AppendExpr(std::move(expr)));
1024 return PushLabel(LabelType::Loop, expr_list);
1027 Result BinaryReaderIR::OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) {
1028 return AppendExpr(std::make_unique<MemoryCopyExpr>(
1029 Var(srcmemidx, GetLocation()), Var(destmemidx, GetLocation())));
1032 Result BinaryReaderIR::OnDataDropExpr(Index segment) {
1033 return AppendExpr(
1034 std::make_unique<DataDropExpr>(Var(segment, GetLocation())));
1037 Result BinaryReaderIR::OnMemoryFillExpr(Index memidx) {
1038 return AppendExpr(
1039 std::make_unique<MemoryFillExpr>(Var(memidx, GetLocation())));
1042 Result BinaryReaderIR::OnMemoryGrowExpr(Index memidx) {
1043 return AppendExpr(
1044 std::make_unique<MemoryGrowExpr>(Var(memidx, GetLocation())));
1047 Result BinaryReaderIR::OnMemoryInitExpr(Index segment, Index memidx) {
1048 return AppendExpr(std::make_unique<MemoryInitExpr>(
1049 Var(segment, GetLocation()), Var(memidx, GetLocation())));
1052 Result BinaryReaderIR::OnMemorySizeExpr(Index memidx) {
1053 return AppendExpr(
1054 std::make_unique<MemorySizeExpr>(Var(memidx, GetLocation())));
1057 Result BinaryReaderIR::OnTableCopyExpr(Index dst_index, Index src_index) {
1058 return AppendExpr(std::make_unique<TableCopyExpr>(
1059 Var(dst_index, GetLocation()), Var(src_index, GetLocation())));
1062 Result BinaryReaderIR::OnElemDropExpr(Index segment) {
1063 return AppendExpr(
1064 std::make_unique<ElemDropExpr>(Var(segment, GetLocation())));
1067 Result BinaryReaderIR::OnTableInitExpr(Index segment, Index table_index) {
1068 return AppendExpr(std::make_unique<TableInitExpr>(
1069 Var(segment, GetLocation()), Var(table_index, GetLocation())));
1072 Result BinaryReaderIR::OnTableGetExpr(Index table_index) {
1073 return AppendExpr(
1074 std::make_unique<TableGetExpr>(Var(table_index, GetLocation())));
1077 Result BinaryReaderIR::OnTableSetExpr(Index table_index) {
1078 return AppendExpr(
1079 std::make_unique<TableSetExpr>(Var(table_index, GetLocation())));
1082 Result BinaryReaderIR::OnTableGrowExpr(Index table_index) {
1083 return AppendExpr(
1084 std::make_unique<TableGrowExpr>(Var(table_index, GetLocation())));
1087 Result BinaryReaderIR::OnTableSizeExpr(Index table_index) {
1088 return AppendExpr(
1089 std::make_unique<TableSizeExpr>(Var(table_index, GetLocation())));
1092 Result BinaryReaderIR::OnTableFillExpr(Index table_index) {
1093 return AppendExpr(
1094 std::make_unique<TableFillExpr>(Var(table_index, GetLocation())));
1097 Result BinaryReaderIR::OnRefFuncExpr(Index func_index) {
1098 return AppendExpr(
1099 std::make_unique<RefFuncExpr>(Var(func_index, GetLocation())));
1102 Result BinaryReaderIR::OnRefNullExpr(Type type) {
1103 return AppendExpr(std::make_unique<RefNullExpr>(type));
1106 Result BinaryReaderIR::OnRefIsNullExpr() {
1107 return AppendExpr(std::make_unique<RefIsNullExpr>());
1110 Result BinaryReaderIR::OnNopExpr() {
1111 return AppendExpr(std::make_unique<NopExpr>());
1114 Result BinaryReaderIR::OnRethrowExpr(Index depth) {
1115 return AppendExpr(std::make_unique<RethrowExpr>(Var(depth, GetLocation())));
1118 Result BinaryReaderIR::OnReturnExpr() {
1119 return AppendExpr(std::make_unique<ReturnExpr>());
1122 Result BinaryReaderIR::OnSelectExpr(Index result_count, Type* result_types) {
1123 TypeVector results;
1124 results.assign(result_types, result_types + result_count);
1125 return AppendExpr(std::make_unique<SelectExpr>(results));
1128 Result BinaryReaderIR::OnGlobalSetExpr(Index global_index) {
1129 return AppendExpr(
1130 std::make_unique<GlobalSetExpr>(Var(global_index, GetLocation())));
1133 Result BinaryReaderIR::OnLocalSetExpr(Index local_index) {
1134 return AppendExpr(
1135 std::make_unique<LocalSetExpr>(Var(local_index, GetLocation())));
1138 Result BinaryReaderIR::OnStoreExpr(Opcode opcode,
1139 Index memidx,
1140 Address alignment_log2,
1141 Address offset) {
1142 return AppendExpr(std::make_unique<StoreExpr>(
1143 opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset));
1146 Result BinaryReaderIR::OnThrowExpr(Index tag_index) {
1147 return AppendExpr(std::make_unique<ThrowExpr>(Var(tag_index, GetLocation())));
1150 Result BinaryReaderIR::OnLocalTeeExpr(Index local_index) {
1151 return AppendExpr(
1152 std::make_unique<LocalTeeExpr>(Var(local_index, GetLocation())));
1155 Result BinaryReaderIR::OnTryExpr(Type sig_type) {
1156 auto expr_ptr = std::make_unique<TryExpr>();
1157 // Save expr so it can be used below, after expr_ptr has been moved.
1158 TryExpr* expr = expr_ptr.get();
1159 ExprList* expr_list = &expr->block.exprs;
1160 SetBlockDeclaration(&expr->block.decl, sig_type);
1161 CHECK_RESULT(AppendExpr(std::move(expr_ptr)));
1162 module_->features_used.exceptions = true;
1163 return PushLabel(LabelType::Try, expr_list, expr);
1166 Result BinaryReaderIR::AppendCatch(Catch&& catch_) {
1167 LabelNode* label = nullptr;
1168 CHECK_RESULT(TopLabel(&label));
1170 if (label->label_type != LabelType::Try) {
1171 PrintError("catch not inside try block");
1172 return Result::Error;
1175 auto* try_ = cast<TryExpr>(label->context);
1177 if (catch_.IsCatchAll() && !try_->catches.empty() &&
1178 try_->catches.back().IsCatchAll()) {
1179 PrintError("only one catch_all allowed in try block");
1180 return Result::Error;
1183 if (try_->kind == TryKind::Plain) {
1184 try_->kind = TryKind::Catch;
1185 } else if (try_->kind != TryKind::Catch) {
1186 PrintError("catch not allowed in try-delegate");
1187 return Result::Error;
1190 try_->catches.push_back(std::move(catch_));
1191 label->exprs = &try_->catches.back().exprs;
1192 return Result::Ok;
1195 Result BinaryReaderIR::OnCatchExpr(Index except_index) {
1196 return AppendCatch(Catch(Var(except_index, GetLocation())));
1199 Result BinaryReaderIR::OnCatchAllExpr() {
1200 return AppendCatch(Catch(GetLocation()));
1203 Result BinaryReaderIR::OnDelegateExpr(Index depth) {
1204 LabelNode* label = nullptr;
1205 CHECK_RESULT(TopLabel(&label));
1207 if (label->label_type != LabelType::Try) {
1208 PrintError("delegate not inside try block");
1209 return Result::Error;
1212 auto* try_ = cast<TryExpr>(label->context);
1214 if (try_->kind == TryKind::Plain) {
1215 try_->kind = TryKind::Delegate;
1216 } else if (try_->kind != TryKind::Delegate) {
1217 PrintError("delegate not allowed in try-catch");
1218 return Result::Error;
1221 try_->delegate_target = Var(depth, GetLocation());
1223 PopLabel();
1224 return Result::Ok;
1227 Result BinaryReaderIR::OnUnaryExpr(Opcode opcode) {
1228 return AppendExpr(std::make_unique<UnaryExpr>(opcode));
1231 Result BinaryReaderIR::OnTernaryExpr(Opcode opcode) {
1232 return AppendExpr(std::make_unique<TernaryExpr>(opcode));
1235 Result BinaryReaderIR::OnUnreachableExpr() {
1236 return AppendExpr(std::make_unique<UnreachableExpr>());
1239 Result BinaryReaderIR::EndFunctionBody(Index index) {
1240 current_func_ = nullptr;
1241 if (!label_stack_.empty()) {
1242 PrintError("function %" PRIindex " missing end marker", index);
1243 return Result::Error;
1245 return Result::Ok;
1248 Result BinaryReaderIR::OnSimdLaneOpExpr(Opcode opcode, uint64_t value) {
1249 return AppendExpr(std::make_unique<SimdLaneOpExpr>(opcode, value));
1252 Result BinaryReaderIR::OnSimdLoadLaneExpr(Opcode opcode,
1253 Index memidx,
1254 Address alignment_log2,
1255 Address offset,
1256 uint64_t value) {
1257 return AppendExpr(std::make_unique<SimdLoadLaneExpr>(
1258 opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset, value));
1261 Result BinaryReaderIR::OnSimdStoreLaneExpr(Opcode opcode,
1262 Index memidx,
1263 Address alignment_log2,
1264 Address offset,
1265 uint64_t value) {
1266 return AppendExpr(std::make_unique<SimdStoreLaneExpr>(
1267 opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset, value));
1270 Result BinaryReaderIR::OnSimdShuffleOpExpr(Opcode opcode, v128 value) {
1271 return AppendExpr(std::make_unique<SimdShuffleOpExpr>(opcode, value));
1274 Result BinaryReaderIR::OnLoadSplatExpr(Opcode opcode,
1275 Index memidx,
1276 Address alignment_log2,
1277 Address offset) {
1278 return AppendExpr(std::make_unique<LoadSplatExpr>(
1279 opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset));
1282 Result BinaryReaderIR::OnLoadZeroExpr(Opcode opcode,
1283 Index memidx,
1284 Address alignment_log2,
1285 Address offset) {
1286 return AppendExpr(std::make_unique<LoadZeroExpr>(
1287 opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset));
1290 Result BinaryReaderIR::OnElemSegmentCount(Index count) {
1291 WABT_TRY
1292 module_->elem_segments.reserve(count);
1293 WABT_CATCH_BAD_ALLOC
1294 return Result::Ok;
1297 Result BinaryReaderIR::BeginElemSegment(Index index,
1298 Index table_index,
1299 uint8_t flags) {
1300 auto field = std::make_unique<ElemSegmentModuleField>(GetLocation());
1301 ElemSegment& elem_segment = field->elem_segment;
1302 elem_segment.table_var = Var(table_index, GetLocation());
1303 if ((flags & SegDeclared) == SegDeclared) {
1304 elem_segment.kind = SegmentKind::Declared;
1305 } else if ((flags & SegPassive) == SegPassive) {
1306 elem_segment.kind = SegmentKind::Passive;
1307 } else {
1308 elem_segment.kind = SegmentKind::Active;
1310 module_->AppendField(std::move(field));
1311 return Result::Ok;
1314 Result BinaryReaderIR::BeginInitExpr(ExprList* expr) {
1315 return PushLabel(LabelType::InitExpr, expr);
1318 Result BinaryReaderIR::BeginElemSegmentInitExpr(Index index) {
1319 assert(index == module_->elem_segments.size() - 1);
1320 ElemSegment* segment = module_->elem_segments[index];
1321 return BeginInitExpr(&segment->offset);
1324 Result BinaryReaderIR::EndInitExpr() {
1325 if (!label_stack_.empty()) {
1326 PrintError("init expression missing end marker");
1327 return Result::Error;
1329 return Result::Ok;
1332 Result BinaryReaderIR::EndElemSegmentInitExpr(Index index) {
1333 return EndInitExpr();
1336 Result BinaryReaderIR::OnElemSegmentElemType(Index index, Type elem_type) {
1337 assert(index == module_->elem_segments.size() - 1);
1338 ElemSegment* segment = module_->elem_segments[index];
1339 segment->elem_type = elem_type;
1340 return Result::Ok;
1343 Result BinaryReaderIR::OnElemSegmentElemExprCount(Index index, Index count) {
1344 assert(index == module_->elem_segments.size() - 1);
1345 ElemSegment* segment = module_->elem_segments[index];
1346 WABT_TRY
1347 segment->elem_exprs.reserve(count);
1348 WABT_CATCH_BAD_ALLOC
1349 return Result::Ok;
1352 Result BinaryReaderIR::OnElemSegmentElemExpr_RefNull(Index segment_index,
1353 Type type) {
1354 assert(segment_index == module_->elem_segments.size() - 1);
1355 ElemSegment* segment = module_->elem_segments[segment_index];
1356 Location loc = GetLocation();
1357 ExprList init_expr;
1358 init_expr.push_back(std::make_unique<RefNullExpr>(type, loc));
1359 segment->elem_exprs.push_back(std::move(init_expr));
1360 return Result::Ok;
1363 Result BinaryReaderIR::OnElemSegmentElemExpr_RefFunc(Index segment_index,
1364 Index func_index) {
1365 assert(segment_index == module_->elem_segments.size() - 1);
1366 ElemSegment* segment = module_->elem_segments[segment_index];
1367 Location loc = GetLocation();
1368 ExprList init_expr;
1369 init_expr.push_back(std::make_unique<RefFuncExpr>(Var(func_index, loc), loc));
1370 segment->elem_exprs.push_back(std::move(init_expr));
1371 return Result::Ok;
1374 Result BinaryReaderIR::OnDataSegmentCount(Index count) {
1375 WABT_TRY
1376 module_->data_segments.reserve(count);
1377 WABT_CATCH_BAD_ALLOC
1378 return Result::Ok;
1381 Result BinaryReaderIR::BeginDataSegment(Index index,
1382 Index memory_index,
1383 uint8_t flags) {
1384 auto field = std::make_unique<DataSegmentModuleField>(GetLocation());
1385 DataSegment& data_segment = field->data_segment;
1386 data_segment.memory_var = Var(memory_index, GetLocation());
1387 if ((flags & SegPassive) == SegPassive) {
1388 data_segment.kind = SegmentKind::Passive;
1389 } else {
1390 data_segment.kind = SegmentKind::Active;
1392 module_->AppendField(std::move(field));
1393 return Result::Ok;
1396 Result BinaryReaderIR::BeginDataSegmentInitExpr(Index index) {
1397 assert(index == module_->data_segments.size() - 1);
1398 DataSegment* segment = module_->data_segments[index];
1399 return BeginInitExpr(&segment->offset);
1402 Result BinaryReaderIR::EndDataSegmentInitExpr(Index index) {
1403 return EndInitExpr();
1406 Result BinaryReaderIR::OnDataSegmentData(Index index,
1407 const void* data,
1408 Address size) {
1409 assert(index == module_->data_segments.size() - 1);
1410 DataSegment* segment = module_->data_segments[index];
1411 segment->data.resize(size);
1412 if (size > 0) {
1413 memcpy(segment->data.data(), data, size);
1415 return Result::Ok;
1418 Result BinaryReaderIR::OnFunctionNamesCount(Index count) {
1419 if (count > module_->funcs.size()) {
1420 PrintError("expected function name count (%" PRIindex
1421 ") <= function count (%" PRIzd ")",
1422 count, module_->funcs.size());
1423 return Result::Error;
1425 return Result::Ok;
1428 static std::string MakeDollarName(std::string_view name) {
1429 return std::string("$") + std::string(name);
1432 Result BinaryReaderIR::OnModuleName(std::string_view name) {
1433 if (name.empty()) {
1434 return Result::Ok;
1437 module_->name = MakeDollarName(name);
1438 return Result::Ok;
1441 Result BinaryReaderIR::SetGlobalName(Index index, std::string_view name) {
1442 if (name.empty()) {
1443 return Result::Ok;
1445 if (index >= module_->globals.size()) {
1446 PrintError("invalid global index: %" PRIindex, index);
1447 return Result::Error;
1449 Global* glob = module_->globals[index];
1450 std::string dollar_name =
1451 GetUniqueName(&module_->global_bindings, MakeDollarName(name));
1452 glob->name = dollar_name;
1453 module_->global_bindings.emplace(dollar_name, Binding(index));
1454 return Result::Ok;
1457 Result BinaryReaderIR::SetFunctionName(Index index, std::string_view name) {
1458 if (name.empty()) {
1459 return Result::Ok;
1461 if (index >= module_->funcs.size()) {
1462 PrintError("invalid function index: %" PRIindex, index);
1463 return Result::Error;
1465 Func* func = module_->funcs[index];
1466 std::string dollar_name =
1467 GetUniqueName(&module_->func_bindings, MakeDollarName(name));
1468 func->name = dollar_name;
1469 module_->func_bindings.emplace(dollar_name, Binding(index));
1470 return Result::Ok;
1473 Result BinaryReaderIR::SetTypeName(Index index, std::string_view name) {
1474 if (name.empty()) {
1475 return Result::Ok;
1477 if (index >= module_->types.size()) {
1478 PrintError("invalid type index: %" PRIindex, index);
1479 return Result::Error;
1481 TypeEntry* type = module_->types[index];
1482 std::string dollar_name =
1483 GetUniqueName(&module_->type_bindings, MakeDollarName(name));
1484 type->name = dollar_name;
1485 module_->type_bindings.emplace(dollar_name, Binding(index));
1486 return Result::Ok;
1489 Result BinaryReaderIR::SetTableName(Index index, std::string_view name) {
1490 if (name.empty()) {
1491 return Result::Ok;
1493 if (index >= module_->tables.size()) {
1494 PrintError("invalid table index: %" PRIindex, index);
1495 return Result::Error;
1497 Table* table = module_->tables[index];
1498 std::string dollar_name =
1499 GetUniqueName(&module_->table_bindings, MakeDollarName(name));
1500 table->name = dollar_name;
1501 module_->table_bindings.emplace(dollar_name, Binding(index));
1502 return Result::Ok;
1505 Result BinaryReaderIR::SetDataSegmentName(Index index, std::string_view name) {
1506 if (name.empty()) {
1507 return Result::Ok;
1509 if (index >= module_->data_segments.size()) {
1510 PrintError("invalid data segment index: %" PRIindex, index);
1511 return Result::Error;
1513 DataSegment* segment = module_->data_segments[index];
1514 std::string dollar_name =
1515 GetUniqueName(&module_->data_segment_bindings, MakeDollarName(name));
1516 segment->name = dollar_name;
1517 module_->data_segment_bindings.emplace(dollar_name, Binding(index));
1518 return Result::Ok;
1521 Result BinaryReaderIR::SetElemSegmentName(Index index, std::string_view name) {
1522 if (name.empty()) {
1523 return Result::Ok;
1525 if (index >= module_->elem_segments.size()) {
1526 PrintError("invalid elem segment index: %" PRIindex, index);
1527 return Result::Error;
1529 ElemSegment* segment = module_->elem_segments[index];
1530 std::string dollar_name =
1531 GetUniqueName(&module_->elem_segment_bindings, MakeDollarName(name));
1532 segment->name = dollar_name;
1533 module_->elem_segment_bindings.emplace(dollar_name, Binding(index));
1534 return Result::Ok;
1537 Result BinaryReaderIR::SetMemoryName(Index index, std::string_view name) {
1538 if (name.empty()) {
1539 return Result::Ok;
1541 if (index >= module_->memories.size()) {
1542 PrintError("invalid memory index: %" PRIindex, index);
1543 return Result::Error;
1545 Memory* memory = module_->memories[index];
1546 std::string dollar_name =
1547 GetUniqueName(&module_->memory_bindings, MakeDollarName(name));
1548 memory->name = dollar_name;
1549 module_->memory_bindings.emplace(dollar_name, Binding(index));
1550 return Result::Ok;
1553 Result BinaryReaderIR::SetTagName(Index index, std::string_view name) {
1554 if (name.empty()) {
1555 return Result::Ok;
1557 if (index >= module_->tags.size()) {
1558 PrintError("invalid tag index: %" PRIindex, index);
1559 return Result::Error;
1561 Tag* tag = module_->tags[index];
1562 std::string dollar_name =
1563 GetUniqueName(&module_->tag_bindings, MakeDollarName(name));
1564 tag->name = dollar_name;
1565 module_->tag_bindings.emplace(dollar_name, Binding(index));
1566 return Result::Ok;
1569 Result BinaryReaderIR::OnFunctionName(Index index, std::string_view name) {
1570 return SetFunctionName(index, name);
1573 Result BinaryReaderIR::OnNameEntry(NameSectionSubsection type,
1574 Index index,
1575 std::string_view name) {
1576 switch (type) {
1577 // TODO(sbc): remove OnFunctionName in favor of just using
1578 // OnNameEntry so that this works
1579 case NameSectionSubsection::Function:
1580 case NameSectionSubsection::Local:
1581 case NameSectionSubsection::Module:
1582 case NameSectionSubsection::Label:
1583 break;
1584 case NameSectionSubsection::Type:
1585 SetTypeName(index, name);
1586 break;
1587 case NameSectionSubsection::Tag:
1588 SetTagName(index, name);
1589 break;
1590 case NameSectionSubsection::Global:
1591 SetGlobalName(index, name);
1592 break;
1593 case NameSectionSubsection::Table:
1594 SetTableName(index, name);
1595 break;
1596 case NameSectionSubsection::DataSegment:
1597 SetDataSegmentName(index, name);
1598 break;
1599 case NameSectionSubsection::Memory:
1600 SetMemoryName(index, name);
1601 break;
1602 case NameSectionSubsection::ElemSegment:
1603 SetElemSegmentName(index, name);
1604 break;
1606 return Result::Ok;
1609 Result BinaryReaderIR::OnLocalNameLocalCount(Index index, Index count) {
1610 assert(index < module_->funcs.size());
1611 Func* func = module_->funcs[index];
1612 Index num_params_and_locals = func->GetNumParamsAndLocals();
1613 if (count > num_params_and_locals) {
1614 PrintError("expected local name count (%" PRIindex
1615 ") <= local count (%" PRIindex ")",
1616 count, num_params_and_locals);
1617 return Result::Error;
1619 return Result::Ok;
1622 Result BinaryReaderIR::BeginCodeMetadataSection(std::string_view name,
1623 Offset size) {
1624 current_metadata_name_ = name;
1625 return Result::Ok;
1628 Result BinaryReaderIR::OnCodeMetadataFuncCount(Index count) {
1629 return Result::Ok;
1632 Result BinaryReaderIR::OnCodeMetadataCount(Index function_index, Index count) {
1633 code_metadata_queue_.push_func(module_->funcs[function_index]);
1634 return Result::Ok;
1637 Result BinaryReaderIR::OnCodeMetadata(Offset offset,
1638 const void* data,
1639 Address size) {
1640 std::vector<uint8_t> data_(static_cast<const uint8_t*>(data),
1641 static_cast<const uint8_t*>(data) + size);
1642 auto meta = std::make_unique<CodeMetadataExpr>(current_metadata_name_,
1643 std::move(data_));
1644 meta->loc.offset = offset;
1645 code_metadata_queue_.push_metadata(std::move(meta));
1646 return Result::Ok;
1649 Result BinaryReaderIR::OnLocalName(Index func_index,
1650 Index local_index,
1651 std::string_view name) {
1652 if (name.empty()) {
1653 return Result::Ok;
1656 Func* func = module_->funcs[func_index];
1657 func->bindings.emplace(GetUniqueName(&func->bindings, MakeDollarName(name)),
1658 Binding(local_index));
1659 return Result::Ok;
1662 Result BinaryReaderIR::OnTagType(Index index, Index sig_index) {
1663 auto field = std::make_unique<TagModuleField>(GetLocation());
1664 Tag& tag = field->tag;
1665 SetFuncDeclaration(&tag.decl, Var(sig_index, GetLocation()));
1666 module_->AppendField(std::move(field));
1667 module_->features_used.exceptions = true;
1668 return Result::Ok;
1671 Result BinaryReaderIR::OnDataSymbol(Index index,
1672 uint32_t flags,
1673 std::string_view name,
1674 Index segment,
1675 uint32_t offset,
1676 uint32_t size) {
1677 if (name.empty()) {
1678 return Result::Ok;
1680 if (flags & WABT_SYMBOL_FLAG_UNDEFINED) {
1681 // Refers to data in another file, `segment` not valid.
1682 return Result::Ok;
1684 if (offset) {
1685 // If it is pointing into the data segment, then it's not really naming
1686 // the whole segment.
1687 return Result::Ok;
1689 if (segment >= module_->data_segments.size()) {
1690 PrintError("invalid data segment index: %" PRIindex, segment);
1691 return Result::Error;
1693 DataSegment* seg = module_->data_segments[segment];
1694 std::string dollar_name =
1695 GetUniqueName(&module_->data_segment_bindings, MakeDollarName(name));
1696 seg->name = dollar_name;
1697 module_->data_segment_bindings.emplace(dollar_name, Binding(segment));
1698 return Result::Ok;
1701 Result BinaryReaderIR::OnFunctionSymbol(Index index,
1702 uint32_t flags,
1703 std::string_view name,
1704 Index func_index) {
1705 if (name.empty()) {
1706 return Result::Ok;
1708 if (func_index >= module_->funcs.size()) {
1709 PrintError("invalid function index: %" PRIindex, func_index);
1710 return Result::Error;
1712 Func* func = module_->funcs[func_index];
1713 if (!func->name.empty()) {
1714 // The name section has already named this function.
1715 return Result::Ok;
1717 std::string dollar_name =
1718 GetUniqueName(&module_->func_bindings, MakeDollarName(name));
1719 func->name = dollar_name;
1720 module_->func_bindings.emplace(dollar_name, Binding(func_index));
1721 return Result::Ok;
1724 Result BinaryReaderIR::OnGlobalSymbol(Index index,
1725 uint32_t flags,
1726 std::string_view name,
1727 Index global_index) {
1728 return SetGlobalName(global_index, name);
1731 Result BinaryReaderIR::OnSectionSymbol(Index index,
1732 uint32_t flags,
1733 Index section_index) {
1734 return Result::Ok;
1737 Result BinaryReaderIR::OnTagSymbol(Index index,
1738 uint32_t flags,
1739 std::string_view name,
1740 Index tag_index) {
1741 if (name.empty()) {
1742 return Result::Ok;
1744 if (tag_index >= module_->tags.size()) {
1745 PrintError("invalid tag index: %" PRIindex, tag_index);
1746 return Result::Error;
1748 Tag* tag = module_->tags[tag_index];
1749 std::string dollar_name =
1750 GetUniqueName(&module_->tag_bindings, MakeDollarName(name));
1751 tag->name = dollar_name;
1752 module_->tag_bindings.emplace(dollar_name, Binding(tag_index));
1753 return Result::Ok;
1756 Result BinaryReaderIR::OnTableSymbol(Index index,
1757 uint32_t flags,
1758 std::string_view name,
1759 Index table_index) {
1760 return SetTableName(table_index, name);
1763 } // end anonymous namespace
1765 Result ReadBinaryIr(const char* filename,
1766 const void* data,
1767 size_t size,
1768 const ReadBinaryOptions& options,
1769 Errors* errors,
1770 Module* out_module) {
1771 BinaryReaderIR reader(out_module, filename, errors);
1772 return ReadBinary(data, size, &reader, options);
1775 } // namespace wabt