1 // Copyright 2020 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_TORQUE_CODE_GENERATOR_H_ 6 #define V8_TORQUE_TORQUE_CODE_GENERATOR_H_ 7 8 #include <iostream> 9 10 #include "src/torque/cfg.h" 11 #include "src/torque/declarable.h" 12 13 namespace v8 { 14 namespace internal { 15 namespace torque { 16 17 class TorqueCodeGenerator { 18 public: TorqueCodeGenerator(const ControlFlowGraph & cfg,std::ostream & out)19 TorqueCodeGenerator(const ControlFlowGraph& cfg, std::ostream& out) 20 : cfg_(cfg), 21 out_(&out), 22 out_decls_(&out), 23 previous_position_(SourcePosition::Invalid()) {} 24 25 protected: 26 const ControlFlowGraph& cfg_; 27 std::ostream* out_; 28 std::ostream* out_decls_; 29 size_t fresh_id_ = 0; 30 SourcePosition previous_position_; 31 std::map<DefinitionLocation, std::string> location_map_; 32 DefinitionToVariable(const DefinitionLocation & location)33 std::string DefinitionToVariable(const DefinitionLocation& location) { 34 if (location.IsPhi()) { 35 std::stringstream stream; 36 stream << "phi_bb" << location.GetPhiBlock()->id() << "_" 37 << location.GetPhiIndex(); 38 return stream.str(); 39 } else if (location.IsParameter()) { 40 auto it = location_map_.find(location); 41 DCHECK_NE(it, location_map_.end()); 42 return it->second; 43 } else { 44 DCHECK(location.IsInstruction()); 45 auto it = location_map_.find(location); 46 if (it == location_map_.end()) { 47 it = location_map_.insert(std::make_pair(location, FreshNodeName())) 48 .first; 49 } 50 return it->second; 51 } 52 } 53 SetDefinitionVariable(const DefinitionLocation & definition,const std::string & str)54 void SetDefinitionVariable(const DefinitionLocation& definition, 55 const std::string& str) { 56 DCHECK_EQ(location_map_.find(definition), location_map_.end()); 57 location_map_.insert(std::make_pair(definition, str)); 58 } 59 out()60 std::ostream& out() { return *out_; } decls()61 std::ostream& decls() { return *out_decls_; } 62 63 static bool IsEmptyInstruction(const Instruction& instruction); 64 virtual void EmitSourcePosition(SourcePosition pos, 65 bool always_emit = false) = 0; 66 FreshNodeName()67 std::string FreshNodeName() { return "tmp" + std::to_string(fresh_id_++); } FreshCatchName()68 std::string FreshCatchName() { return "catch" + std::to_string(fresh_id_++); } FreshLabelName()69 std::string FreshLabelName() { return "label" + std::to_string(fresh_id_++); } BlockName(const Block * block)70 std::string BlockName(const Block* block) { 71 return "block" + std::to_string(block->id()); 72 } 73 74 void EmitInstruction(const Instruction& instruction, 75 Stack<std::string>* stack); 76 77 template <typename T> EmitIRAnnotation(const T & instruction,Stack<std::string> * stack)78 void EmitIRAnnotation(const T& instruction, Stack<std::string>* stack) { 79 out() << " // " << instruction 80 << ", starting stack size: " << stack->Size() << "\n"; 81 } 82 83 #define EMIT_INSTRUCTION_DECLARATION(T) \ 84 void EmitInstruction(const T& instruction, Stack<std::string>* stack); 85 TORQUE_BACKEND_AGNOSTIC_INSTRUCTION_LIST(EMIT_INSTRUCTION_DECLARATION) 86 #undef EMIT_INSTRUCTION_DECLARATION 87 88 #define EMIT_INSTRUCTION_DECLARATION(T) \ 89 virtual void EmitInstruction(const T& instruction, \ 90 Stack<std::string>* stack) = 0; 91 TORQUE_BACKEND_DEPENDENT_INSTRUCTION_LIST(EMIT_INSTRUCTION_DECLARATION) 92 #undef EMIT_INSTRUCTION_DECLARATION 93 }; 94 95 } // namespace torque 96 } // namespace internal 97 } // namespace v8 98 99 #endif // V8_TORQUE_TORQUE_CODE_GENERATOR_H_ 100