Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/wabt/ir.h
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 #ifndef WABT_IR_H_ 18 #define WABT_IR_H_ 19 20 #include <cassert> 21 #include <cstddef> 22 #include <cstdint> 23 #include <memory> 24 #include <string> 25 #include <string_view> 26 #include <type_traits> 27 #include <vector> 28 29 #include "wabt/binding-hash.h" 30 #include "wabt/common.h" 31 #include "wabt/intrusive-list.h" 32 #include "wabt/opcode.h" 33 34 namespace wabt { 35 36 struct Module; 37 38 enum class VarType { 39 Index, 40 Name, 41 }; 42 43 struct Var { 44 explicit Var(); 45 explicit Var(Index index, const Location& loc); 46 explicit Var(std::string_view name, const Location& loc); 47 Var(Var&&); 48 Var(const Var&); 49 Var& operator=(const Var&); 50 Var& operator=(Var&&); 51 ~Var(); 52 53 VarType type() const { return type_; } 54 bool is_index() const { return type_ == VarType::Index; } 55 bool is_name() const { return type_ == VarType::Name; } 56 57 Index index() const { 58 assert(is_index()); 59 return index_; 60 } 61 const std::string& name() const { 62 assert(is_name()); 63 return name_; 64 } 65 66 void set_index(Index); 67 void set_name(std::string&&); 68 void set_name(std::string_view); 69 70 Location loc; 71 72 private: 73 void Destroy(); 74 75 VarType type_; 76 union { 77 Index index_; 78 std::string name_; 79 }; 80 }; 81 using VarVector = std::vector<Var>; 82 83 struct Const { 84 static constexpr uintptr_t kRefNullBits = ~uintptr_t(0); 85 86 Const() : Const(Type::I32, uint32_t(0)) {} 87 88 static Const I32(uint32_t val = 0, const Location& loc = Location()) { 89 return Const(Type::I32, val, loc); 90 } 91 static Const I64(uint64_t val = 0, const Location& loc = Location()) { 92 return Const(Type::I64, val, loc); 93 } 94 static Const F32(uint32_t val = 0, const Location& loc = Location()) { 95 return Const(Type::F32, val, loc); 96 } 97 static Const F64(uint64_t val = 0, const Location& loc = Location()) { 98 return Const(Type::F64, val, loc); 99 } 100 static Const V128(v128 val, const Location& loc = Location()) { 101 return Const(Type::V128, val, loc); 102 } 103 104 Type type() const { return type_; } 105 Type lane_type() const { 106 assert(type_ == Type::V128); 107 return lane_type_; 108 } 109 110 int lane_count() const { 111 switch (lane_type()) { 112 case Type::I8: return 16; 113 case Type::I16: return 8; 114 case Type::I32: return 4; 115 case Type::I64: return 2; 116 case Type::F32: return 4; 117 case Type::F64: return 2; 118 default: WABT_UNREACHABLE; 119 } 120 } 121 122 uint32_t u32() const { return data_.u32(0); } 123 uint64_t u64() const { return data_.u64(0); } 124 uint32_t f32_bits() const { return data_.f32_bits(0); } 125 uint64_t f64_bits() const { return data_.f64_bits(0); } 126 uintptr_t ref_bits() const { return data_.To<uintptr_t>(0); } 127 v128 vec128() const { return data_; } 128 129 template <typename T> 130 T v128_lane(int lane) const { 131 return data_.To<T>(lane); 132 } 133 134 void set_u32(uint32_t x) { From(Type::I32, x); } 135 void set_u64(uint64_t x) { From(Type::I64, x); } 136 void set_f32(uint32_t x) { From(Type::F32, x); } 137 void set_f64(uint64_t x) { From(Type::F64, x); } 138 139 void set_v128_u8(int lane, uint8_t x) { set_v128_lane(lane, Type::I8, x); } 140 void set_v128_u16(int lane, uint16_t x) { set_v128_lane(lane, Type::I16, x); } 141 void set_v128_u32(int lane, uint32_t x) { set_v128_lane(lane, Type::I32, x); } 142 void set_v128_u64(int lane, uint64_t x) { set_v128_lane(lane, Type::I64, x); } 143 void set_v128_f32(int lane, uint32_t x) { set_v128_lane(lane, Type::F32, x); } 144 void set_v128_f64(int lane, uint64_t x) { set_v128_lane(lane, Type::F64, x); } 145 146 // Only used for expectations. (e.g. wast assertions) 147 void set_f32(ExpectedNan nan) { 148 set_f32(0); 149 set_expected_nan(0, nan); 150 } 151 void set_f64(ExpectedNan nan) { 152 set_f64(0); 153 set_expected_nan(0, nan); 154 } 155 void set_funcref() { From<uintptr_t>(Type::FuncRef, 0); } 156 void set_externref(uintptr_t x) { From(Type::ExternRef, x); } 157 void set_null(Type type) { From<uintptr_t>(type, kRefNullBits); } 158 159 bool is_expected_nan(int lane = 0) const { 160 return expected_nan(lane) != ExpectedNan::None; 161 } 162 163 ExpectedNan expected_nan(int lane = 0) const { 164 return lane < 4 ? nan_[lane] : ExpectedNan::None; 165 } 166 167 void set_expected_nan(int lane, ExpectedNan nan) { 168 if (lane < 4) { 169 nan_[lane] = nan; 170 } 171 } 172 173 // v128 support 174 Location loc; 175 176 private: 177 template <typename T> 178 void set_v128_lane(int lane, Type lane_type, T x) { 179 lane_type_ = lane_type; 180 From(Type::V128, x, lane); 181 set_expected_nan(lane, ExpectedNan::None); 182 } 183 184 template <typename T> 185 Const(Type type, T data, const Location& loc = Location()) : loc(loc) { 186 From<T>(type, data); 187 } 188 189 template <typename T> 190 void From(Type type, T data, int lane = 0) { 191 static_assert(sizeof(T) <= sizeof(data_), "Invalid cast!"); 192 assert((lane + 1) * sizeof(T) <= sizeof(data_)); 193 type_ = type; 194 data_.From<T>(lane, data); 195 set_expected_nan(lane, ExpectedNan::None); 196 } 197 198 Type type_; 199 Type lane_type_; // Only valid if type_ == Type::V128. 200 v128 data_; 201 ExpectedNan nan_[4]; 202 }; 203 using ConstVector = std::vector<Const>; 204 205 enum class ExpectationType { 206 Values, 207 Either, 208 }; 209 210 class Expectation { 211 public: 212 Expectation() = delete; 213 virtual ~Expectation() = default; 214 ExpectationType type() const { return type_; } 215 216 Location loc; 217 218 ConstVector expected; 219 220 protected: 221 explicit Expectation(ExpectationType type, const Location& loc = Location()) 222 : loc(loc), type_(type) {} 223 224 private: 225 ExpectationType type_; 226 }; 227 228 template <ExpectationType TypeEnum> 229 class ExpectationMixin : public Expectation { 230 public: 231 static bool classof(const Expectation* expectation) { 232 return expectation->type() == TypeEnum; 233 } 234 235 explicit ExpectationMixin(const Location& loc = Location()) 236 : Expectation(TypeEnum, loc) {} 237 }; 238 239 class ValueExpectation : public ExpectationMixin<ExpectationType::Values> { 240 public: 241 explicit ValueExpectation(const Location& loc = Location()) 242 : ExpectationMixin<ExpectationType::Values>(loc) {} 243 }; 244 245 struct EitherExpectation : public ExpectationMixin<ExpectationType::Either> { 246 public: 247 explicit EitherExpectation(const Location& loc = Location()) 248 : ExpectationMixin<ExpectationType::Either>(loc) {} 249 }; 250 251 typedef std::unique_ptr<Expectation> ExpectationPtr; 252 253 struct FuncSignature { 254 TypeVector param_types; 255 TypeVector result_types; 256 257 // Some types can have names, for example (ref $foo) has type $foo. 258 // So to use this type we need to translate its name into 259 // a proper index from the module type section. 260 // This is the mapping from parameter/result index to its name. 261 std::unordered_map<uint32_t, std::string> param_type_names; 262 std::unordered_map<uint32_t, std::string> result_type_names; 263 264 Index GetNumParams() const { return param_types.size(); } 265 Index GetNumResults() const { return result_types.size(); } 266 Type GetParamType(Index index) const { return param_types[index]; } 267 Type GetResultType(Index index) const { return result_types[index]; } 268 269 bool operator==(const FuncSignature&) const; 270 }; 271 272 enum class TypeEntryKind { 273 Func, 274 Struct, 275 Array, 276 }; 277 278 class TypeEntry { 279 public: 280 WABT_DISALLOW_COPY_AND_ASSIGN(TypeEntry); 281 282 virtual ~TypeEntry() = default; 283 284 TypeEntryKind kind() const { return kind_; } 285 286 Location loc; 287 std::string name; 288 289 protected: 290 explicit TypeEntry(TypeEntryKind kind, 291 std::string_view name = std::string_view(), 292 const Location& loc = Location()) 293 : loc(loc), name(name), kind_(kind) {} 294 295 TypeEntryKind kind_; 296 }; 297 298 class FuncType : public TypeEntry { 299 public: 300 static bool classof(const TypeEntry* entry) { 301 return entry->kind() == TypeEntryKind::Func; 302 } 303 304 explicit FuncType(std::string_view name = std::string_view()) 305 : TypeEntry(TypeEntryKind::Func, name) {} 306 307 Index GetNumParams() const { return sig.GetNumParams(); } 308 Index GetNumResults() const { return sig.GetNumResults(); } 309 Type GetParamType(Index index) const { return sig.GetParamType(index); } 310 Type GetResultType(Index index) const { return sig.GetResultType(index); } 311 312 FuncSignature sig; 313 314 // The BinaryReaderIR tracks whether a FuncType is the target of a tailcall 315 // (via a return_call_indirect). wasm2c (CWriter) uses this information to 316 // limit its output in some cases. 317 struct { 318 bool tailcall = false; 319 } features_used; 320 }; 321 322 struct Field { 323 std::string name; 324 Type type = Type::Void; 325 bool mutable_ = false; 326 }; 327 328 class StructType : public TypeEntry { 329 public: 330 static bool classof(const TypeEntry* entry) { 331 return entry->kind() == TypeEntryKind::Struct; 332 } 333 334 explicit StructType(std::string_view name = std::string_view()) 335 : TypeEntry(TypeEntryKind::Struct) {} 336 337 std::vector<Field> fields; 338 }; 339 340 class ArrayType : public TypeEntry { 341 public: 342 static bool classof(const TypeEntry* entry) { 343 return entry->kind() == TypeEntryKind::Array; 344 } 345 346 explicit ArrayType(std::string_view name = std::string_view()) 347 : TypeEntry(TypeEntryKind::Array) {} 348 349 Field field; 350 }; 351 352 struct FuncDeclaration { 353 Index GetNumParams() const { return sig.GetNumParams(); } 354 Index GetNumResults() const { return sig.GetNumResults(); } 355 Type GetParamType(Index index) const { return sig.GetParamType(index); } 356 Type GetResultType(Index index) const { return sig.GetResultType(index); } 357 358 bool has_func_type = false; 359 Var type_var; 360 FuncSignature sig; 361 }; 362 363 enum class ExprType { 364 AtomicLoad, 365 AtomicRmw, 366 AtomicRmwCmpxchg, 367 AtomicStore, 368 AtomicNotify, 369 AtomicFence, 370 AtomicWait, 371 Binary, 372 Block, 373 Br, 374 BrIf, 375 BrTable, 376 Call, 377 CallIndirect, 378 CallRef, 379 CodeMetadata, 380 Compare, 381 Const, 382 Convert, 383 Drop, 384 GlobalGet, 385 GlobalSet, 386 If, 387 Load, 388 LocalGet, 389 LocalSet, 390 LocalTee, 391 Loop, 392 MemoryCopy, 393 DataDrop, 394 MemoryFill, 395 MemoryGrow, 396 MemoryInit, 397 MemorySize, 398 Nop, 399 RefIsNull, 400 RefFunc, 401 RefNull, 402 Rethrow, 403 Return, 404 ReturnCall, 405 ReturnCallIndirect, 406 Select, 407 SimdLaneOp, 408 SimdLoadLane, 409 SimdStoreLane, 410 SimdShuffleOp, 411 LoadSplat, 412 LoadZero, 413 Store, 414 TableCopy, 415 ElemDrop, 416 TableInit, 417 TableGet, 418 TableGrow, 419 TableSize, 420 TableSet, 421 TableFill, 422 Ternary, 423 Throw, 424 Try, 425 Unary, 426 Unreachable, 427 428 First = AtomicLoad, 429 Last = Unreachable 430 }; 431 432 const char* GetExprTypeName(ExprType type); 433 434 class Expr; 435 using ExprList = intrusive_list<Expr>; 436 437 using BlockDeclaration = FuncDeclaration; 438 439 struct Block { 440 Block() = default; 441 explicit Block(ExprList exprs) : exprs(std::move(exprs)) {} 442 443 std::string label; 444 BlockDeclaration decl; 445 ExprList exprs; 446 Location end_loc; 447 }; 448 449 struct Catch { 450 explicit Catch(const Location& loc = Location()) : loc(loc) {} 451 explicit Catch(const Var& var, const Location& loc = Location()) 452 : loc(loc), var(var) {} 453 Location loc; 454 Var var; 455 ExprList exprs; 456 bool IsCatchAll() const { 457 return var.is_index() && var.index() == kInvalidIndex; 458 } 459 }; 460 using CatchVector = std::vector<Catch>; 461 462 enum class TryKind { Plain, Catch, Delegate }; 463 464 class Expr : public intrusive_list_base<Expr> { 465 public: 466 WABT_DISALLOW_COPY_AND_ASSIGN(Expr); 467 Expr() = delete; 468 virtual ~Expr() = default; 469 470 ExprType type() const { return type_; } 471 472 Location loc; 473 474 protected: 475 explicit Expr(ExprType type, const Location& loc = Location()) 476 : loc(loc), type_(type) {} 477 478 ExprType type_; 479 }; 480 481 const char* GetExprTypeName(const Expr& expr); 482 483 template <ExprType TypeEnum> 484 class ExprMixin : public Expr { 485 public: 486 static bool classof(const Expr* expr) { return expr->type() == TypeEnum; } 487 488 explicit ExprMixin(const Location& loc = Location()) : Expr(TypeEnum, loc) {} 489 }; 490 491 template <ExprType TypeEnum> 492 class MemoryExpr : public ExprMixin<TypeEnum> { 493 public: 494 MemoryExpr(Var memidx, const Location& loc = Location()) 495 : ExprMixin<TypeEnum>(loc), memidx(memidx) {} 496 497 Var memidx; 498 }; 499 500 template <ExprType TypeEnum> 501 class MemoryBinaryExpr : public ExprMixin<TypeEnum> { 502 public: 503 MemoryBinaryExpr(Var destmemidx, 504 Var srcmemidx, 505 const Location& loc = Location()) 506 : ExprMixin<TypeEnum>(loc), 507 destmemidx(destmemidx), 508 srcmemidx(srcmemidx) {} 509 510 Var destmemidx; 511 Var srcmemidx; 512 }; 513 514 using DropExpr = ExprMixin<ExprType::Drop>; 515 using NopExpr = ExprMixin<ExprType::Nop>; 516 using ReturnExpr = ExprMixin<ExprType::Return>; 517 using UnreachableExpr = ExprMixin<ExprType::Unreachable>; 518 519 using MemoryGrowExpr = MemoryExpr<ExprType::MemoryGrow>; 520 using MemorySizeExpr = MemoryExpr<ExprType::MemorySize>; 521 using MemoryFillExpr = MemoryExpr<ExprType::MemoryFill>; 522 523 using MemoryCopyExpr = MemoryBinaryExpr<ExprType::MemoryCopy>; 524 525 template <ExprType TypeEnum> 526 class RefTypeExpr : public ExprMixin<TypeEnum> { 527 public: 528 RefTypeExpr(Type type, const Location& loc = Location()) 529 : ExprMixin<TypeEnum>(loc), type(type) {} 530 531 Type type; 532 }; 533 534 using RefNullExpr = RefTypeExpr<ExprType::RefNull>; 535 using RefIsNullExpr = ExprMixin<ExprType::RefIsNull>; 536 537 template <ExprType TypeEnum> 538 class OpcodeExpr : public ExprMixin<TypeEnum> { 539 public: 540 OpcodeExpr(Opcode opcode, const Location& loc = Location()) 541 : ExprMixin<TypeEnum>(loc), opcode(opcode) {} 542 543 Opcode opcode; 544 }; 545 546 using BinaryExpr = OpcodeExpr<ExprType::Binary>; 547 using CompareExpr = OpcodeExpr<ExprType::Compare>; 548 using ConvertExpr = OpcodeExpr<ExprType::Convert>; 549 using UnaryExpr = OpcodeExpr<ExprType::Unary>; 550 using TernaryExpr = OpcodeExpr<ExprType::Ternary>; 551 552 class SimdLaneOpExpr : public ExprMixin<ExprType::SimdLaneOp> { 553 public: 554 SimdLaneOpExpr(Opcode opcode, uint64_t val, const Location& loc = Location()) 555 : ExprMixin<ExprType::SimdLaneOp>(loc), opcode(opcode), val(val) {} 556 557 Opcode opcode; 558 uint64_t val; 559 }; 560 561 class SimdLoadLaneExpr : public MemoryExpr<ExprType::SimdLoadLane> { 562 public: 563 SimdLoadLaneExpr(Opcode opcode, 564 Var memidx, 565 Address align, 566 Address offset, 567 uint64_t val, 568 const Location& loc = Location()) 569 : MemoryExpr<ExprType::SimdLoadLane>(memidx, loc), 570 opcode(opcode), 571 align(align), 572 offset(offset), 573 val(val) {} 574 575 Opcode opcode; 576 Address align; 577 Address offset; 578 uint64_t val; 579 }; 580 581 class SimdStoreLaneExpr : public MemoryExpr<ExprType::SimdStoreLane> { 582 public: 583 SimdStoreLaneExpr(Opcode opcode, 584 Var memidx, 585 Address align, 586 Address offset, 587 uint64_t val, 588 const Location& loc = Location()) 589 : MemoryExpr<ExprType::SimdStoreLane>(memidx, loc), 590 opcode(opcode), 591 align(align), 592 offset(offset), 593 val(val) {} 594 595 Opcode opcode; 596 Address align; 597 Address offset; 598 uint64_t val; 599 }; 600 601 class SimdShuffleOpExpr : public ExprMixin<ExprType::SimdShuffleOp> { 602 public: 603 SimdShuffleOpExpr(Opcode opcode, v128 val, const Location& loc = Location()) 604 : ExprMixin<ExprType::SimdShuffleOp>(loc), opcode(opcode), val(val) {} 605 606 Opcode opcode; 607 v128 val; 608 }; 609 610 template <ExprType TypeEnum> 611 class VarExpr : public ExprMixin<TypeEnum> { 612 public: 613 VarExpr(const Var& var, const Location& loc = Location()) 614 : ExprMixin<TypeEnum>(loc), var(var) {} 615 616 Var var; 617 }; 618 619 template <ExprType TypeEnum> 620 class MemoryVarExpr : public MemoryExpr<TypeEnum> { 621 public: 622 MemoryVarExpr(const Var& var, Var memidx, const Location& loc = Location()) 623 : MemoryExpr<TypeEnum>(memidx, loc), var(var) {} 624 625 Var var; 626 }; 627 628 using BrExpr = VarExpr<ExprType::Br>; 629 using BrIfExpr = VarExpr<ExprType::BrIf>; 630 using CallExpr = VarExpr<ExprType::Call>; 631 using RefFuncExpr = VarExpr<ExprType::RefFunc>; 632 using GlobalGetExpr = VarExpr<ExprType::GlobalGet>; 633 using GlobalSetExpr = VarExpr<ExprType::GlobalSet>; 634 using LocalGetExpr = VarExpr<ExprType::LocalGet>; 635 using LocalSetExpr = VarExpr<ExprType::LocalSet>; 636 using LocalTeeExpr = VarExpr<ExprType::LocalTee>; 637 using ReturnCallExpr = VarExpr<ExprType::ReturnCall>; 638 using ThrowExpr = VarExpr<ExprType::Throw>; 639 using RethrowExpr = VarExpr<ExprType::Rethrow>; 640 641 using DataDropExpr = VarExpr<ExprType::DataDrop>; 642 using ElemDropExpr = VarExpr<ExprType::ElemDrop>; 643 using TableGetExpr = VarExpr<ExprType::TableGet>; 644 using TableSetExpr = VarExpr<ExprType::TableSet>; 645 using TableGrowExpr = VarExpr<ExprType::TableGrow>; 646 using TableSizeExpr = VarExpr<ExprType::TableSize>; 647 using TableFillExpr = VarExpr<ExprType::TableFill>; 648 649 using MemoryInitExpr = MemoryVarExpr<ExprType::MemoryInit>; 650 651 class SelectExpr : public ExprMixin<ExprType::Select> { 652 public: 653 SelectExpr(TypeVector type, const Location& loc = Location()) 654 : ExprMixin<ExprType::Select>(loc), result_type(type) {} 655 TypeVector result_type; 656 }; 657 658 class TableInitExpr : public ExprMixin<ExprType::TableInit> { 659 public: 660 TableInitExpr(const Var& segment_index, 661 const Var& table_index, 662 const Location& loc = Location()) 663 : ExprMixin<ExprType::TableInit>(loc), 664 segment_index(segment_index), 665 table_index(table_index) {} 666 667 Var segment_index; 668 Var table_index; 669 }; 670 671 class TableCopyExpr : public ExprMixin<ExprType::TableCopy> { 672 public: 673 TableCopyExpr(const Var& dst, 674 const Var& src, 675 const Location& loc = Location()) 676 : ExprMixin<ExprType::TableCopy>(loc), dst_table(dst), src_table(src) {} 677 678 Var dst_table; 679 Var src_table; 680 }; 681 682 class CallIndirectExpr : public ExprMixin<ExprType::CallIndirect> { 683 public: 684 explicit CallIndirectExpr(const Location& loc = Location()) 685 : ExprMixin<ExprType::CallIndirect>(loc) {} 686 687 FuncDeclaration decl; 688 Var table; 689 }; 690 691 class CodeMetadataExpr : public ExprMixin<ExprType::CodeMetadata> { 692 public: 693 explicit CodeMetadataExpr(std::string_view name, 694 std::vector<uint8_t> data, 695 const Location& loc = Location()) 696 : ExprMixin<ExprType::CodeMetadata>(loc), 697 name(std::move(name)), 698 data(std::move(data)) {} 699 700 std::string_view name; 701 std::vector<uint8_t> data; 702 }; 703 704 class ReturnCallIndirectExpr : public ExprMixin<ExprType::ReturnCallIndirect> { 705 public: 706 explicit ReturnCallIndirectExpr(const Location& loc = Location()) 707 : ExprMixin<ExprType::ReturnCallIndirect>(loc) {} 708 709 FuncDeclaration decl; 710 Var table; 711 }; 712 713 class CallRefExpr : public ExprMixin<ExprType::CallRef> { 714 public: 715 explicit CallRefExpr(const Location& loc = Location()) 716 : ExprMixin<ExprType::CallRef>(loc) {} 717 718 // This field is setup only during Validate phase, 719 // so keep that in mind when you use it. 720 Var function_type_index; 721 }; 722 723 template <ExprType TypeEnum> 724 class BlockExprBase : public ExprMixin<TypeEnum> { 725 public: 726 explicit BlockExprBase(const Location& loc = Location()) 727 : ExprMixin<TypeEnum>(loc) {} 728 729 Block block; 730 }; 731 732 using BlockExpr = BlockExprBase<ExprType::Block>; 733 using LoopExpr = BlockExprBase<ExprType::Loop>; 734 735 class IfExpr : public ExprMixin<ExprType::If> { 736 public: 737 explicit IfExpr(const Location& loc = Location()) 738 : ExprMixin<ExprType::If>(loc) {} 739 740 Block true_; 741 ExprList false_; 742 Location false_end_loc; 743 }; 744 745 class TryExpr : public ExprMixin<ExprType::Try> { 746 public: 747 explicit TryExpr(const Location& loc = Location()) 748 : ExprMixin<ExprType::Try>(loc), kind(TryKind::Plain) {} 749 750 TryKind kind; 751 Block block; 752 CatchVector catches; 753 Var delegate_target; 754 }; 755 756 class BrTableExpr : public ExprMixin<ExprType::BrTable> { 757 public: 758 BrTableExpr(const Location& loc = Location()) 759 : ExprMixin<ExprType::BrTable>(loc) {} 760 761 VarVector targets; 762 Var default_target; 763 }; 764 765 class ConstExpr : public ExprMixin<ExprType::Const> { 766 public: 767 ConstExpr(const Const& c, const Location& loc = Location()) 768 : ExprMixin<ExprType::Const>(loc), const_(c) {} 769 770 Const const_; 771 }; 772 773 // TODO(binji): Rename this, it is used for more than loads/stores now. 774 template <ExprType TypeEnum> 775 class LoadStoreExpr : public MemoryExpr<TypeEnum> { 776 public: 777 LoadStoreExpr(Opcode opcode, 778 Var memidx, 779 Address align, 780 Address offset, 781 const Location& loc = Location()) 782 : MemoryExpr<TypeEnum>(memidx, loc), 783 opcode(opcode), 784 align(align), 785 offset(offset) {} 786 787 Opcode opcode; 788 Address align; 789 Address offset; 790 }; 791 792 using LoadExpr = LoadStoreExpr<ExprType::Load>; 793 using StoreExpr = LoadStoreExpr<ExprType::Store>; 794 795 using AtomicLoadExpr = LoadStoreExpr<ExprType::AtomicLoad>; 796 using AtomicStoreExpr = LoadStoreExpr<ExprType::AtomicStore>; 797 using AtomicRmwExpr = LoadStoreExpr<ExprType::AtomicRmw>; 798 using AtomicRmwCmpxchgExpr = LoadStoreExpr<ExprType::AtomicRmwCmpxchg>; 799 using AtomicWaitExpr = LoadStoreExpr<ExprType::AtomicWait>; 800 using AtomicNotifyExpr = LoadStoreExpr<ExprType::AtomicNotify>; 801 using LoadSplatExpr = LoadStoreExpr<ExprType::LoadSplat>; 802 using LoadZeroExpr = LoadStoreExpr<ExprType::LoadZero>; 803 804 class AtomicFenceExpr : public ExprMixin<ExprType::AtomicFence> { 805 public: 806 explicit AtomicFenceExpr(uint32_t consistency_model, 807 const Location& loc = Location()) 808 : ExprMixin<ExprType::AtomicFence>(loc), 809 consistency_model(consistency_model) {} 810 811 uint32_t consistency_model; 812 }; 813 814 struct Tag { 815 explicit Tag(std::string_view name) : name(name) {} 816 817 std::string name; 818 FuncDeclaration decl; 819 }; 820 821 class LocalTypes { 822 public: 823 using Decl = std::pair<Type, Index>; 824 using Decls = std::vector<Decl>; 825 826 struct const_iterator { 827 const_iterator(Decls::const_iterator decl, Index index) 828 : decl(decl), index(index) {} 829 Type operator*() const { return decl->first; } 830 const_iterator& operator++(); 831 const_iterator operator++(int); 832 833 Decls::const_iterator decl; 834 Index index; 835 }; 836 837 void Set(const TypeVector&); 838 839 const Decls& decls() const { return decls_; } 840 841 void AppendDecl(Type type, Index count) { 842 if (count != 0) { 843 decls_.emplace_back(type, count); 844 } 845 } 846 847 Index size() const; 848 Type operator[](Index) const; 849 850 const_iterator begin() const { return {decls_.begin(), 0}; } 851 const_iterator end() const { return {decls_.end(), 0}; } 852 853 private: 854 Decls decls_; 855 }; 856 857 inline LocalTypes::const_iterator& LocalTypes::const_iterator::operator++() { 858 ++index; 859 if (index >= decl->second) { 860 ++decl; 861 index = 0; 862 } 863 return *this; 864 } 865 866 inline LocalTypes::const_iterator LocalTypes::const_iterator::operator++(int) { 867 const_iterator result = *this; 868 operator++(); 869 return result; 870 } 871 872 inline bool operator==(const LocalTypes::const_iterator& lhs, 873 const LocalTypes::const_iterator& rhs) { 874 return lhs.decl == rhs.decl && lhs.index == rhs.index; 875 } 876 877 inline bool operator!=(const LocalTypes::const_iterator& lhs, 878 const LocalTypes::const_iterator& rhs) { 879 return !operator==(lhs, rhs); 880 } 881 882 struct Func { 883 explicit Func(std::string_view name) : name(name) {} 884 885 Type GetParamType(Index index) const { return decl.GetParamType(index); } 886 Type GetResultType(Index index) const { return decl.GetResultType(index); } 887 Type GetLocalType(Index index) const; 888 Type GetLocalType(const Var& var) const; 889 Index GetNumParams() const { return decl.GetNumParams(); } 890 Index GetNumLocals() const { return local_types.size(); } 891 Index GetNumParamsAndLocals() const { 892 return GetNumParams() + GetNumLocals(); 893 } 894 Index GetNumResults() const { return decl.GetNumResults(); } 895 Index GetLocalIndex(const Var&) const; 896 897 std::string name; 898 FuncDeclaration decl; 899 LocalTypes local_types; 900 BindingHash bindings; 901 ExprList exprs; 902 Location loc; 903 904 // For a subset of features, the BinaryReaderIR tracks whether they are 905 // actually used by the function. wasm2c (CWriter) uses this information to 906 // limit its output in some cases. 907 struct { 908 bool tailcall = false; 909 } features_used; 910 }; 911 912 struct Global { 913 explicit Global(std::string_view name) : name(name) {} 914 915 std::string name; 916 Type type = Type::Void; 917 bool mutable_ = false; 918 ExprList init_expr; 919 }; 920 921 struct Table { 922 explicit Table(std::string_view name) 923 : name(name), elem_type(Type::FuncRef) {} 924 925 std::string name; 926 Limits elem_limits; 927 Type elem_type; 928 }; 929 930 using ExprListVector = std::vector<ExprList>; 931 932 struct ElemSegment { 933 explicit ElemSegment(std::string_view name) : name(name) {} 934 uint8_t GetFlags(const Module*) const; 935 936 SegmentKind kind = SegmentKind::Active; 937 std::string name; 938 Var table_var; 939 Type elem_type; 940 ExprList offset; 941 ExprListVector elem_exprs; 942 }; 943 944 struct Memory { 945 explicit Memory(std::string_view name) : name(name) {} 946 947 std::string name; 948 Limits page_limits; 949 }; 950 951 struct DataSegment { 952 explicit DataSegment(std::string_view name) : name(name) {} 953 uint8_t GetFlags(const Module*) const; 954 955 SegmentKind kind = SegmentKind::Active; 956 std::string name; 957 Var memory_var; 958 ExprList offset; 959 std::vector<uint8_t> data; 960 }; 961 962 class Import { 963 public: 964 WABT_DISALLOW_COPY_AND_ASSIGN(Import); 965 Import() = delete; 966 virtual ~Import() = default; 967 968 ExternalKind kind() const { return kind_; } 969 970 std::string module_name; 971 std::string field_name; 972 973 protected: 974 Import(ExternalKind kind) : kind_(kind) {} 975 976 ExternalKind kind_; 977 }; 978 979 template <ExternalKind TypeEnum> 980 class ImportMixin : public Import { 981 public: 982 static bool classof(const Import* import) { 983 return import->kind() == TypeEnum; 984 } 985 986 ImportMixin() : Import(TypeEnum) {} 987 }; 988 989 class FuncImport : public ImportMixin<ExternalKind::Func> { 990 public: 991 explicit FuncImport(std::string_view name = std::string_view()) 992 : ImportMixin<ExternalKind::Func>(), func(name) {} 993 994 Func func; 995 }; 996 997 class TableImport : public ImportMixin<ExternalKind::Table> { 998 public: 999 explicit TableImport(std::string_view name = std::string_view()) 1000 : ImportMixin<ExternalKind::Table>(), table(name) {} 1001 1002 Table table; 1003 }; 1004 1005 class MemoryImport : public ImportMixin<ExternalKind::Memory> { 1006 public: 1007 explicit MemoryImport(std::string_view name = std::string_view()) 1008 : ImportMixin<ExternalKind::Memory>(), memory(name) {} 1009 1010 Memory memory; 1011 }; 1012 1013 class GlobalImport : public ImportMixin<ExternalKind::Global> { 1014 public: 1015 explicit GlobalImport(std::string_view name = std::string_view()) 1016 : ImportMixin<ExternalKind::Global>(), global(name) {} 1017 1018 Global global; 1019 }; 1020 1021 class TagImport : public ImportMixin<ExternalKind::Tag> { 1022 public: 1023 explicit TagImport(std::string_view name = std::string_view()) 1024 : ImportMixin<ExternalKind::Tag>(), tag(name) {} 1025 1026 Tag tag; 1027 }; 1028 1029 struct Export { 1030 std::string name; 1031 ExternalKind kind; 1032 Var var; 1033 }; 1034 1035 enum class ModuleFieldType { 1036 Func, 1037 Global, 1038 Import, 1039 Export, 1040 Type, 1041 Table, 1042 ElemSegment, 1043 Memory, 1044 DataSegment, 1045 Start, 1046 Tag 1047 }; 1048 1049 class ModuleField : public intrusive_list_base<ModuleField> { 1050 public: 1051 WABT_DISALLOW_COPY_AND_ASSIGN(ModuleField); 1052 ModuleField() = delete; 1053 virtual ~ModuleField() = default; 1054 1055 ModuleFieldType type() const { return type_; } 1056 1057 Location loc; 1058 1059 protected: 1060 ModuleField(ModuleFieldType type, const Location& loc) 1061 : loc(loc), type_(type) {} 1062 1063 ModuleFieldType type_; 1064 }; 1065 1066 using ModuleFieldList = intrusive_list<ModuleField>; 1067 1068 template <ModuleFieldType TypeEnum> 1069 class ModuleFieldMixin : public ModuleField { 1070 public: 1071 static bool classof(const ModuleField* field) { 1072 return field->type() == TypeEnum; 1073 } 1074 1075 explicit ModuleFieldMixin(const Location& loc) : ModuleField(TypeEnum, loc) {} 1076 }; 1077 1078 class FuncModuleField : public ModuleFieldMixin<ModuleFieldType::Func> { 1079 public: 1080 explicit FuncModuleField(const Location& loc = Location(), 1081 std::string_view name = std::string_view()) 1082 : ModuleFieldMixin<ModuleFieldType::Func>(loc), func(name) {} 1083 1084 Func func; 1085 }; 1086 1087 class GlobalModuleField : public ModuleFieldMixin<ModuleFieldType::Global> { 1088 public: 1089 explicit GlobalModuleField(const Location& loc = Location(), 1090 std::string_view name = std::string_view()) 1091 : ModuleFieldMixin<ModuleFieldType::Global>(loc), global(name) {} 1092 1093 Global global; 1094 }; 1095 1096 class ImportModuleField : public ModuleFieldMixin<ModuleFieldType::Import> { 1097 public: 1098 explicit ImportModuleField(const Location& loc = Location()) 1099 : ModuleFieldMixin<ModuleFieldType::Import>(loc) {} 1100 explicit ImportModuleField(std::unique_ptr<Import> import, 1101 const Location& loc = Location()) 1102 : ModuleFieldMixin<ModuleFieldType::Import>(loc), 1103 import(std::move(import)) {} 1104 1105 std::unique_ptr<Import> import; 1106 }; 1107 1108 class ExportModuleField : public ModuleFieldMixin<ModuleFieldType::Export> { 1109 public: 1110 explicit ExportModuleField(const Location& loc = Location()) 1111 : ModuleFieldMixin<ModuleFieldType::Export>(loc) {} 1112 1113 Export export_; 1114 }; 1115 1116 class TypeModuleField : public ModuleFieldMixin<ModuleFieldType::Type> { 1117 public: 1118 explicit TypeModuleField(const Location& loc = Location()) 1119 : ModuleFieldMixin<ModuleFieldType::Type>(loc) {} 1120 1121 std::unique_ptr<TypeEntry> type; 1122 }; 1123 1124 class TableModuleField : public ModuleFieldMixin<ModuleFieldType::Table> { 1125 public: 1126 explicit TableModuleField(const Location& loc = Location(), 1127 std::string_view name = std::string_view()) 1128 : ModuleFieldMixin<ModuleFieldType::Table>(loc), table(name) {} 1129 1130 Table table; 1131 }; 1132 1133 class ElemSegmentModuleField 1134 : public ModuleFieldMixin<ModuleFieldType::ElemSegment> { 1135 public: 1136 explicit ElemSegmentModuleField(const Location& loc = Location(), 1137 std::string_view name = std::string_view()) 1138 : ModuleFieldMixin<ModuleFieldType::ElemSegment>(loc), 1139 elem_segment(name) {} 1140 1141 ElemSegment elem_segment; 1142 }; 1143 1144 class MemoryModuleField : public ModuleFieldMixin<ModuleFieldType::Memory> { 1145 public: 1146 explicit MemoryModuleField(const Location& loc = Location(), 1147 std::string_view name = std::string_view()) 1148 : ModuleFieldMixin<ModuleFieldType::Memory>(loc), memory(name) {} 1149 1150 Memory memory; 1151 }; 1152 1153 class DataSegmentModuleField 1154 : public ModuleFieldMixin<ModuleFieldType::DataSegment> { 1155 public: 1156 explicit DataSegmentModuleField(const Location& loc = Location(), 1157 std::string_view name = std::string_view()) 1158 : ModuleFieldMixin<ModuleFieldType::DataSegment>(loc), 1159 data_segment(name) {} 1160 1161 DataSegment data_segment; 1162 }; 1163 1164 class TagModuleField : public ModuleFieldMixin<ModuleFieldType::Tag> { 1165 public: 1166 explicit TagModuleField(const Location& loc = Location(), 1167 std::string_view name = std::string_view()) 1168 : ModuleFieldMixin<ModuleFieldType::Tag>(loc), tag(name) {} 1169 1170 Tag tag; 1171 }; 1172 1173 class StartModuleField : public ModuleFieldMixin<ModuleFieldType::Start> { 1174 public: 1175 explicit StartModuleField(Var start = Var(), const Location& loc = Location()) 1176 : ModuleFieldMixin<ModuleFieldType::Start>(loc), start(start) {} 1177 1178 Var start; 1179 }; 1180 1181 struct Custom { 1182 explicit Custom(const Location& loc = Location(), 1183 std::string_view name = std::string_view(), 1184 std::vector<uint8_t> data = std::vector<uint8_t>()) 1185 : name(name), data(data), loc(loc) {} 1186 1187 std::string name; 1188 std::vector<uint8_t> data; 1189 Location loc; 1190 }; 1191 1192 struct Module { 1193 Index GetFuncTypeIndex(const Var&) const; 1194 Index GetFuncTypeIndex(const FuncDeclaration&) const; 1195 Index GetFuncTypeIndex(const FuncSignature&) const; 1196 const FuncType* GetFuncType(const Var&) const; 1197 FuncType* GetFuncType(const Var&); 1198 Index GetFuncIndex(const Var&) const; 1199 const Func* GetFunc(const Var&) const; 1200 Func* GetFunc(const Var&); 1201 Index GetTableIndex(const Var&) const; 1202 const Table* GetTable(const Var&) const; 1203 Table* GetTable(const Var&); 1204 Index GetMemoryIndex(const Var&) const; 1205 const Memory* GetMemory(const Var&) const; 1206 Memory* GetMemory(const Var&); 1207 Index GetGlobalIndex(const Var&) const; 1208 const Global* GetGlobal(const Var&) const; 1209 Global* GetGlobal(const Var&); 1210 const Export* GetExport(std::string_view) const; 1211 Tag* GetTag(const Var&) const; 1212 Index GetTagIndex(const Var&) const; 1213 const DataSegment* GetDataSegment(const Var&) const; 1214 DataSegment* GetDataSegment(const Var&); 1215 Index GetDataSegmentIndex(const Var&) const; 1216 const ElemSegment* GetElemSegment(const Var&) const; 1217 ElemSegment* GetElemSegment(const Var&); 1218 Index GetElemSegmentIndex(const Var&) const; 1219 1220 bool IsImport(ExternalKind kind, const Var&) const; 1221 bool IsImport(const Export& export_) const { 1222 return IsImport(export_.kind, export_.var); 1223 } 1224 1225 // TODO(binji): move this into a builder class? 1226 void AppendField(std::unique_ptr<DataSegmentModuleField>); 1227 void AppendField(std::unique_ptr<ElemSegmentModuleField>); 1228 void AppendField(std::unique_ptr<TagModuleField>); 1229 void AppendField(std::unique_ptr<ExportModuleField>); 1230 void AppendField(std::unique_ptr<FuncModuleField>); 1231 void AppendField(std::unique_ptr<TypeModuleField>); 1232 void AppendField(std::unique_ptr<GlobalModuleField>); 1233 void AppendField(std::unique_ptr<ImportModuleField>); 1234 void AppendField(std::unique_ptr<MemoryModuleField>); 1235 void AppendField(std::unique_ptr<StartModuleField>); 1236 void AppendField(std::unique_ptr<TableModuleField>); 1237 void AppendField(std::unique_ptr<ModuleField>); 1238 void AppendFields(ModuleFieldList*); 1239 1240 Location loc; 1241 std::string name; 1242 ModuleFieldList fields; 1243 1244 Index num_tag_imports = 0; 1245 Index num_func_imports = 0; 1246 Index num_table_imports = 0; 1247 Index num_memory_imports = 0; 1248 Index num_global_imports = 0; 1249 1250 // Cached for convenience; the pointers are shared with values that are 1251 // stored in either ModuleField or Import. 1252 std::vector<Tag*> tags; 1253 std::vector<Func*> funcs; 1254 std::vector<Global*> globals; 1255 std::vector<Import*> imports; 1256 std::vector<Export*> exports; 1257 std::vector<TypeEntry*> types; 1258 std::vector<Table*> tables; 1259 std::vector<ElemSegment*> elem_segments; 1260 std::vector<Memory*> memories; 1261 std::vector<DataSegment*> data_segments; 1262 std::vector<Var*> starts; 1263 std::vector<Custom> customs; 1264 1265 BindingHash tag_bindings; 1266 BindingHash func_bindings; 1267 BindingHash global_bindings; 1268 BindingHash export_bindings; 1269 BindingHash type_bindings; 1270 BindingHash table_bindings; 1271 BindingHash memory_bindings; 1272 BindingHash data_segment_bindings; 1273 BindingHash elem_segment_bindings; 1274 1275 // For a subset of features, the BinaryReaderIR tracks whether they are 1276 // actually used by the module. wasm2c (CWriter) uses this information to 1277 // limit its output in some cases. 1278 struct { 1279 bool simd = false; 1280 bool exceptions = false; 1281 bool threads = false; 1282 } features_used; 1283 }; 1284 1285 enum class ScriptModuleType { 1286 Text, 1287 Binary, 1288 Quoted, 1289 }; 1290 1291 // A ScriptModule is a module that may not yet be decoded. This allows for text 1292 // and binary parsing errors to be deferred until validation time. 1293 class ScriptModule { 1294 public: 1295 WABT_DISALLOW_COPY_AND_ASSIGN(ScriptModule); 1296 ScriptModule() = delete; 1297 virtual ~ScriptModule() = default; 1298 1299 ScriptModuleType type() const { return type_; } 1300 virtual const Location& location() const = 0; 1301 1302 protected: 1303 explicit ScriptModule(ScriptModuleType type) : type_(type) {} 1304 1305 ScriptModuleType type_; 1306 }; 1307 1308 template <ScriptModuleType TypeEnum> 1309 class ScriptModuleMixin : public ScriptModule { 1310 public: 1311 static bool classof(const ScriptModule* script_module) { 1312 return script_module->type() == TypeEnum; 1313 } 1314 1315 ScriptModuleMixin() : ScriptModule(TypeEnum) {} 1316 }; 1317 1318 class TextScriptModule : public ScriptModuleMixin<ScriptModuleType::Text> { 1319 public: 1320 const Location& location() const override { return module.loc; } 1321 1322 Module module; 1323 }; 1324 1325 template <ScriptModuleType TypeEnum> 1326 class DataScriptModule : public ScriptModuleMixin<TypeEnum> { 1327 public: 1328 const Location& location() const override { return loc; } 1329 1330 Location loc; 1331 std::string name; 1332 std::vector<uint8_t> data; 1333 }; 1334 1335 using BinaryScriptModule = DataScriptModule<ScriptModuleType::Binary>; 1336 using QuotedScriptModule = DataScriptModule<ScriptModuleType::Quoted>; 1337 1338 enum class ActionType { 1339 Invoke, 1340 Get, 1341 }; 1342 1343 class Action { 1344 public: 1345 WABT_DISALLOW_COPY_AND_ASSIGN(Action); 1346 Action() = delete; 1347 virtual ~Action() = default; 1348 1349 ActionType type() const { return type_; } 1350 1351 Location loc; 1352 Var module_var; 1353 std::string name; 1354 1355 protected: 1356 explicit Action(ActionType type, const Location& loc = Location()) 1357 : loc(loc), type_(type) {} 1358 1359 ActionType type_; 1360 }; 1361 1362 using ActionPtr = std::unique_ptr<Action>; 1363 1364 template <ActionType TypeEnum> 1365 class ActionMixin : public Action { 1366 public: 1367 static bool classof(const Action* action) { 1368 return action->type() == TypeEnum; 1369 } 1370 1371 explicit ActionMixin(const Location& loc = Location()) 1372 : Action(TypeEnum, loc) {} 1373 }; 1374 1375 class GetAction : public ActionMixin<ActionType::Get> { 1376 public: 1377 explicit GetAction(const Location& loc = Location()) 1378 : ActionMixin<ActionType::Get>(loc) {} 1379 }; 1380 1381 class InvokeAction : public ActionMixin<ActionType::Invoke> { 1382 public: 1383 explicit InvokeAction(const Location& loc = Location()) 1384 : ActionMixin<ActionType::Invoke>(loc) {} 1385 1386 ConstVector args; 1387 }; 1388 1389 enum class CommandType { 1390 Module, 1391 ScriptModule, 1392 Action, 1393 Register, 1394 AssertMalformed, 1395 AssertInvalid, 1396 AssertUnlinkable, 1397 AssertUninstantiable, 1398 AssertReturn, 1399 AssertTrap, 1400 AssertExhaustion, 1401 AssertException, 1402 1403 First = Module, 1404 Last = AssertException, 1405 }; 1406 constexpr int kCommandTypeCount = WABT_ENUM_COUNT(CommandType); 1407 1408 class Command { 1409 public: 1410 WABT_DISALLOW_COPY_AND_ASSIGN(Command); 1411 Command() = delete; 1412 virtual ~Command() = default; 1413 1414 CommandType type; 1415 1416 protected: 1417 explicit Command(CommandType type) : type(type) {} 1418 }; 1419 1420 template <CommandType TypeEnum> 1421 class CommandMixin : public Command { 1422 public: 1423 static bool classof(const Command* cmd) { return cmd->type == TypeEnum; } 1424 CommandMixin() : Command(TypeEnum) {} 1425 }; 1426 1427 class ModuleCommand : public CommandMixin<CommandType::Module> { 1428 public: 1429 Module module; 1430 }; 1431 1432 class ScriptModuleCommand : public CommandMixin<CommandType::ScriptModule> { 1433 public: 1434 // Both the module and the script_module need to be stored since the module 1435 // has the parsed information about the module, but the script_module has the 1436 // original contents (binary or quoted). 1437 Module module; 1438 std::unique_ptr<ScriptModule> script_module; 1439 }; 1440 1441 template <CommandType TypeEnum> 1442 class ActionCommandBase : public CommandMixin<TypeEnum> { 1443 public: 1444 ActionPtr action; 1445 }; 1446 1447 using ActionCommand = ActionCommandBase<CommandType::Action>; 1448 1449 class RegisterCommand : public CommandMixin<CommandType::Register> { 1450 public: 1451 RegisterCommand(std::string_view module_name, const Var& var) 1452 : module_name(module_name), var(var) {} 1453 1454 std::string module_name; 1455 Var var; 1456 }; 1457 1458 class AssertReturnCommand : public CommandMixin<CommandType::AssertReturn> { 1459 public: 1460 ActionPtr action; 1461 ExpectationPtr expected; 1462 }; 1463 1464 template <CommandType TypeEnum> 1465 class AssertTrapCommandBase : public CommandMixin<TypeEnum> { 1466 public: 1467 ActionPtr action; 1468 std::string text; 1469 }; 1470 1471 using AssertTrapCommand = AssertTrapCommandBase<CommandType::AssertTrap>; 1472 using AssertExhaustionCommand = 1473 AssertTrapCommandBase<CommandType::AssertExhaustion>; 1474 1475 template <CommandType TypeEnum> 1476 class AssertModuleCommand : public CommandMixin<TypeEnum> { 1477 public: 1478 std::unique_ptr<ScriptModule> module; 1479 std::string text; 1480 }; 1481 1482 using AssertMalformedCommand = 1483 AssertModuleCommand<CommandType::AssertMalformed>; 1484 using AssertInvalidCommand = AssertModuleCommand<CommandType::AssertInvalid>; 1485 using AssertUnlinkableCommand = 1486 AssertModuleCommand<CommandType::AssertUnlinkable>; 1487 using AssertUninstantiableCommand = 1488 AssertModuleCommand<CommandType::AssertUninstantiable>; 1489 1490 class AssertExceptionCommand 1491 : public CommandMixin<CommandType::AssertException> { 1492 public: 1493 ActionPtr action; 1494 }; 1495 1496 using CommandPtr = std::unique_ptr<Command>; 1497 using CommandPtrVector = std::vector<CommandPtr>; 1498 1499 struct Script { 1500 WABT_DISALLOW_COPY_AND_ASSIGN(Script); 1501 Script() = default; 1502 1503 const Module* GetFirstModule() const; 1504 Module* GetFirstModule(); 1505 const Module* GetModule(const Var&) const; 1506 1507 CommandPtrVector commands; 1508 BindingHash module_bindings; 1509 }; 1510 1511 void MakeTypeBindingReverseMapping( 1512 size_t num_types, 1513 const BindingHash& bindings, 1514 std::vector<std::string>* out_reverse_mapping); 1515 1516 } // namespace wabt 1517 1518 #endif /* WABT_IR_H_ */