blob: 52aea70eb6f2a4ada099131c11c74251bed937a2 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 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_COMPILER_INSTRUCTION_SELECTOR_H_
6#define V8_COMPILER_INSTRUCTION_SELECTOR_H_
7
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include <map>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009
10#include "src/compiler/common-operator.h"
11#include "src/compiler/instruction.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012#include "src/compiler/instruction-scheduler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013#include "src/compiler/machine-operator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014#include "src/compiler/node.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015#include "src/zone-containers.h"
16
17namespace v8 {
18namespace internal {
19namespace compiler {
20
21// Forward declarations.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022class BasicBlock;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023struct CallBuffer; // TODO(bmeurer): Remove this.
24class FlagsContinuation;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040025class Linkage;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000026class OperandGenerator;
27struct SwitchInfo;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040028
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000029// This struct connects nodes of parameters which are going to be pushed on the
30// call stack with their parameter index in the call descriptor of the callee.
31class PushParameter {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033 PushParameter() : node_(nullptr), type_(MachineType::None()) {}
34 PushParameter(Node* node, MachineType type) : node_(node), type_(type) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -040035
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036 Node* node() const { return node_; }
37 MachineType type() const { return type_; }
38
39 private:
40 Node* node_;
41 MachineType type_;
42};
43
44// Instruction selection generates an InstructionSequence for a given Schedule.
45class InstructionSelector final {
46 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047 // Forward declarations.
48 class Features;
49
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 enum SourcePositionMode { kCallSourcePositions, kAllSourcePositions };
51
52 InstructionSelector(
53 Zone* zone, size_t node_count, Linkage* linkage,
54 InstructionSequence* sequence, Schedule* schedule,
55 SourcePositionTable* source_positions,
56 SourcePositionMode source_position_mode = kCallSourcePositions,
57 Features features = SupportedFeatures());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058
59 // Visit code for the entire graph with the included schedule.
60 void SelectInstructions();
61
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062 void StartBlock(RpoNumber rpo);
63 void EndBlock(RpoNumber rpo);
64 void AddInstruction(Instruction* instr);
65
Ben Murdochb8a8cc12014-11-26 15:28:44 +000066 // ===========================================================================
67 // ============= Architecture-independent code emission methods. =============
68 // ===========================================================================
69
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070 Instruction* Emit(InstructionCode opcode, InstructionOperand output,
71 size_t temp_count = 0, InstructionOperand* temps = nullptr);
72 Instruction* Emit(InstructionCode opcode, InstructionOperand output,
73 InstructionOperand a, size_t temp_count = 0,
74 InstructionOperand* temps = nullptr);
75 Instruction* Emit(InstructionCode opcode, InstructionOperand output,
76 InstructionOperand a, InstructionOperand b,
77 size_t temp_count = 0, InstructionOperand* temps = nullptr);
78 Instruction* Emit(InstructionCode opcode, InstructionOperand output,
79 InstructionOperand a, InstructionOperand b,
80 InstructionOperand c, size_t temp_count = 0,
81 InstructionOperand* temps = nullptr);
82 Instruction* Emit(InstructionCode opcode, InstructionOperand output,
83 InstructionOperand a, InstructionOperand b,
84 InstructionOperand c, InstructionOperand d,
85 size_t temp_count = 0, InstructionOperand* temps = nullptr);
86 Instruction* Emit(InstructionCode opcode, InstructionOperand output,
87 InstructionOperand a, InstructionOperand b,
88 InstructionOperand c, InstructionOperand d,
89 InstructionOperand e, size_t temp_count = 0,
90 InstructionOperand* temps = nullptr);
91 Instruction* Emit(InstructionCode opcode, InstructionOperand output,
92 InstructionOperand a, InstructionOperand b,
93 InstructionOperand c, InstructionOperand d,
94 InstructionOperand e, InstructionOperand f,
95 size_t temp_count = 0, InstructionOperand* temps = nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000096 Instruction* Emit(InstructionCode opcode, size_t output_count,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000097 InstructionOperand* outputs, size_t input_count,
98 InstructionOperand* inputs, size_t temp_count = 0,
99 InstructionOperand* temps = nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100 Instruction* Emit(Instruction* instr);
101
102 // ===========================================================================
103 // ============== Architecture-independent CPU feature methods. ==============
104 // ===========================================================================
105
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000106 class Features final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107 public:
108 Features() : bits_(0) {}
109 explicit Features(unsigned bits) : bits_(bits) {}
110 explicit Features(CpuFeature f) : bits_(1u << f) {}
111 Features(CpuFeature f1, CpuFeature f2) : bits_((1u << f1) | (1u << f2)) {}
112
113 bool Contains(CpuFeature f) const { return (bits_ & (1u << f)); }
114
115 private:
116 unsigned bits_;
117 };
118
119 bool IsSupported(CpuFeature feature) const {
120 return features_.Contains(feature);
121 }
122
123 // Returns the features supported on the target platform.
124 static Features SupportedFeatures() {
125 return Features(CpuFeatures::SupportedFeatures());
126 }
127
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400128 // TODO(sigurds) This should take a CpuFeatures argument.
129 static MachineOperatorBuilder::Flags SupportedMachineOperatorFlags();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000130
131 // ===========================================================================
132 // ============ Architecture-independent graph covering methods. =============
133 // ===========================================================================
134
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000135 // Used in pattern matching during code generation.
136 // Check if {node} can be covered while generating code for the current
137 // instruction. A node can be covered if the {user} of the node has the only
138 // edge and the two are in the same basic block.
139 bool CanCover(Node* user, Node* node) const;
140
141 // Checks if {node} was already defined, and therefore code was already
142 // generated for it.
143 bool IsDefined(Node* node) const;
144
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000145 // Checks if {node} has any uses, and therefore code has to be generated for
146 // it.
147 bool IsUsed(Node* node) const;
148
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400149 // Checks if {node} is currently live.
150 bool IsLive(Node* node) const { return !IsDefined(node) && IsUsed(node); }
151
152 int GetVirtualRegister(const Node* node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000153 const std::map<NodeId, int> GetVirtualRegistersForTesting() const;
154
155 Isolate* isolate() const { return sequence()->isolate(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400156
157 private:
158 friend class OperandGenerator;
159
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000160 void EmitTableSwitch(const SwitchInfo& sw, InstructionOperand& index_operand);
161 void EmitLookupSwitch(const SwitchInfo& sw,
162 InstructionOperand& value_operand);
163
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400164 // Inform the instruction selection that {node} was just defined.
165 void MarkAsDefined(Node* node);
166
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000167 // Inform the instruction selection that {node} has at least one use and we
168 // will need to generate code for it.
169 void MarkAsUsed(Node* node);
170
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000171 // Inform the register allocation of the representation of the value produced
172 // by {node}.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000173 void MarkAsRepresentation(MachineRepresentation rep, Node* node);
174 void MarkAsWord32(Node* node) {
175 MarkAsRepresentation(MachineRepresentation::kWord32, node);
176 }
177 void MarkAsWord64(Node* node) {
178 MarkAsRepresentation(MachineRepresentation::kWord64, node);
179 }
180 void MarkAsFloat32(Node* node) {
181 MarkAsRepresentation(MachineRepresentation::kFloat32, node);
182 }
183 void MarkAsFloat64(Node* node) {
184 MarkAsRepresentation(MachineRepresentation::kFloat64, node);
185 }
186 void MarkAsReference(Node* node) {
187 MarkAsRepresentation(MachineRepresentation::kTagged, node);
188 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400190 // Inform the register allocation of the representation of the unallocated
191 // operand {op}.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000192 void MarkAsRepresentation(MachineRepresentation rep,
193 const InstructionOperand& op);
194
195 enum CallBufferFlag {
196 kCallCodeImmediate = 1u << 0,
197 kCallAddressImmediate = 1u << 1,
198 kCallTail = 1u << 2
199 };
200 typedef base::Flags<CallBufferFlag> CallBufferFlags;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400201
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202 // Initialize the call buffer with the InstructionOperands, nodes, etc,
203 // corresponding
204 // to the inputs and outputs of the call.
205 // {call_code_immediate} to generate immediate operands to calls of code.
206 // {call_address_immediate} to generate immediate operands to address calls.
207 void InitializeCallBuffer(Node* call, CallBuffer* buffer,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208 CallBufferFlags flags, int stack_param_delta = 0);
209 bool IsTailCallAddressImmediate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210
211 FrameStateDescriptor* GetFrameStateDescriptor(Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212
213 // ===========================================================================
214 // ============= Architecture-specific graph covering methods. ===============
215 // ===========================================================================
216
217 // Visit nodes in the given block and generate code.
218 void VisitBlock(BasicBlock* block);
219
220 // Visit the node for the control flow at the end of the block, generating
221 // code if necessary.
222 void VisitControl(BasicBlock* block);
223
224 // Visit the node and generate code, if any.
225 void VisitNode(Node* node);
226
227#define DECLARE_GENERATOR(x) void Visit##x(Node* node);
228 MACHINE_OP_LIST(DECLARE_GENERATOR)
229#undef DECLARE_GENERATOR
230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 void VisitFinishRegion(Node* node);
232 void VisitGuard(Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233 void VisitParameter(Node* node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 void VisitIfException(Node* node);
235 void VisitOsrValue(Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236 void VisitPhi(Node* node);
237 void VisitProjection(Node* node);
238 void VisitConstant(Node* node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000239 void VisitCall(Node* call, BasicBlock* handler = nullptr);
240 void VisitTailCall(Node* call);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241 void VisitGoto(BasicBlock* target);
242 void VisitBranch(Node* input, BasicBlock* tbranch, BasicBlock* fbranch);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000243 void VisitSwitch(Node* node, const SwitchInfo& sw);
244 void VisitDeoptimize(DeoptimizeKind kind, Node* value);
245 void VisitReturn(Node* ret);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000246 void VisitThrow(Node* value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000247
248 void EmitPrepareArguments(ZoneVector<compiler::PushParameter>* arguments,
249 const CallDescriptor* descriptor, Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000250
251 // ===========================================================================
252
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400253 Schedule* schedule() const { return schedule_; }
254 Linkage* linkage() const { return linkage_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255 InstructionSequence* sequence() const { return sequence_; }
256 Zone* instruction_zone() const { return sequence()->zone(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400257 Zone* zone() const { return zone_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000258
259 // ===========================================================================
260
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400261 Zone* const zone_;
262 Linkage* const linkage_;
263 InstructionSequence* const sequence_;
264 SourcePositionTable* const source_positions_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000265 SourcePositionMode const source_position_mode_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000266 Features features_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400267 Schedule* const schedule_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000268 BasicBlock* current_block_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000269 ZoneVector<Instruction*> instructions_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000270 BoolVector defined_;
271 BoolVector used_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272 IntVector virtual_registers_;
273 InstructionScheduler* scheduler_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000274};
275
276} // namespace compiler
277} // namespace internal
278} // namespace v8
279
280#endif // V8_COMPILER_INSTRUCTION_SELECTOR_H_