1 // Copyright 2018 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_TORQUE_INSTRUCTIONS_H_ 6 #define V8_TORQUE_INSTRUCTIONS_H_ 7 8 #include <memory> 9 10 #include "src/torque/ast.h" 11 #include "src/torque/source-positions.h" 12 #include "src/torque/types.h" 13 #include "src/torque/utils.h" 14 15 namespace v8 { 16 namespace internal { 17 namespace torque { 18 19 class Block; 20 class Builtin; 21 class ControlFlowGraph; 22 class Intrinsic; 23 class Macro; 24 class NamespaceConstant; 25 class RuntimeFunction; 26 27 // Instructions where all backends generate code the same way. 28 #define TORQUE_BACKEND_AGNOSTIC_INSTRUCTION_LIST(V) \ 29 V(PeekInstruction) \ 30 V(PokeInstruction) \ 31 V(DeleteRangeInstruction) 32 33 // Instructions where different backends may generate different code. 34 #define TORQUE_BACKEND_DEPENDENT_INSTRUCTION_LIST(V) \ 35 V(PushUninitializedInstruction) \ 36 V(PushBuiltinPointerInstruction) \ 37 V(LoadReferenceInstruction) \ 38 V(StoreReferenceInstruction) \ 39 V(LoadBitFieldInstruction) \ 40 V(StoreBitFieldInstruction) \ 41 V(CallCsaMacroInstruction) \ 42 V(CallIntrinsicInstruction) \ 43 V(NamespaceConstantInstruction) \ 44 V(CallCsaMacroAndBranchInstruction) \ 45 V(CallBuiltinInstruction) \ 46 V(CallRuntimeInstruction) \ 47 V(CallBuiltinPointerInstruction) \ 48 V(BranchInstruction) \ 49 V(ConstexprBranchInstruction) \ 50 V(GotoInstruction) \ 51 V(GotoExternalInstruction) \ 52 V(ReturnInstruction) \ 53 V(PrintConstantStringInstruction) \ 54 V(AbortInstruction) \ 55 V(UnsafeCastInstruction) 56 57 #define TORQUE_INSTRUCTION_LIST(V) \ 58 TORQUE_BACKEND_AGNOSTIC_INSTRUCTION_LIST(V) \ 59 TORQUE_BACKEND_DEPENDENT_INSTRUCTION_LIST(V) 60 61 #define TORQUE_INSTRUCTION_BOILERPLATE() \ 62 static const InstructionKind kKind; \ 63 std::unique_ptr<InstructionBase> Clone() const override; \ 64 void Assign(const InstructionBase& other) override; \ 65 void TypeInstruction(Stack<const Type*>* stack, ControlFlowGraph* cfg) \ 66 const override; \ 67 void RecomputeDefinitionLocations(Stack<DefinitionLocation>* locations, \ 68 Worklist<Block*>* worklist) \ 69 const override; 70 71 enum class InstructionKind { 72 #define ENUM_ITEM(name) k##name, 73 TORQUE_INSTRUCTION_LIST(ENUM_ITEM) 74 #undef ENUM_ITEM 75 }; 76 77 struct InstructionBase; 78 79 class DefinitionLocation { 80 public: 81 enum class Kind { 82 kInvalid, 83 kParameter, 84 kPhi, 85 kInstruction, 86 }; 87 DefinitionLocation()88 DefinitionLocation() : kind_(Kind::kInvalid), location_(nullptr), index_(0) {} 89 Parameter(std::size_t index)90 static DefinitionLocation Parameter(std::size_t index) { 91 return DefinitionLocation(Kind::kParameter, nullptr, index); 92 } 93 Phi(const Block * block,std::size_t index)94 static DefinitionLocation Phi(const Block* block, std::size_t index) { 95 return DefinitionLocation(Kind::kPhi, block, index); 96 } 97 98 static DefinitionLocation Instruction(const InstructionBase* instruction, 99 std::size_t index = 0) { 100 return DefinitionLocation(Kind::kInstruction, instruction, index); 101 } 102 GetKind()103 Kind GetKind() const { return kind_; } IsValid()104 bool IsValid() const { return kind_ != Kind::kInvalid; } IsParameter()105 bool IsParameter() const { return kind_ == Kind::kParameter; } IsPhi()106 bool IsPhi() const { return kind_ == Kind::kPhi; } IsInstruction()107 bool IsInstruction() const { return kind_ == Kind::kInstruction; } 108 GetParameterIndex()109 std::size_t GetParameterIndex() const { 110 DCHECK(IsParameter()); 111 return index_; 112 } 113 GetPhiBlock()114 const Block* GetPhiBlock() const { 115 DCHECK(IsPhi()); 116 return reinterpret_cast<const Block*>(location_); 117 } 118 IsPhiFromBlock(const Block * block)119 bool IsPhiFromBlock(const Block* block) const { 120 return IsPhi() && GetPhiBlock() == block; 121 } 122 GetPhiIndex()123 std::size_t GetPhiIndex() const { 124 DCHECK(IsPhi()); 125 return index_; 126 } 127 GetInstruction()128 const InstructionBase* GetInstruction() const { 129 DCHECK(IsInstruction()); 130 return reinterpret_cast<const InstructionBase*>(location_); 131 } 132 GetInstructionIndex()133 std::size_t GetInstructionIndex() const { 134 DCHECK(IsInstruction()); 135 return index_; 136 } 137 138 bool operator==(const DefinitionLocation& other) const { 139 if (kind_ != other.kind_) return false; 140 if (location_ != other.location_) return false; 141 return index_ == other.index_; 142 } 143 144 bool operator!=(const DefinitionLocation& other) const { 145 return !operator==(other); 146 } 147 148 bool operator<(const DefinitionLocation& other) const { 149 if (kind_ != other.kind_) { 150 return static_cast<int>(kind_) < static_cast<int>(other.kind_); 151 } 152 if (location_ != other.location_) { 153 return location_ < other.location_; 154 } 155 return index_ < other.index_; 156 } 157 158 private: DefinitionLocation(Kind kind,const void * location,std::size_t index)159 DefinitionLocation(Kind kind, const void* location, std::size_t index) 160 : kind_(kind), location_(location), index_(index) {} 161 162 Kind kind_; 163 const void* location_; 164 std::size_t index_; 165 }; 166 167 inline std::ostream& operator<<(std::ostream& stream, 168 const DefinitionLocation& loc) { 169 switch (loc.GetKind()) { 170 case DefinitionLocation::Kind::kInvalid: 171 return stream << "DefinitionLocation::Invalid()"; 172 case DefinitionLocation::Kind::kParameter: 173 return stream << "DefinitionLocation::Parameter(" 174 << loc.GetParameterIndex() << ")"; 175 case DefinitionLocation::Kind::kPhi: 176 return stream << "DefinitionLocation::Phi(" << std::hex 177 << loc.GetPhiBlock() << std::dec << ", " 178 << loc.GetPhiIndex() << ")"; 179 case DefinitionLocation::Kind::kInstruction: 180 return stream << "DefinitionLocation::Instruction(" << std::hex 181 << loc.GetInstruction() << std::dec << ", " 182 << loc.GetInstructionIndex() << ")"; 183 } 184 } 185 186 struct InstructionBase { InstructionBaseInstructionBase187 InstructionBase() : pos(CurrentSourcePosition::Get()) {} 188 virtual std::unique_ptr<InstructionBase> Clone() const = 0; 189 virtual void Assign(const InstructionBase& other) = 0; 190 virtual ~InstructionBase() = default; 191 192 virtual void TypeInstruction(Stack<const Type*>* stack, 193 ControlFlowGraph* cfg) const = 0; 194 virtual void RecomputeDefinitionLocations( 195 Stack<DefinitionLocation>* locations, 196 Worklist<Block*>* worklist) const = 0; 197 void InvalidateTransientTypes(Stack<const Type*>* stack) const; IsBlockTerminatorInstructionBase198 virtual bool IsBlockTerminator() const { return false; } AppendSuccessorBlocksInstructionBase199 virtual void AppendSuccessorBlocks(std::vector<Block*>* block_list) const {} 200 201 SourcePosition pos; 202 }; 203 204 class Instruction { 205 public: 206 template <class T> Instruction(T instr)207 Instruction(T instr) // NOLINT(runtime/explicit) 208 : kind_(T::kKind), instruction_(new T(std::move(instr))) {} 209 210 template <class T> Cast()211 T& Cast() { 212 DCHECK(Is<T>()); 213 return static_cast<T&>(*instruction_); 214 } 215 216 template <class T> Cast()217 const T& Cast() const { 218 DCHECK(Is<T>()); 219 return static_cast<const T&>(*instruction_); 220 } 221 222 template <class T> Is()223 bool Is() const { 224 return kind_ == T::kKind; 225 } 226 227 template <class T> DynamicCast()228 T* DynamicCast() { 229 if (Is<T>()) return &Cast<T>(); 230 return nullptr; 231 } 232 233 template <class T> DynamicCast()234 const T* DynamicCast() const { 235 if (Is<T>()) return &Cast<T>(); 236 return nullptr; 237 } 238 Instruction(const Instruction & other)239 Instruction(const Instruction& other) V8_NOEXCEPT 240 : kind_(other.kind_), 241 instruction_(other.instruction_->Clone()) {} 242 Instruction& operator=(const Instruction& other) V8_NOEXCEPT { 243 if (kind_ == other.kind_) { 244 instruction_->Assign(*other.instruction_); 245 } else { 246 kind_ = other.kind_; 247 instruction_ = other.instruction_->Clone(); 248 } 249 return *this; 250 } 251 kind()252 InstructionKind kind() const { return kind_; } Mnemonic()253 const char* Mnemonic() const { 254 switch (kind()) { 255 #define ENUM_ITEM(name) \ 256 case InstructionKind::k##name: \ 257 return #name; 258 TORQUE_INSTRUCTION_LIST(ENUM_ITEM) 259 #undef ENUM_ITEM 260 default: 261 UNREACHABLE(); 262 } 263 } TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg)264 void TypeInstruction(Stack<const Type*>* stack, ControlFlowGraph* cfg) const { 265 return instruction_->TypeInstruction(stack, cfg); 266 } RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist)267 void RecomputeDefinitionLocations(Stack<DefinitionLocation>* locations, 268 Worklist<Block*>* worklist) const { 269 instruction_->RecomputeDefinitionLocations(locations, worklist); 270 } 271 272 InstructionBase* operator->() { return instruction_.get(); } 273 const InstructionBase* operator->() const { return instruction_.get(); } 274 275 private: 276 InstructionKind kind_; 277 std::unique_ptr<InstructionBase> instruction_; 278 }; 279 280 struct PeekInstruction : InstructionBase { 281 TORQUE_INSTRUCTION_BOILERPLATE() 282 PeekInstructionPeekInstruction283 PeekInstruction(BottomOffset slot, base::Optional<const Type*> widened_type) 284 : slot(slot), widened_type(widened_type) {} 285 286 BottomOffset slot; 287 base::Optional<const Type*> widened_type; 288 }; 289 290 struct PokeInstruction : InstructionBase { 291 TORQUE_INSTRUCTION_BOILERPLATE() 292 PokeInstructionPokeInstruction293 PokeInstruction(BottomOffset slot, base::Optional<const Type*> widened_type) 294 : slot(slot), widened_type(widened_type) {} 295 296 BottomOffset slot; 297 base::Optional<const Type*> widened_type; 298 }; 299 300 // Preserve the top {preserved_slots} number of slots, and delete 301 // {deleted_slots} number or slots below. 302 struct DeleteRangeInstruction : InstructionBase { TORQUE_INSTRUCTION_BOILERPLATEDeleteRangeInstruction303 TORQUE_INSTRUCTION_BOILERPLATE() 304 explicit DeleteRangeInstruction(StackRange range) : range(range) {} 305 306 StackRange range; 307 }; 308 309 struct PushUninitializedInstruction : InstructionBase { TORQUE_INSTRUCTION_BOILERPLATEPushUninitializedInstruction310 TORQUE_INSTRUCTION_BOILERPLATE() 311 explicit PushUninitializedInstruction(const Type* type) : type(type) {} 312 313 DefinitionLocation GetValueDefinition() const; 314 315 const Type* type; 316 }; 317 318 struct PushBuiltinPointerInstruction : InstructionBase { 319 TORQUE_INSTRUCTION_BOILERPLATE() PushBuiltinPointerInstructionPushBuiltinPointerInstruction320 PushBuiltinPointerInstruction(std::string external_name, const Type* type) 321 : external_name(std::move(external_name)), type(type) { 322 DCHECK(type->IsBuiltinPointerType()); 323 } 324 325 DefinitionLocation GetValueDefinition() const; 326 327 std::string external_name; 328 const Type* type; 329 }; 330 331 struct NamespaceConstantInstruction : InstructionBase { TORQUE_INSTRUCTION_BOILERPLATENamespaceConstantInstruction332 TORQUE_INSTRUCTION_BOILERPLATE() 333 explicit NamespaceConstantInstruction(NamespaceConstant* constant) 334 : constant(constant) {} 335 336 std::size_t GetValueDefinitionCount() const; 337 DefinitionLocation GetValueDefinition(std::size_t index) const; 338 339 NamespaceConstant* constant; 340 }; 341 342 struct LoadReferenceInstruction : InstructionBase { TORQUE_INSTRUCTION_BOILERPLATELoadReferenceInstruction343 TORQUE_INSTRUCTION_BOILERPLATE() 344 explicit LoadReferenceInstruction(const Type* type) : type(type) {} 345 346 DefinitionLocation GetValueDefinition() const; 347 348 const Type* type; 349 }; 350 351 struct StoreReferenceInstruction : InstructionBase { TORQUE_INSTRUCTION_BOILERPLATEStoreReferenceInstruction352 TORQUE_INSTRUCTION_BOILERPLATE() 353 explicit StoreReferenceInstruction(const Type* type) : type(type) {} 354 const Type* type; 355 }; 356 357 // Pops a bitfield struct; pushes a bitfield value extracted from it. 358 struct LoadBitFieldInstruction : InstructionBase { 359 TORQUE_INSTRUCTION_BOILERPLATE() LoadBitFieldInstructionLoadBitFieldInstruction360 LoadBitFieldInstruction(const Type* bit_field_struct_type, BitField bit_field) 361 : bit_field_struct_type(bit_field_struct_type), 362 bit_field(std::move(bit_field)) {} 363 364 DefinitionLocation GetValueDefinition() const; 365 366 const Type* bit_field_struct_type; 367 BitField bit_field; 368 }; 369 370 // Pops a bitfield value and a bitfield struct; pushes a new bitfield struct 371 // containing the updated value. 372 struct StoreBitFieldInstruction : InstructionBase { 373 TORQUE_INSTRUCTION_BOILERPLATE() StoreBitFieldInstructionStoreBitFieldInstruction374 StoreBitFieldInstruction(const Type* bit_field_struct_type, 375 BitField bit_field, bool starts_as_zero) 376 : bit_field_struct_type(bit_field_struct_type), 377 bit_field(std::move(bit_field)), 378 starts_as_zero(starts_as_zero) {} 379 380 DefinitionLocation GetValueDefinition() const; 381 382 const Type* bit_field_struct_type; 383 BitField bit_field; 384 // Allows skipping the mask step if we know the starting value is zero. 385 bool starts_as_zero; 386 }; 387 388 struct CallIntrinsicInstruction : InstructionBase { 389 TORQUE_INSTRUCTION_BOILERPLATE() CallIntrinsicInstructionCallIntrinsicInstruction390 CallIntrinsicInstruction(Intrinsic* intrinsic, 391 TypeVector specialization_types, 392 std::vector<std::string> constexpr_arguments) 393 : intrinsic(intrinsic), 394 specialization_types(std::move(specialization_types)), 395 constexpr_arguments(constexpr_arguments) {} 396 397 std::size_t GetValueDefinitionCount() const; 398 DefinitionLocation GetValueDefinition(std::size_t index) const; 399 400 Intrinsic* intrinsic; 401 TypeVector specialization_types; 402 std::vector<std::string> constexpr_arguments; 403 }; 404 405 struct CallCsaMacroInstruction : InstructionBase { 406 TORQUE_INSTRUCTION_BOILERPLATE() CallCsaMacroInstructionCallCsaMacroInstruction407 CallCsaMacroInstruction(Macro* macro, 408 std::vector<std::string> constexpr_arguments, 409 base::Optional<Block*> catch_block) 410 : macro(macro), 411 constexpr_arguments(constexpr_arguments), 412 catch_block(catch_block) {} AppendSuccessorBlocksCallCsaMacroInstruction413 void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override { 414 if (catch_block) block_list->push_back(*catch_block); 415 } 416 417 base::Optional<DefinitionLocation> GetExceptionObjectDefinition() const; 418 std::size_t GetValueDefinitionCount() const; 419 DefinitionLocation GetValueDefinition(std::size_t index) const; 420 421 Macro* macro; 422 std::vector<std::string> constexpr_arguments; 423 base::Optional<Block*> catch_block; 424 }; 425 426 struct CallCsaMacroAndBranchInstruction : InstructionBase { 427 TORQUE_INSTRUCTION_BOILERPLATE() CallCsaMacroAndBranchInstructionCallCsaMacroAndBranchInstruction428 CallCsaMacroAndBranchInstruction(Macro* macro, 429 std::vector<std::string> constexpr_arguments, 430 base::Optional<Block*> return_continuation, 431 std::vector<Block*> label_blocks, 432 base::Optional<Block*> catch_block) 433 : macro(macro), 434 constexpr_arguments(constexpr_arguments), 435 return_continuation(return_continuation), 436 label_blocks(label_blocks), 437 catch_block(catch_block) {} IsBlockTerminatorCallCsaMacroAndBranchInstruction438 bool IsBlockTerminator() const override { return true; } AppendSuccessorBlocksCallCsaMacroAndBranchInstruction439 void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override { 440 if (catch_block) block_list->push_back(*catch_block); 441 if (return_continuation) block_list->push_back(*return_continuation); 442 for (Block* block : label_blocks) block_list->push_back(block); 443 } 444 445 std::size_t GetLabelCount() const; 446 std::size_t GetLabelValueDefinitionCount(std::size_t label) const; 447 DefinitionLocation GetLabelValueDefinition(std::size_t label, 448 std::size_t index) const; 449 std::size_t GetValueDefinitionCount() const; 450 DefinitionLocation GetValueDefinition(std::size_t index) const; 451 base::Optional<DefinitionLocation> GetExceptionObjectDefinition() const; 452 453 Macro* macro; 454 std::vector<std::string> constexpr_arguments; 455 base::Optional<Block*> return_continuation; 456 std::vector<Block*> label_blocks; 457 base::Optional<Block*> catch_block; 458 }; 459 460 struct CallBuiltinInstruction : InstructionBase { TORQUE_INSTRUCTION_BOILERPLATECallBuiltinInstruction461 TORQUE_INSTRUCTION_BOILERPLATE() 462 bool IsBlockTerminator() const override { return is_tailcall; } CallBuiltinInstructionCallBuiltinInstruction463 CallBuiltinInstruction(bool is_tailcall, Builtin* builtin, size_t argc, 464 base::Optional<Block*> catch_block) 465 : is_tailcall(is_tailcall), 466 builtin(builtin), 467 argc(argc), 468 catch_block(catch_block) {} AppendSuccessorBlocksCallBuiltinInstruction469 void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override { 470 if (catch_block) block_list->push_back(*catch_block); 471 } 472 473 std::size_t GetValueDefinitionCount() const; 474 DefinitionLocation GetValueDefinition(std::size_t index) const; 475 base::Optional<DefinitionLocation> GetExceptionObjectDefinition() const; 476 477 bool is_tailcall; 478 Builtin* builtin; 479 size_t argc; 480 base::Optional<Block*> catch_block; 481 }; 482 483 struct CallBuiltinPointerInstruction : InstructionBase { TORQUE_INSTRUCTION_BOILERPLATECallBuiltinPointerInstruction484 TORQUE_INSTRUCTION_BOILERPLATE() 485 bool IsBlockTerminator() const override { return is_tailcall; } CallBuiltinPointerInstructionCallBuiltinPointerInstruction486 CallBuiltinPointerInstruction(bool is_tailcall, 487 const BuiltinPointerType* type, size_t argc) 488 : is_tailcall(is_tailcall), type(type), argc(argc) {} 489 490 std::size_t GetValueDefinitionCount() const; 491 DefinitionLocation GetValueDefinition(std::size_t index) const; 492 493 bool is_tailcall; 494 const BuiltinPointerType* type; 495 size_t argc; 496 }; 497 498 struct CallRuntimeInstruction : InstructionBase { 499 TORQUE_INSTRUCTION_BOILERPLATE() 500 bool IsBlockTerminator() const override; 501 CallRuntimeInstructionCallRuntimeInstruction502 CallRuntimeInstruction(bool is_tailcall, RuntimeFunction* runtime_function, 503 size_t argc, base::Optional<Block*> catch_block) 504 : is_tailcall(is_tailcall), 505 runtime_function(runtime_function), 506 argc(argc), 507 catch_block(catch_block) {} AppendSuccessorBlocksCallRuntimeInstruction508 void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override { 509 if (catch_block) block_list->push_back(*catch_block); 510 } 511 512 std::size_t GetValueDefinitionCount() const; 513 DefinitionLocation GetValueDefinition(std::size_t index) const; 514 base::Optional<DefinitionLocation> GetExceptionObjectDefinition() const; 515 516 bool is_tailcall; 517 RuntimeFunction* runtime_function; 518 size_t argc; 519 base::Optional<Block*> catch_block; 520 }; 521 522 struct BranchInstruction : InstructionBase { TORQUE_INSTRUCTION_BOILERPLATEBranchInstruction523 TORQUE_INSTRUCTION_BOILERPLATE() 524 bool IsBlockTerminator() const override { return true; } AppendSuccessorBlocksBranchInstruction525 void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override { 526 block_list->push_back(if_true); 527 block_list->push_back(if_false); 528 } 529 BranchInstructionBranchInstruction530 BranchInstruction(Block* if_true, Block* if_false) 531 : if_true(if_true), if_false(if_false) {} 532 533 Block* if_true; 534 Block* if_false; 535 }; 536 537 struct ConstexprBranchInstruction : InstructionBase { TORQUE_INSTRUCTION_BOILERPLATEConstexprBranchInstruction538 TORQUE_INSTRUCTION_BOILERPLATE() 539 bool IsBlockTerminator() const override { return true; } AppendSuccessorBlocksConstexprBranchInstruction540 void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override { 541 block_list->push_back(if_true); 542 block_list->push_back(if_false); 543 } 544 ConstexprBranchInstructionConstexprBranchInstruction545 ConstexprBranchInstruction(std::string condition, Block* if_true, 546 Block* if_false) 547 : condition(condition), if_true(if_true), if_false(if_false) {} 548 549 std::string condition; 550 Block* if_true; 551 Block* if_false; 552 }; 553 554 struct GotoInstruction : InstructionBase { TORQUE_INSTRUCTION_BOILERPLATEGotoInstruction555 TORQUE_INSTRUCTION_BOILERPLATE() 556 bool IsBlockTerminator() const override { return true; } AppendSuccessorBlocksGotoInstruction557 void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override { 558 block_list->push_back(destination); 559 } 560 GotoInstructionGotoInstruction561 explicit GotoInstruction(Block* destination) : destination(destination) {} 562 563 Block* destination; 564 }; 565 566 struct GotoExternalInstruction : InstructionBase { TORQUE_INSTRUCTION_BOILERPLATEGotoExternalInstruction567 TORQUE_INSTRUCTION_BOILERPLATE() 568 bool IsBlockTerminator() const override { return true; } 569 GotoExternalInstructionGotoExternalInstruction570 GotoExternalInstruction(std::string destination, 571 std::vector<std::string> variable_names) 572 : destination(std::move(destination)), 573 variable_names(std::move(variable_names)) {} 574 575 std::string destination; 576 std::vector<std::string> variable_names; 577 }; 578 579 struct ReturnInstruction : InstructionBase { TORQUE_INSTRUCTION_BOILERPLATEReturnInstruction580 TORQUE_INSTRUCTION_BOILERPLATE() 581 bool IsBlockTerminator() const override { return true; } 582 }; 583 584 struct PrintConstantStringInstruction : InstructionBase { TORQUE_INSTRUCTION_BOILERPLATEPrintConstantStringInstruction585 TORQUE_INSTRUCTION_BOILERPLATE() 586 explicit PrintConstantStringInstruction(std::string message) 587 : message(std::move(message)) {} 588 589 std::string message; 590 }; 591 592 struct AbortInstruction : InstructionBase { 593 TORQUE_INSTRUCTION_BOILERPLATE() 594 enum class Kind { kDebugBreak, kUnreachable, kAssertionFailure }; IsBlockTerminatorAbortInstruction595 bool IsBlockTerminator() const override { return kind != Kind::kDebugBreak; } 596 explicit AbortInstruction(Kind kind, std::string message = "") kindAbortInstruction597 : kind(kind), message(std::move(message)) {} 598 599 Kind kind; 600 std::string message; 601 }; 602 603 struct UnsafeCastInstruction : InstructionBase { TORQUE_INSTRUCTION_BOILERPLATEUnsafeCastInstruction604 TORQUE_INSTRUCTION_BOILERPLATE() 605 explicit UnsafeCastInstruction(const Type* destination_type) 606 : destination_type(destination_type) {} 607 608 DefinitionLocation GetValueDefinition() const; 609 610 const Type* destination_type; 611 }; 612 613 } // namespace torque 614 } // namespace internal 615 } // namespace v8 616 617 #endif // V8_TORQUE_INSTRUCTIONS_H_ 618