// Copyright 2014 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_COMPILER_INSTRUCTION_SELECTOR_H_ #define V8_COMPILER_INSTRUCTION_SELECTOR_H_ #include <deque> #include "src/compiler/common-operator.h" #include "src/compiler/instruction.h" #include "src/compiler/machine-operator.h" #include "src/zone-containers.h" namespace v8 { namespace internal { namespace compiler { // Forward declarations. struct CallBuffer; // TODO(bmeurer): Remove this. class FlagsContinuation; class InstructionSelector FINAL { public: // Forward declarations. class Features; InstructionSelector(InstructionSequence* sequence, SourcePositionTable* source_positions, Features features = SupportedFeatures()); // Visit code for the entire graph with the included schedule. void SelectInstructions(); // =========================================================================== // ============= Architecture-independent code emission methods. ============= // =========================================================================== Instruction* Emit(InstructionCode opcode, InstructionOperand* output, size_t temp_count = 0, InstructionOperand* *temps = NULL); Instruction* Emit(InstructionCode opcode, InstructionOperand* output, InstructionOperand* a, size_t temp_count = 0, InstructionOperand* *temps = NULL); Instruction* Emit(InstructionCode opcode, InstructionOperand* output, InstructionOperand* a, InstructionOperand* b, size_t temp_count = 0, InstructionOperand* *temps = NULL); Instruction* Emit(InstructionCode opcode, InstructionOperand* output, InstructionOperand* a, InstructionOperand* b, InstructionOperand* c, size_t temp_count = 0, InstructionOperand* *temps = NULL); Instruction* Emit(InstructionCode opcode, InstructionOperand* output, InstructionOperand* a, InstructionOperand* b, InstructionOperand* c, InstructionOperand* d, size_t temp_count = 0, InstructionOperand* *temps = NULL); Instruction* Emit(InstructionCode opcode, size_t output_count, InstructionOperand** outputs, size_t input_count, InstructionOperand** inputs, size_t temp_count = 0, InstructionOperand* *temps = NULL); Instruction* Emit(Instruction* instr); // =========================================================================== // ============== Architecture-independent CPU feature methods. ============== // =========================================================================== class Features FINAL { public: Features() : bits_(0) {} explicit Features(unsigned bits) : bits_(bits) {} explicit Features(CpuFeature f) : bits_(1u << f) {} Features(CpuFeature f1, CpuFeature f2) : bits_((1u << f1) | (1u << f2)) {} bool Contains(CpuFeature f) const { return (bits_ & (1u << f)); } private: unsigned bits_; }; bool IsSupported(CpuFeature feature) const { return features_.Contains(feature); } // Returns the features supported on the target platform. static Features SupportedFeatures() { return Features(CpuFeatures::SupportedFeatures()); } private: friend class OperandGenerator; // =========================================================================== // ============ Architecture-independent graph covering methods. ============= // =========================================================================== // Checks if {block} will appear directly after {current_block_} when // assembling code, in which case, a fall-through can be used. bool IsNextInAssemblyOrder(const BasicBlock* block) const; // Used in pattern matching during code generation. // Check if {node} can be covered while generating code for the current // instruction. A node can be covered if the {user} of the node has the only // edge and the two are in the same basic block. bool CanCover(Node* user, Node* node) const; // Checks if {node} was already defined, and therefore code was already // generated for it. bool IsDefined(Node* node) const; // Inform the instruction selection that {node} was just defined. void MarkAsDefined(Node* node); // Checks if {node} has any uses, and therefore code has to be generated for // it. bool IsUsed(Node* node) const; // Inform the instruction selection that {node} has at least one use and we // will need to generate code for it. void MarkAsUsed(Node* node); // Checks if {node} is marked as double. bool IsDouble(const Node* node) const; // Inform the register allocator of a double result. void MarkAsDouble(Node* node); // Checks if {node} is marked as reference. bool IsReference(const Node* node) const; // Inform the register allocator of a reference result. void MarkAsReference(Node* node); // Inform the register allocation of the representation of the value produced // by {node}. void MarkAsRepresentation(MachineType rep, Node* node); // Initialize the call buffer with the InstructionOperands, nodes, etc, // corresponding // to the inputs and outputs of the call. // {call_code_immediate} to generate immediate operands to calls of code. // {call_address_immediate} to generate immediate operands to address calls. void InitializeCallBuffer(Node* call, CallBuffer* buffer, bool call_code_immediate, bool call_address_immediate); FrameStateDescriptor* GetFrameStateDescriptor(Node* node); void AddFrameStateInputs(Node* state, InstructionOperandVector* inputs, FrameStateDescriptor* descriptor); // =========================================================================== // ============= Architecture-specific graph covering methods. =============== // =========================================================================== // Visit nodes in the given block and generate code. void VisitBlock(BasicBlock* block); // Visit the node for the control flow at the end of the block, generating // code if necessary. void VisitControl(BasicBlock* block); // Visit the node and generate code, if any. void VisitNode(Node* node); #define DECLARE_GENERATOR(x) void Visit##x(Node* node); MACHINE_OP_LIST(DECLARE_GENERATOR) #undef DECLARE_GENERATOR void VisitInt32AddWithOverflow(Node* node, FlagsContinuation* cont); void VisitInt32SubWithOverflow(Node* node, FlagsContinuation* cont); void VisitWord32Test(Node* node, FlagsContinuation* cont); void VisitWord64Test(Node* node, FlagsContinuation* cont); void VisitWord32Compare(Node* node, FlagsContinuation* cont); void VisitWord64Compare(Node* node, FlagsContinuation* cont); void VisitFloat64Compare(Node* node, FlagsContinuation* cont); void VisitFinish(Node* node); void VisitParameter(Node* node); void VisitPhi(Node* node); void VisitProjection(Node* node); void VisitConstant(Node* node); void VisitCall(Node* call, BasicBlock* continuation, BasicBlock* deoptimization); void VisitGoto(BasicBlock* target); void VisitBranch(Node* input, BasicBlock* tbranch, BasicBlock* fbranch); void VisitReturn(Node* value); void VisitThrow(Node* value); void VisitDeoptimize(Node* deopt); // =========================================================================== Graph* graph() const { return sequence()->graph(); } Linkage* linkage() const { return sequence()->linkage(); } Schedule* schedule() const { return sequence()->schedule(); } InstructionSequence* sequence() const { return sequence_; } Zone* instruction_zone() const { return sequence()->zone(); } Zone* zone() { return &zone_; } // =========================================================================== Zone zone_; InstructionSequence* sequence_; SourcePositionTable* source_positions_; Features features_; BasicBlock* current_block_; ZoneDeque<Instruction*> instructions_; BoolVector defined_; BoolVector used_; }; } // namespace compiler } // namespace internal } // namespace v8 #endif // V8_COMPILER_INSTRUCTION_SELECTOR_H_