blob: a01cab4dab5232390bdb8413d8f451722f360247 [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,
Ben Murdoch097c5b22016-05-18 11:27:45 +010055 SourcePositionTable* source_positions, Frame* frame,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056 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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100152 // Gets the effect level of {node}.
153 int GetEffectLevel(Node* node) const;
154
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400155 int GetVirtualRegister(const Node* node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156 const std::map<NodeId, int> GetVirtualRegistersForTesting() const;
157
158 Isolate* isolate() const { return sequence()->isolate(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400159
160 private:
161 friend class OperandGenerator;
162
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000163 void EmitTableSwitch(const SwitchInfo& sw, InstructionOperand& index_operand);
164 void EmitLookupSwitch(const SwitchInfo& sw,
165 InstructionOperand& value_operand);
166
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400167 // Inform the instruction selection that {node} was just defined.
168 void MarkAsDefined(Node* node);
169
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000170 // Inform the instruction selection that {node} has at least one use and we
171 // will need to generate code for it.
172 void MarkAsUsed(Node* node);
173
Ben Murdoch097c5b22016-05-18 11:27:45 +0100174 // Sets the effect level of {node}.
175 void SetEffectLevel(Node* node, int effect_level);
176
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000177 // Inform the register allocation of the representation of the value produced
178 // by {node}.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179 void MarkAsRepresentation(MachineRepresentation rep, Node* node);
180 void MarkAsWord32(Node* node) {
181 MarkAsRepresentation(MachineRepresentation::kWord32, node);
182 }
183 void MarkAsWord64(Node* node) {
184 MarkAsRepresentation(MachineRepresentation::kWord64, node);
185 }
186 void MarkAsFloat32(Node* node) {
187 MarkAsRepresentation(MachineRepresentation::kFloat32, node);
188 }
189 void MarkAsFloat64(Node* node) {
190 MarkAsRepresentation(MachineRepresentation::kFloat64, node);
191 }
192 void MarkAsReference(Node* node) {
193 MarkAsRepresentation(MachineRepresentation::kTagged, node);
194 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000195
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400196 // Inform the register allocation of the representation of the unallocated
197 // operand {op}.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198 void MarkAsRepresentation(MachineRepresentation rep,
199 const InstructionOperand& op);
200
201 enum CallBufferFlag {
202 kCallCodeImmediate = 1u << 0,
203 kCallAddressImmediate = 1u << 1,
204 kCallTail = 1u << 2
205 };
206 typedef base::Flags<CallBufferFlag> CallBufferFlags;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400207
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000208 // Initialize the call buffer with the InstructionOperands, nodes, etc,
209 // corresponding
210 // to the inputs and outputs of the call.
211 // {call_code_immediate} to generate immediate operands to calls of code.
212 // {call_address_immediate} to generate immediate operands to address calls.
213 void InitializeCallBuffer(Node* call, CallBuffer* buffer,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214 CallBufferFlags flags, int stack_param_delta = 0);
215 bool IsTailCallAddressImmediate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216
217 FrameStateDescriptor* GetFrameStateDescriptor(Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218
219 // ===========================================================================
220 // ============= Architecture-specific graph covering methods. ===============
221 // ===========================================================================
222
223 // Visit nodes in the given block and generate code.
224 void VisitBlock(BasicBlock* block);
225
226 // Visit the node for the control flow at the end of the block, generating
227 // code if necessary.
228 void VisitControl(BasicBlock* block);
229
230 // Visit the node and generate code, if any.
231 void VisitNode(Node* node);
232
233#define DECLARE_GENERATOR(x) void Visit##x(Node* node);
234 MACHINE_OP_LIST(DECLARE_GENERATOR)
235#undef DECLARE_GENERATOR
236
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000237 void VisitFinishRegion(Node* node);
238 void VisitGuard(Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239 void VisitParameter(Node* node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 void VisitIfException(Node* node);
241 void VisitOsrValue(Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242 void VisitPhi(Node* node);
243 void VisitProjection(Node* node);
244 void VisitConstant(Node* node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000245 void VisitCall(Node* call, BasicBlock* handler = nullptr);
246 void VisitTailCall(Node* call);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000247 void VisitGoto(BasicBlock* target);
248 void VisitBranch(Node* input, BasicBlock* tbranch, BasicBlock* fbranch);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000249 void VisitSwitch(Node* node, const SwitchInfo& sw);
250 void VisitDeoptimize(DeoptimizeKind kind, Node* value);
251 void VisitReturn(Node* ret);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000252 void VisitThrow(Node* value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000253
254 void EmitPrepareArguments(ZoneVector<compiler::PushParameter>* arguments,
255 const CallDescriptor* descriptor, Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000256
257 // ===========================================================================
258
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400259 Schedule* schedule() const { return schedule_; }
260 Linkage* linkage() const { return linkage_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000261 InstructionSequence* sequence() const { return sequence_; }
262 Zone* instruction_zone() const { return sequence()->zone(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400263 Zone* zone() const { return zone_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000264
265 // ===========================================================================
266
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400267 Zone* const zone_;
268 Linkage* const linkage_;
269 InstructionSequence* const sequence_;
270 SourcePositionTable* const source_positions_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000271 SourcePositionMode const source_position_mode_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272 Features features_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400273 Schedule* const schedule_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000274 BasicBlock* current_block_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000275 ZoneVector<Instruction*> instructions_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000276 BoolVector defined_;
277 BoolVector used_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100278 IntVector effect_level_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 IntVector virtual_registers_;
280 InstructionScheduler* scheduler_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100281 Frame* frame_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000282};
283
284} // namespace compiler
285} // namespace internal
286} // namespace v8
287
288#endif // V8_COMPILER_INSTRUCTION_SELECTOR_H_