blob: 851ba24cbb83332e057a55dbe89615bf0e4a7879 [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_H_
6#define V8_COMPILER_INSTRUCTION_H_
7
8#include <deque>
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009#include <iosfwd>
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include <map>
11#include <set>
12
13#include "src/compiler/common-operator.h"
14#include "src/compiler/frame.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015#include "src/compiler/instruction-codes.h"
16#include "src/compiler/opcodes.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017#include "src/compiler/source-position.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018#include "src/macro-assembler.h"
19#include "src/register-configuration.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020#include "src/zone-allocator.h"
21
22namespace v8 {
23namespace internal {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024namespace compiler {
25
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000026// Forward declarations.
27class Schedule;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030class InstructionOperand {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 static const int kInvalidVirtualRegister = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000034 // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with
35 // kInvalidVirtualRegister and some DCHECKS.
36 enum Kind { INVALID, UNALLOCATED, CONSTANT, IMMEDIATE, EXPLICIT, ALLOCATED };
37
38 InstructionOperand() : InstructionOperand(INVALID) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000039
40 Kind kind() const { return KindField::decode(value_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041
42#define INSTRUCTION_OPERAND_PREDICATE(name, type) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000043 bool Is##name() const { return kind() == type; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID)
45 // UnallocatedOperands are place-holder operands created before register
46 // allocation. They later are assigned registers and become AllocatedOperands.
47 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED)
48 // Constant operands participate in register allocation. They are allocated to
49 // registers but have a special "spilling" behavior. When a ConstantOperand
50 // value must be rematerialized, it is loaded from an immediate constant
51 // rather from an unspilled slot.
52 INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT)
53 // ImmediateOperands do not participate in register allocation and are only
54 // embedded directly in instructions, e.g. small integers and on some
55 // platforms Objects.
56 INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE)
57 // ExplicitOperands do not participate in register allocation. They are
58 // created by the instruction selector for direct access to registers and
59 // stack slots, completely bypassing the register allocator. They are never
60 // associated with a virtual register
61 INSTRUCTION_OPERAND_PREDICATE(Explicit, EXPLICIT)
62 // AllocatedOperands are registers or stack slots that are assigned by the
63 // register allocator and are always associated with a virtual register.
64 INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065#undef INSTRUCTION_OPERAND_PREDICATE
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066
67 inline bool IsAnyRegister() const;
68 inline bool IsRegister() const;
Ben Murdochc5610432016-08-08 18:44:38 +010069 inline bool IsFPRegister() const;
70 inline bool IsFloatRegister() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071 inline bool IsDoubleRegister() const;
Ben Murdoch097c5b22016-05-18 11:27:45 +010072 inline bool IsSimd128Register() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073 inline bool IsStackSlot() const;
Ben Murdochc5610432016-08-08 18:44:38 +010074 inline bool IsFPStackSlot() const;
75 inline bool IsFloatStackSlot() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076 inline bool IsDoubleStackSlot() const;
Ben Murdoch097c5b22016-05-18 11:27:45 +010077 inline bool IsSimd128StackSlot() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078
79 template <typename SubKindOperand>
80 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) {
81 void* buffer = zone->New(sizeof(op));
82 return new (buffer) SubKindOperand(op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083 }
84
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000085 static void ReplaceWith(InstructionOperand* dest,
86 const InstructionOperand* src) {
87 *dest = *src;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000088 }
89
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090 bool Equals(const InstructionOperand& that) const {
91 return this->value_ == that.value_;
92 }
93
94 bool Compare(const InstructionOperand& that) const {
95 return this->value_ < that.value_;
96 }
97
98 bool EqualsCanonicalized(const InstructionOperand& that) const {
99 return this->GetCanonicalizedValue() == that.GetCanonicalizedValue();
100 }
101
102 bool CompareCanonicalized(const InstructionOperand& that) const {
103 return this->GetCanonicalizedValue() < that.GetCanonicalizedValue();
104 }
105
106 void Print(const RegisterConfiguration* config) const;
107 void Print() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000108
109 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000110 explicit InstructionOperand(Kind kind) : value_(KindField::encode(kind)) {}
111
112 inline uint64_t GetCanonicalizedValue() const;
113
114 class KindField : public BitField64<Kind, 0, 3> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400116 uint64_t value_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000117};
118
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000119
120typedef ZoneVector<InstructionOperand> InstructionOperandVector;
121
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000122
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400123struct PrintableInstructionOperand {
124 const RegisterConfiguration* register_configuration_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 InstructionOperand op_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400126};
127
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000128
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400129std::ostream& operator<<(std::ostream& os,
130 const PrintableInstructionOperand& op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000131
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132
133#define INSTRUCTION_OPERAND_CASTS(OperandType, OperandKind) \
134 \
135 static OperandType* cast(InstructionOperand* op) { \
136 DCHECK_EQ(OperandKind, op->kind()); \
137 return static_cast<OperandType*>(op); \
138 } \
139 \
140 static const OperandType* cast(const InstructionOperand* op) { \
141 DCHECK_EQ(OperandKind, op->kind()); \
142 return static_cast<const OperandType*>(op); \
143 } \
144 \
145 static OperandType cast(const InstructionOperand& op) { \
146 DCHECK_EQ(OperandKind, op.kind()); \
147 return *static_cast<const OperandType*>(&op); \
148 }
149
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150class UnallocatedOperand : public InstructionOperand {
151 public:
152 enum BasicPolicy { FIXED_SLOT, EXTENDED_POLICY };
153
154 enum ExtendedPolicy {
155 NONE,
156 ANY,
157 FIXED_REGISTER,
158 FIXED_DOUBLE_REGISTER,
159 MUST_HAVE_REGISTER,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000160 MUST_HAVE_SLOT,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000161 SAME_AS_FIRST_INPUT
162 };
163
164 // Lifetime of operand inside the instruction.
165 enum Lifetime {
166 // USED_AT_START operand is guaranteed to be live only at
167 // instruction start. Register allocator is free to assign the same register
168 // to some other operand used inside instruction (i.e. temporary or
169 // output).
170 USED_AT_START,
171
172 // USED_AT_END operand is treated as live until the end of
173 // instruction. This means that register allocator will not reuse it's
174 // register for any other operand inside instruction.
175 USED_AT_END
176 };
177
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000178 UnallocatedOperand(ExtendedPolicy policy, int virtual_register)
179 : UnallocatedOperand(virtual_register) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000180 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
181 value_ |= ExtendedPolicyField::encode(policy);
182 value_ |= LifetimeField::encode(USED_AT_END);
183 }
184
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000185 UnallocatedOperand(BasicPolicy policy, int index, int virtual_register)
186 : UnallocatedOperand(virtual_register) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000187 DCHECK(policy == FIXED_SLOT);
188 value_ |= BasicPolicyField::encode(policy);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400189 value_ |= static_cast<int64_t>(index) << FixedSlotIndexField::kShift;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190 DCHECK(this->fixed_slot_index() == index);
191 }
192
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 UnallocatedOperand(ExtendedPolicy policy, int index, int virtual_register)
194 : UnallocatedOperand(virtual_register) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000195 DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER);
196 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
197 value_ |= ExtendedPolicyField::encode(policy);
198 value_ |= LifetimeField::encode(USED_AT_END);
199 value_ |= FixedRegisterField::encode(index);
200 }
201
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000202 UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime,
203 int virtual_register)
204 : UnallocatedOperand(virtual_register) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
206 value_ |= ExtendedPolicyField::encode(policy);
207 value_ |= LifetimeField::encode(lifetime);
208 }
209
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210 UnallocatedOperand(int reg_id, int slot_id, int virtual_register)
211 : UnallocatedOperand(FIXED_REGISTER, reg_id, virtual_register) {
212 value_ |= HasSecondaryStorageField::encode(true);
213 value_ |= SecondaryStorageField::encode(slot_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214 }
215
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216 // Predicates for the operand policy.
217 bool HasAnyPolicy() const {
218 return basic_policy() == EXTENDED_POLICY && extended_policy() == ANY;
219 }
220 bool HasFixedPolicy() const {
221 return basic_policy() == FIXED_SLOT ||
222 extended_policy() == FIXED_REGISTER ||
223 extended_policy() == FIXED_DOUBLE_REGISTER;
224 }
225 bool HasRegisterPolicy() const {
226 return basic_policy() == EXTENDED_POLICY &&
227 extended_policy() == MUST_HAVE_REGISTER;
228 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000229 bool HasSlotPolicy() const {
230 return basic_policy() == EXTENDED_POLICY &&
231 extended_policy() == MUST_HAVE_SLOT;
232 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233 bool HasSameAsInputPolicy() const {
234 return basic_policy() == EXTENDED_POLICY &&
235 extended_policy() == SAME_AS_FIRST_INPUT;
236 }
237 bool HasFixedSlotPolicy() const { return basic_policy() == FIXED_SLOT; }
238 bool HasFixedRegisterPolicy() const {
239 return basic_policy() == EXTENDED_POLICY &&
240 extended_policy() == FIXED_REGISTER;
241 }
242 bool HasFixedDoubleRegisterPolicy() const {
243 return basic_policy() == EXTENDED_POLICY &&
244 extended_policy() == FIXED_DOUBLE_REGISTER;
245 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000246 bool HasSecondaryStorage() const {
247 return basic_policy() == EXTENDED_POLICY &&
248 extended_policy() == FIXED_REGISTER &&
249 HasSecondaryStorageField::decode(value_);
250 }
251 int GetSecondaryStorage() const {
252 DCHECK(HasSecondaryStorage());
253 return SecondaryStorageField::decode(value_);
254 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255
256 // [basic_policy]: Distinguish between FIXED_SLOT and all other policies.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000257 BasicPolicy basic_policy() const {
258 DCHECK_EQ(UNALLOCATED, kind());
259 return BasicPolicyField::decode(value_);
260 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000261
262 // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy.
263 ExtendedPolicy extended_policy() const {
264 DCHECK(basic_policy() == EXTENDED_POLICY);
265 return ExtendedPolicyField::decode(value_);
266 }
267
268 // [fixed_slot_index]: Only for FIXED_SLOT.
269 int fixed_slot_index() const {
270 DCHECK(HasFixedSlotPolicy());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000271 return static_cast<int>(static_cast<int64_t>(value_) >>
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400272 FixedSlotIndexField::kShift);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273 }
274
275 // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER.
276 int fixed_register_index() const {
277 DCHECK(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy());
278 return FixedRegisterField::decode(value_);
279 }
280
281 // [virtual_register]: The virtual register ID for this operand.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000282 int32_t virtual_register() const {
283 DCHECK_EQ(UNALLOCATED, kind());
284 return static_cast<int32_t>(VirtualRegisterField::decode(value_));
285 }
286
287 // TODO(dcarney): remove this.
288 void set_virtual_register(int32_t id) {
289 DCHECK_EQ(UNALLOCATED, kind());
290 value_ = VirtualRegisterField::update(value_, static_cast<uint32_t>(id));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000291 }
292
293 // [lifetime]: Only for non-FIXED_SLOT.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400294 bool IsUsedAtStart() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000295 DCHECK(basic_policy() == EXTENDED_POLICY);
296 return LifetimeField::decode(value_) == USED_AT_START;
297 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000298
299 INSTRUCTION_OPERAND_CASTS(UnallocatedOperand, UNALLOCATED);
300
301 // The encoding used for UnallocatedOperand operands depends on the policy
302 // that is
303 // stored within the operand. The FIXED_SLOT policy uses a compact encoding
304 // because it accommodates a larger pay-load.
305 //
306 // For FIXED_SLOT policy:
307 // +------------------------------------------------+
308 // | slot_index | 0 | virtual_register | 001 |
309 // +------------------------------------------------+
310 //
311 // For all other (extended) policies:
312 // +-----------------------------------------------------+
313 // | reg_index | L | PPP | 1 | virtual_register | 001 |
314 // +-----------------------------------------------------+
315 // L ... Lifetime
316 // P ... Policy
317 //
318 // The slot index is a signed value which requires us to decode it manually
319 // instead of using the BitField utility class.
320
321 STATIC_ASSERT(KindField::kSize == 3);
322
323 class VirtualRegisterField : public BitField64<uint32_t, 3, 32> {};
324
325 // BitFields for all unallocated operands.
326 class BasicPolicyField : public BitField64<BasicPolicy, 35, 1> {};
327
328 // BitFields specific to BasicPolicy::FIXED_SLOT.
329 class FixedSlotIndexField : public BitField64<int, 36, 28> {};
330
331 // BitFields specific to BasicPolicy::EXTENDED_POLICY.
332 class ExtendedPolicyField : public BitField64<ExtendedPolicy, 36, 3> {};
333 class LifetimeField : public BitField64<Lifetime, 39, 1> {};
334 class HasSecondaryStorageField : public BitField64<bool, 40, 1> {};
335 class FixedRegisterField : public BitField64<int, 41, 6> {};
336 class SecondaryStorageField : public BitField64<int, 47, 3> {};
337
338 private:
339 explicit UnallocatedOperand(int virtual_register)
340 : InstructionOperand(UNALLOCATED) {
341 value_ |=
342 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
343 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000344};
345
346
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000347class ConstantOperand : public InstructionOperand {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000349 explicit ConstantOperand(int virtual_register)
350 : InstructionOperand(CONSTANT) {
351 value_ |=
352 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
353 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000354
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000355 int32_t virtual_register() const {
356 return static_cast<int32_t>(VirtualRegisterField::decode(value_));
357 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000358
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359 static ConstantOperand* New(Zone* zone, int virtual_register) {
360 return InstructionOperand::New(zone, ConstantOperand(virtual_register));
361 }
362
363 INSTRUCTION_OPERAND_CASTS(ConstantOperand, CONSTANT);
364
365 STATIC_ASSERT(KindField::kSize == 3);
366 class VirtualRegisterField : public BitField64<uint32_t, 3, 32> {};
367};
368
369
370class ImmediateOperand : public InstructionOperand {
371 public:
372 enum ImmediateType { INLINE, INDEXED };
373
374 explicit ImmediateOperand(ImmediateType type, int32_t value)
375 : InstructionOperand(IMMEDIATE) {
376 value_ |= TypeField::encode(type);
377 value_ |= static_cast<int64_t>(value) << ValueField::kShift;
378 }
379
380 ImmediateType type() const { return TypeField::decode(value_); }
381
382 int32_t inline_value() const {
383 DCHECK_EQ(INLINE, type());
384 return static_cast<int64_t>(value_) >> ValueField::kShift;
385 }
386
387 int32_t indexed_value() const {
388 DCHECK_EQ(INDEXED, type());
389 return static_cast<int64_t>(value_) >> ValueField::kShift;
390 }
391
392 static ImmediateOperand* New(Zone* zone, ImmediateType type, int32_t value) {
393 return InstructionOperand::New(zone, ImmediateOperand(type, value));
394 }
395
396 INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE);
397
398 STATIC_ASSERT(KindField::kSize == 3);
399 class TypeField : public BitField64<ImmediateType, 3, 1> {};
400 class ValueField : public BitField64<int32_t, 32, 32> {};
401};
402
403
404class LocationOperand : public InstructionOperand {
405 public:
406 enum LocationKind { REGISTER, STACK_SLOT };
407
408 LocationOperand(InstructionOperand::Kind operand_kind,
409 LocationOperand::LocationKind location_kind,
410 MachineRepresentation rep, int index)
411 : InstructionOperand(operand_kind) {
412 DCHECK_IMPLIES(location_kind == REGISTER, index >= 0);
413 DCHECK(IsSupportedRepresentation(rep));
414 value_ |= LocationKindField::encode(location_kind);
415 value_ |= RepresentationField::encode(rep);
416 value_ |= static_cast<int64_t>(index) << IndexField::kShift;
417 }
418
419 int index() const {
Ben Murdochc5610432016-08-08 18:44:38 +0100420 DCHECK(IsStackSlot() || IsFPStackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000421 return static_cast<int64_t>(value_) >> IndexField::kShift;
422 }
423
424 Register GetRegister() const {
425 DCHECK(IsRegister());
426 return Register::from_code(static_cast<int64_t>(value_) >>
427 IndexField::kShift);
428 }
429
Ben Murdochc5610432016-08-08 18:44:38 +0100430 FloatRegister GetFloatRegister() const {
431 DCHECK(IsFloatRegister());
432 return FloatRegister::from_code(static_cast<int64_t>(value_) >>
433 IndexField::kShift);
434 }
435
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000436 DoubleRegister GetDoubleRegister() const {
Ben Murdochc5610432016-08-08 18:44:38 +0100437 // TODO(bbudge) Tighten this test to IsDoubleRegister when all code
438 // generators are changed to use the correct Get*Register method.
439 DCHECK(IsFPRegister());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000440 return DoubleRegister::from_code(static_cast<int64_t>(value_) >>
441 IndexField::kShift);
442 }
443
Ben Murdoch097c5b22016-05-18 11:27:45 +0100444 Simd128Register GetSimd128Register() const {
445 DCHECK(IsSimd128Register());
446 return Simd128Register::from_code(static_cast<int64_t>(value_) >>
447 IndexField::kShift);
448 }
449
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000450 LocationKind location_kind() const {
451 return LocationKindField::decode(value_);
452 }
453
454 MachineRepresentation representation() const {
455 return RepresentationField::decode(value_);
456 }
457
458 static bool IsSupportedRepresentation(MachineRepresentation rep) {
459 switch (rep) {
460 case MachineRepresentation::kWord32:
461 case MachineRepresentation::kWord64:
462 case MachineRepresentation::kFloat32:
463 case MachineRepresentation::kFloat64:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100464 case MachineRepresentation::kSimd128:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000465 case MachineRepresentation::kTagged:
466 return true;
467 case MachineRepresentation::kBit:
468 case MachineRepresentation::kWord8:
469 case MachineRepresentation::kWord16:
470 case MachineRepresentation::kNone:
471 return false;
472 }
473 UNREACHABLE();
474 return false;
475 }
476
477 static LocationOperand* cast(InstructionOperand* op) {
478 DCHECK(ALLOCATED == op->kind() || EXPLICIT == op->kind());
479 return static_cast<LocationOperand*>(op);
480 }
481
482 static const LocationOperand* cast(const InstructionOperand* op) {
483 DCHECK(ALLOCATED == op->kind() || EXPLICIT == op->kind());
484 return static_cast<const LocationOperand*>(op);
485 }
486
487 static LocationOperand cast(const InstructionOperand& op) {
488 DCHECK(ALLOCATED == op.kind() || EXPLICIT == op.kind());
489 return *static_cast<const LocationOperand*>(&op);
490 }
491
492 STATIC_ASSERT(KindField::kSize == 3);
493 class LocationKindField : public BitField64<LocationKind, 3, 2> {};
494 class RepresentationField : public BitField64<MachineRepresentation, 5, 8> {};
495 class IndexField : public BitField64<int32_t, 35, 29> {};
496};
497
498
499class ExplicitOperand : public LocationOperand {
500 public:
501 ExplicitOperand(LocationKind kind, MachineRepresentation rep, int index);
502
503 static ExplicitOperand* New(Zone* zone, LocationKind kind,
504 MachineRepresentation rep, int index) {
505 return InstructionOperand::New(zone, ExplicitOperand(kind, rep, index));
506 }
507
508 INSTRUCTION_OPERAND_CASTS(ExplicitOperand, EXPLICIT);
509};
510
511
512class AllocatedOperand : public LocationOperand {
513 public:
514 AllocatedOperand(LocationKind kind, MachineRepresentation rep, int index)
515 : LocationOperand(ALLOCATED, kind, rep, index) {}
516
517 static AllocatedOperand* New(Zone* zone, LocationKind kind,
518 MachineRepresentation rep, int index) {
519 return InstructionOperand::New(zone, AllocatedOperand(kind, rep, index));
520 }
521
522 INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED);
523};
524
525
526#undef INSTRUCTION_OPERAND_CASTS
527
528
529bool InstructionOperand::IsAnyRegister() const {
530 return (IsAllocated() || IsExplicit()) &&
531 LocationOperand::cast(this)->location_kind() ==
532 LocationOperand::REGISTER;
533}
534
535
536bool InstructionOperand::IsRegister() const {
537 return IsAnyRegister() &&
538 !IsFloatingPoint(LocationOperand::cast(this)->representation());
539}
540
Ben Murdochc5610432016-08-08 18:44:38 +0100541bool InstructionOperand::IsFPRegister() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000542 return IsAnyRegister() &&
543 IsFloatingPoint(LocationOperand::cast(this)->representation());
544}
545
Ben Murdochc5610432016-08-08 18:44:38 +0100546bool InstructionOperand::IsFloatRegister() const {
547 return IsAnyRegister() &&
548 LocationOperand::cast(this)->representation() ==
549 MachineRepresentation::kFloat32;
550}
551
552bool InstructionOperand::IsDoubleRegister() const {
553 return IsAnyRegister() &&
554 LocationOperand::cast(this)->representation() ==
555 MachineRepresentation::kFloat64;
556}
557
Ben Murdoch097c5b22016-05-18 11:27:45 +0100558bool InstructionOperand::IsSimd128Register() const {
559 return IsAnyRegister() &&
560 LocationOperand::cast(this)->representation() ==
561 MachineRepresentation::kSimd128;
562}
563
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000564bool InstructionOperand::IsStackSlot() const {
565 return (IsAllocated() || IsExplicit()) &&
566 LocationOperand::cast(this)->location_kind() ==
567 LocationOperand::STACK_SLOT &&
568 !IsFloatingPoint(LocationOperand::cast(this)->representation());
569}
570
Ben Murdochc5610432016-08-08 18:44:38 +0100571bool InstructionOperand::IsFPStackSlot() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000572 return (IsAllocated() || IsExplicit()) &&
573 LocationOperand::cast(this)->location_kind() ==
574 LocationOperand::STACK_SLOT &&
575 IsFloatingPoint(LocationOperand::cast(this)->representation());
576}
577
Ben Murdochc5610432016-08-08 18:44:38 +0100578bool InstructionOperand::IsFloatStackSlot() const {
579 return (IsAllocated() || IsExplicit()) &&
580 LocationOperand::cast(this)->location_kind() ==
581 LocationOperand::STACK_SLOT &&
582 LocationOperand::cast(this)->representation() ==
583 MachineRepresentation::kFloat32;
584}
585
586bool InstructionOperand::IsDoubleStackSlot() const {
587 return (IsAllocated() || IsExplicit()) &&
588 LocationOperand::cast(this)->location_kind() ==
589 LocationOperand::STACK_SLOT &&
590 LocationOperand::cast(this)->representation() ==
591 MachineRepresentation::kFloat64;
592}
593
Ben Murdoch097c5b22016-05-18 11:27:45 +0100594bool InstructionOperand::IsSimd128StackSlot() const {
595 return (IsAllocated() || IsExplicit()) &&
596 LocationOperand::cast(this)->location_kind() ==
597 LocationOperand::STACK_SLOT &&
598 LocationOperand::cast(this)->representation() ==
599 MachineRepresentation::kSimd128;
600}
601
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602uint64_t InstructionOperand::GetCanonicalizedValue() const {
603 if (IsAllocated() || IsExplicit()) {
604 // TODO(dcarney): put machine type last and mask.
605 MachineRepresentation canonicalized_representation =
606 IsFloatingPoint(LocationOperand::cast(this)->representation())
607 ? MachineRepresentation::kFloat64
608 : MachineRepresentation::kNone;
609 return InstructionOperand::KindField::update(
610 LocationOperand::RepresentationField::update(
611 this->value_, canonicalized_representation),
612 LocationOperand::EXPLICIT);
613 }
614 return this->value_;
615}
616
617
618// Required for maps that don't care about machine type.
619struct CompareOperandModuloType {
620 bool operator()(const InstructionOperand& a,
621 const InstructionOperand& b) const {
622 return a.CompareCanonicalized(b);
623 }
624};
625
626
627class MoveOperands final : public ZoneObject {
628 public:
629 MoveOperands(const InstructionOperand& source,
630 const InstructionOperand& destination)
631 : source_(source), destination_(destination) {
632 DCHECK(!source.IsInvalid() && !destination.IsInvalid());
633 }
634
635 const InstructionOperand& source() const { return source_; }
636 InstructionOperand& source() { return source_; }
637 void set_source(const InstructionOperand& operand) { source_ = operand; }
638
639 const InstructionOperand& destination() const { return destination_; }
640 InstructionOperand& destination() { return destination_; }
641 void set_destination(const InstructionOperand& operand) {
642 destination_ = operand;
643 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000644
645 // The gap resolver marks moves as "in-progress" by clearing the
646 // destination (but not the source).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000647 bool IsPending() const {
648 return destination_.IsInvalid() && !source_.IsInvalid();
649 }
650 void SetPending() { destination_ = InstructionOperand(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000651
652 // True if this move a move into the given destination operand.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000653 bool Blocks(const InstructionOperand& operand) const {
654 return !IsEliminated() && source().EqualsCanonicalized(operand);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000655 }
656
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000657 // A move is redundant if it's been eliminated or if its source and
658 // destination are the same.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000659 bool IsRedundant() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000660 DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant());
661 return IsEliminated() || source_.EqualsCanonicalized(destination_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000662 }
663
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000664 // We clear both operands to indicate move that's been eliminated.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000665 void Eliminate() { source_ = destination_ = InstructionOperand(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000666 bool IsEliminated() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000667 DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid());
668 return source_.IsInvalid();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000669 }
670
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000671 void Print(const RegisterConfiguration* config) const;
672 void Print() const;
673
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000674 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000675 InstructionOperand source_;
676 InstructionOperand destination_;
677
678 DISALLOW_COPY_AND_ASSIGN(MoveOperands);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000679};
680
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400681
682struct PrintableMoveOperands {
683 const RegisterConfiguration* register_configuration_;
684 const MoveOperands* move_operands_;
685};
686
687
688std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo);
689
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000690
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000691class ParallelMove final : public ZoneVector<MoveOperands*>, public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000692 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000693 explicit ParallelMove(Zone* zone) : ZoneVector<MoveOperands*>(zone) {
694 reserve(4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000695 }
696
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000697 MoveOperands* AddMove(const InstructionOperand& from,
698 const InstructionOperand& to) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100699 Zone* zone = get_allocator().zone();
700 return AddMove(from, to, zone);
701 }
702
703 MoveOperands* AddMove(const InstructionOperand& from,
704 const InstructionOperand& to,
705 Zone* operand_allocation_zone) {
706 MoveOperands* move = new (operand_allocation_zone) MoveOperands(from, to);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000707 push_back(move);
708 return move;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000709 }
710
711 bool IsRedundant() const;
712
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000713 // Prepare this ParallelMove to insert move as if it happened in a subsequent
714 // ParallelMove. move->source() may be changed. The MoveOperand returned
715 // must be Eliminated.
716 MoveOperands* PrepareInsertAfter(MoveOperands* move) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000717
718 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000719 DISALLOW_COPY_AND_ASSIGN(ParallelMove);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000720};
721
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400722
723struct PrintableParallelMove {
724 const RegisterConfiguration* register_configuration_;
725 const ParallelMove* parallel_move_;
726};
727
728
729std::ostream& operator<<(std::ostream& os, const PrintableParallelMove& pm);
730
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000731
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000732class ReferenceMap final : public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000733 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000734 explicit ReferenceMap(Zone* zone)
735 : reference_operands_(8, zone), instruction_position_(-1) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000736
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000737 const ZoneVector<InstructionOperand>& reference_operands() const {
738 return reference_operands_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000739 }
740 int instruction_position() const { return instruction_position_; }
741
742 void set_instruction_position(int pos) {
743 DCHECK(instruction_position_ == -1);
744 instruction_position_ = pos;
745 }
746
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000747 void RecordReference(const AllocatedOperand& op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000748
749 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000750 friend std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000751
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000752 ZoneVector<InstructionOperand> reference_operands_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000753 int instruction_position_;
754};
755
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000756std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000757
Ben Murdochc5610432016-08-08 18:44:38 +0100758class InstructionBlock;
759
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000760class Instruction final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761 public:
762 size_t OutputCount() const { return OutputCountField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000763 const InstructionOperand* OutputAt(size_t i) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000764 DCHECK(i < OutputCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000765 return &operands_[i];
766 }
767 InstructionOperand* OutputAt(size_t i) {
768 DCHECK(i < OutputCount());
769 return &operands_[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000770 }
771
772 bool HasOutput() const { return OutputCount() == 1; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000773 const InstructionOperand* Output() const { return OutputAt(0); }
774 InstructionOperand* Output() { return OutputAt(0); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000775
776 size_t InputCount() const { return InputCountField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000777 const InstructionOperand* InputAt(size_t i) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000778 DCHECK(i < InputCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000779 return &operands_[OutputCount() + i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000780 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000781 InstructionOperand* InputAt(size_t i) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400782 DCHECK(i < InputCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000783 return &operands_[OutputCount() + i];
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400784 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000785
786 size_t TempCount() const { return TempCountField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000787 const InstructionOperand* TempAt(size_t i) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000788 DCHECK(i < TempCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000789 return &operands_[OutputCount() + InputCount() + i];
790 }
791 InstructionOperand* TempAt(size_t i) {
792 DCHECK(i < TempCount());
793 return &operands_[OutputCount() + InputCount() + i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000794 }
795
796 InstructionCode opcode() const { return opcode_; }
797 ArchOpcode arch_opcode() const { return ArchOpcodeField::decode(opcode()); }
798 AddressingMode addressing_mode() const {
799 return AddressingModeField::decode(opcode());
800 }
801 FlagsMode flags_mode() const { return FlagsModeField::decode(opcode()); }
802 FlagsCondition flags_condition() const {
803 return FlagsConditionField::decode(opcode());
804 }
805
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000806 static Instruction* New(Zone* zone, InstructionCode opcode) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000807 return New(zone, opcode, 0, nullptr, 0, nullptr, 0, nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000808 }
809
810 static Instruction* New(Zone* zone, InstructionCode opcode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000811 size_t output_count, InstructionOperand* outputs,
812 size_t input_count, InstructionOperand* inputs,
813 size_t temp_count, InstructionOperand* temps) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000814 DCHECK(opcode >= 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000815 DCHECK(output_count == 0 || outputs != nullptr);
816 DCHECK(input_count == 0 || inputs != nullptr);
817 DCHECK(temp_count == 0 || temps != nullptr);
Ben Murdochda12d292016-06-02 14:46:10 +0100818 // TODO(jarin/mstarzinger): Handle this gracefully. See crbug.com/582702.
819 CHECK(InputCountField::is_valid(input_count));
820
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000821 size_t total_extra_ops = output_count + input_count + temp_count;
822 if (total_extra_ops != 0) total_extra_ops--;
823 int size = static_cast<int>(
824 RoundUp(sizeof(Instruction), sizeof(InstructionOperand)) +
825 total_extra_ops * sizeof(InstructionOperand));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000826 return new (zone->New(size)) Instruction(
827 opcode, output_count, outputs, input_count, inputs, temp_count, temps);
828 }
829
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000830 Instruction* MarkAsCall() {
831 bit_field_ = IsCallField::update(bit_field_, true);
832 return this;
833 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000834 bool IsCall() const { return IsCallField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000835 bool NeedsReferenceMap() const { return IsCall(); }
836 bool HasReferenceMap() const { return reference_map_ != nullptr; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000837
838 bool ClobbersRegisters() const { return IsCall(); }
839 bool ClobbersTemps() const { return IsCall(); }
840 bool ClobbersDoubleRegisters() const { return IsCall(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000841 ReferenceMap* reference_map() const { return reference_map_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000842
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000843 void set_reference_map(ReferenceMap* map) {
844 DCHECK(NeedsReferenceMap());
845 DCHECK(!reference_map_);
846 reference_map_ = map;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000847 }
848
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400849 void OverwriteWithNop() {
850 opcode_ = ArchOpcodeField::encode(kArchNop);
851 bit_field_ = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000852 reference_map_ = nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400853 }
854
855 bool IsNop() const {
856 return arch_opcode() == kArchNop && InputCount() == 0 &&
857 OutputCount() == 0 && TempCount() == 0;
858 }
859
Ben Murdochda12d292016-06-02 14:46:10 +0100860 bool IsDeoptimizeCall() const {
861 return arch_opcode() == ArchOpcode::kArchDeoptimize ||
862 FlagsModeField::decode(opcode()) == kFlags_deoptimize;
863 }
864
865 bool IsJump() const { return arch_opcode() == ArchOpcode::kArchJmp; }
866 bool IsRet() const { return arch_opcode() == ArchOpcode::kArchRet; }
867 bool IsTailCall() const {
868 return arch_opcode() == ArchOpcode::kArchTailCallCodeObject ||
869 arch_opcode() == ArchOpcode::kArchTailCallCodeObjectFromJSFunction ||
870 arch_opcode() == ArchOpcode::kArchTailCallJSFunction ||
Ben Murdochc5610432016-08-08 18:44:38 +0100871 arch_opcode() == ArchOpcode::kArchTailCallJSFunctionFromJSFunction ||
872 arch_opcode() == ArchOpcode::kArchTailCallAddress;
Ben Murdochda12d292016-06-02 14:46:10 +0100873 }
874 bool IsThrow() const {
875 return arch_opcode() == ArchOpcode::kArchThrowTerminator;
876 }
877
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000878 enum GapPosition {
879 START,
880 END,
881 FIRST_GAP_POSITION = START,
882 LAST_GAP_POSITION = END
883 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000884
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000885 ParallelMove* GetOrCreateParallelMove(GapPosition pos, Zone* zone) {
886 if (parallel_moves_[pos] == nullptr) {
887 parallel_moves_[pos] = new (zone) ParallelMove(zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000888 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000889 return parallel_moves_[pos];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000890 }
891
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000892 ParallelMove* GetParallelMove(GapPosition pos) {
893 return parallel_moves_[pos];
894 }
895
896 const ParallelMove* GetParallelMove(GapPosition pos) const {
897 return parallel_moves_[pos];
898 }
899
900 bool AreMovesRedundant() const;
901
902 ParallelMove* const* parallel_moves() const { return &parallel_moves_[0]; }
903 ParallelMove** parallel_moves() { return &parallel_moves_[0]; }
904
Ben Murdochc5610432016-08-08 18:44:38 +0100905 // The block_id may be invalidated in JumpThreading. It is only important for
906 // register allocation, to avoid searching for blocks from instruction
907 // indexes.
908 InstructionBlock* block() const { return block_; }
909 void set_block(InstructionBlock* block) {
910 DCHECK_NOT_NULL(block);
911 block_ = block;
912 }
913
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000914 void Print(const RegisterConfiguration* config) const;
915 void Print() const;
916
917 private:
918 explicit Instruction(InstructionCode opcode);
919
920 Instruction(InstructionCode opcode, size_t output_count,
921 InstructionOperand* outputs, size_t input_count,
922 InstructionOperand* inputs, size_t temp_count,
923 InstructionOperand* temps);
924
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000925 typedef BitField<size_t, 0, 8> OutputCountField;
926 typedef BitField<size_t, 8, 16> InputCountField;
927 typedef BitField<size_t, 24, 6> TempCountField;
928 typedef BitField<bool, 30, 1> IsCallField;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000929
930 InstructionCode opcode_;
931 uint32_t bit_field_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000932 ParallelMove* parallel_moves_[2];
933 ReferenceMap* reference_map_;
Ben Murdochc5610432016-08-08 18:44:38 +0100934 InstructionBlock* block_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000935 InstructionOperand operands_[1];
936
937 DISALLOW_COPY_AND_ASSIGN(Instruction);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000938};
939
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400940
941struct PrintableInstruction {
942 const RegisterConfiguration* register_configuration_;
943 const Instruction* instr_;
944};
945std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr);
946
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000947
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000948class RpoNumber final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000949 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000950 static const int kInvalidRpoNumber = -1;
951 int ToInt() const {
952 DCHECK(IsValid());
953 return index_;
954 }
955 size_t ToSize() const {
956 DCHECK(IsValid());
957 return static_cast<size_t>(index_);
958 }
959 bool IsValid() const { return index_ >= 0; }
960 static RpoNumber FromInt(int index) { return RpoNumber(index); }
961 static RpoNumber Invalid() { return RpoNumber(kInvalidRpoNumber); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000962
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000963 bool IsNext(const RpoNumber other) const {
964 DCHECK(IsValid());
965 return other.index_ == this->index_ + 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000966 }
967
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968 // Comparison operators.
969 bool operator==(RpoNumber other) const { return index_ == other.index_; }
970 bool operator!=(RpoNumber other) const { return index_ != other.index_; }
971 bool operator>(RpoNumber other) const { return index_ > other.index_; }
972 bool operator<(RpoNumber other) const { return index_ < other.index_; }
973 bool operator<=(RpoNumber other) const { return index_ <= other.index_; }
974 bool operator>=(RpoNumber other) const { return index_ >= other.index_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000975
976 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000977 explicit RpoNumber(int32_t index) : index_(index) {}
978 int32_t index_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000979};
980
981
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000982std::ostream& operator<<(std::ostream&, const RpoNumber&);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000983
984
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000985class Constant final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000986 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400987 enum Type {
988 kInt32,
989 kInt64,
990 kFloat32,
991 kFloat64,
992 kExternalReference,
993 kHeapObject,
994 kRpoNumber
995 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000996
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000997 explicit Constant(int32_t v);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998 explicit Constant(int64_t v) : type_(kInt64), value_(v) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400999 explicit Constant(float v) : type_(kFloat32), value_(bit_cast<int32_t>(v)) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001000 explicit Constant(double v) : type_(kFloat64), value_(bit_cast<int64_t>(v)) {}
1001 explicit Constant(ExternalReference ref)
1002 : type_(kExternalReference), value_(bit_cast<intptr_t>(ref)) {}
1003 explicit Constant(Handle<HeapObject> obj)
1004 : type_(kHeapObject), value_(bit_cast<intptr_t>(obj)) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005 explicit Constant(RpoNumber rpo) : type_(kRpoNumber), value_(rpo.ToInt()) {}
Ben Murdochc5610432016-08-08 18:44:38 +01001006 explicit Constant(RelocatablePtrConstantInfo info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001007
1008 Type type() const { return type_; }
1009
Ben Murdochc5610432016-08-08 18:44:38 +01001010 RelocInfo::Mode rmode() const { return rmode_; }
1011
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001012 int32_t ToInt32() const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001013 DCHECK(type() == kInt32 || type() == kInt64);
1014 const int32_t value = static_cast<int32_t>(value_);
1015 DCHECK_EQ(value_, static_cast<int64_t>(value));
1016 return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001017 }
1018
1019 int64_t ToInt64() const {
1020 if (type() == kInt32) return ToInt32();
1021 DCHECK_EQ(kInt64, type());
1022 return value_;
1023 }
1024
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001025 float ToFloat32() const {
1026 DCHECK_EQ(kFloat32, type());
1027 return bit_cast<float>(static_cast<int32_t>(value_));
1028 }
1029
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001030 double ToFloat64() const {
1031 if (type() == kInt32) return ToInt32();
1032 DCHECK_EQ(kFloat64, type());
1033 return bit_cast<double>(value_);
1034 }
1035
1036 ExternalReference ToExternalReference() const {
1037 DCHECK_EQ(kExternalReference, type());
1038 return bit_cast<ExternalReference>(static_cast<intptr_t>(value_));
1039 }
1040
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001041 RpoNumber ToRpoNumber() const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001042 DCHECK_EQ(kRpoNumber, type());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001043 return RpoNumber::FromInt(static_cast<int>(value_));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001044 }
1045
Ben Murdochc5610432016-08-08 18:44:38 +01001046 Handle<HeapObject> ToHeapObject() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001047
1048 private:
1049 Type type_;
1050 int64_t value_;
Ben Murdochc5610432016-08-08 18:44:38 +01001051#if V8_TARGET_ARCH_32_BIT
1052 RelocInfo::Mode rmode_ = RelocInfo::NONE32;
1053#else
1054 RelocInfo::Mode rmode_ = RelocInfo::NONE64;
1055#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001056};
1057
1058
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001059std::ostream& operator<<(std::ostream& os, const Constant& constant);
1060
1061
1062// Forward declarations.
1063class FrameStateDescriptor;
1064
1065
1066enum class StateValueKind { kPlain, kNested, kDuplicate };
1067
1068
1069class StateValueDescriptor {
1070 public:
1071 explicit StateValueDescriptor(Zone* zone)
1072 : kind_(StateValueKind::kPlain),
1073 type_(MachineType::AnyTagged()),
1074 id_(0),
1075 fields_(zone) {}
1076
1077 static StateValueDescriptor Plain(Zone* zone, MachineType type) {
1078 return StateValueDescriptor(StateValueKind::kPlain, zone, type, 0);
1079 }
1080 static StateValueDescriptor Recursive(Zone* zone, size_t id) {
1081 return StateValueDescriptor(StateValueKind::kNested, zone,
1082 MachineType::AnyTagged(), id);
1083 }
1084 static StateValueDescriptor Duplicate(Zone* zone, size_t id) {
1085 return StateValueDescriptor(StateValueKind::kDuplicate, zone,
1086 MachineType::AnyTagged(), id);
1087 }
1088
1089 size_t size() { return fields_.size(); }
1090 ZoneVector<StateValueDescriptor>& fields() { return fields_; }
1091 int IsPlain() { return kind_ == StateValueKind::kPlain; }
1092 int IsNested() { return kind_ == StateValueKind::kNested; }
1093 int IsDuplicate() { return kind_ == StateValueKind::kDuplicate; }
1094 MachineType type() const { return type_; }
1095 MachineType GetOperandType(size_t index) const {
1096 return fields_[index].type_;
1097 }
1098 size_t id() const { return id_; }
1099
1100 private:
1101 StateValueDescriptor(StateValueKind kind, Zone* zone, MachineType type,
1102 size_t id)
1103 : kind_(kind), type_(type), id_(id), fields_(zone) {}
1104
1105 StateValueKind kind_;
1106 MachineType type_;
1107 size_t id_;
1108 ZoneVector<StateValueDescriptor> fields_;
1109};
1110
1111
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001112class FrameStateDescriptor : public ZoneObject {
1113 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001114 FrameStateDescriptor(Zone* zone, FrameStateType type, BailoutId bailout_id,
1115 OutputFrameStateCombine state_combine,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001116 size_t parameters_count, size_t locals_count,
1117 size_t stack_count,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001118 MaybeHandle<SharedFunctionInfo> shared_info,
1119 FrameStateDescriptor* outer_state = nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001120
1121 FrameStateType type() const { return type_; }
1122 BailoutId bailout_id() const { return bailout_id_; }
1123 OutputFrameStateCombine state_combine() const { return frame_state_combine_; }
1124 size_t parameters_count() const { return parameters_count_; }
1125 size_t locals_count() const { return locals_count_; }
1126 size_t stack_count() const { return stack_count_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001127 MaybeHandle<SharedFunctionInfo> shared_info() const { return shared_info_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001128 FrameStateDescriptor* outer_state() const { return outer_state_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001129 bool HasContext() const {
1130 return FrameStateFunctionInfo::IsJSFunctionType(type_);
1131 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001132
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001133 size_t GetSize(OutputFrameStateCombine combine =
1134 OutputFrameStateCombine::Ignore()) const;
1135 size_t GetTotalSize() const;
1136 size_t GetFrameCount() const;
1137 size_t GetJSFrameCount() const;
1138
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001139 MachineType GetType(size_t index) const {
1140 return values_.GetOperandType(index);
1141 }
1142 StateValueDescriptor* GetStateValueDescriptor() { return &values_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001143
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001144 private:
1145 FrameStateType type_;
1146 BailoutId bailout_id_;
1147 OutputFrameStateCombine frame_state_combine_;
1148 size_t parameters_count_;
1149 size_t locals_count_;
1150 size_t stack_count_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001151 StateValueDescriptor values_;
1152 MaybeHandle<SharedFunctionInfo> const shared_info_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001153 FrameStateDescriptor* outer_state_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001154};
1155
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001156
1157typedef ZoneVector<FrameStateDescriptor*> DeoptimizationVector;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001158
1159
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001160class PhiInstruction final : public ZoneObject {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001161 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001162 typedef ZoneVector<InstructionOperand> Inputs;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001163
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001164 PhiInstruction(Zone* zone, int virtual_register, size_t input_count);
1165
1166 void SetInput(size_t offset, int virtual_register);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001167
1168 int virtual_register() const { return virtual_register_; }
1169 const IntVector& operands() const { return operands_; }
1170
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001171 // TODO(dcarney): this has no real business being here, since it's internal to
1172 // the register allocator, but putting it here was convenient.
1173 const InstructionOperand& output() const { return output_; }
1174 InstructionOperand& output() { return output_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001175
1176 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001177 const int virtual_register_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001178 InstructionOperand output_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001179 IntVector operands_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001180};
1181
1182
1183// Analogue of BasicBlock for Instructions instead of Nodes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001184class InstructionBlock final : public ZoneObject {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001185 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001186 InstructionBlock(Zone* zone, RpoNumber rpo_number, RpoNumber loop_header,
1187 RpoNumber loop_end, bool deferred, bool handler);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001188
1189 // Instruction indexes (used by the register allocator).
1190 int first_instruction_index() const {
1191 DCHECK(code_start_ >= 0);
1192 DCHECK(code_end_ > 0);
1193 DCHECK(code_end_ >= code_start_);
1194 return code_start_;
1195 }
1196 int last_instruction_index() const {
1197 DCHECK(code_start_ >= 0);
1198 DCHECK(code_end_ > 0);
1199 DCHECK(code_end_ >= code_start_);
1200 return code_end_ - 1;
1201 }
1202
1203 int32_t code_start() const { return code_start_; }
1204 void set_code_start(int32_t start) { code_start_ = start; }
1205
1206 int32_t code_end() const { return code_end_; }
1207 void set_code_end(int32_t end) { code_end_ = end; }
1208
1209 bool IsDeferred() const { return deferred_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001210 bool IsHandler() const { return handler_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001211
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001212 RpoNumber ao_number() const { return ao_number_; }
1213 RpoNumber rpo_number() const { return rpo_number_; }
1214 RpoNumber loop_header() const { return loop_header_; }
1215 RpoNumber loop_end() const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001216 DCHECK(IsLoopHeader());
1217 return loop_end_;
1218 }
1219 inline bool IsLoopHeader() const { return loop_end_.IsValid(); }
1220
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001221 typedef ZoneVector<RpoNumber> Predecessors;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001222 Predecessors& predecessors() { return predecessors_; }
1223 const Predecessors& predecessors() const { return predecessors_; }
1224 size_t PredecessorCount() const { return predecessors_.size(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001225 size_t PredecessorIndexOf(RpoNumber rpo_number) const;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001226
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001227 typedef ZoneVector<RpoNumber> Successors;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001228 Successors& successors() { return successors_; }
1229 const Successors& successors() const { return successors_; }
1230 size_t SuccessorCount() const { return successors_.size(); }
1231
1232 typedef ZoneVector<PhiInstruction*> PhiInstructions;
1233 const PhiInstructions& phis() const { return phis_; }
1234 void AddPhi(PhiInstruction* phi) { phis_.push_back(phi); }
1235
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001236 void set_ao_number(RpoNumber ao_number) { ao_number_ = ao_number; }
1237
1238 bool needs_frame() const { return needs_frame_; }
1239 void mark_needs_frame() { needs_frame_ = true; }
1240
1241 bool must_construct_frame() const { return must_construct_frame_; }
1242 void mark_must_construct_frame() { must_construct_frame_ = true; }
1243
1244 bool must_deconstruct_frame() const { return must_deconstruct_frame_; }
1245 void mark_must_deconstruct_frame() { must_deconstruct_frame_ = true; }
1246
1247 void set_last_deferred(RpoNumber last) { last_deferred_ = last; }
1248 RpoNumber last_deferred() const { return last_deferred_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001249
1250 private:
1251 Successors successors_;
1252 Predecessors predecessors_;
1253 PhiInstructions phis_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001254 RpoNumber ao_number_; // Assembly order number.
1255 const RpoNumber rpo_number_;
1256 const RpoNumber loop_header_;
1257 const RpoNumber loop_end_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001258 int32_t code_start_; // start index of arch-specific code.
1259 int32_t code_end_; // end index of arch-specific code.
1260 const bool deferred_; // Block contains deferred code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001261 const bool handler_; // Block is a handler entry point.
1262 bool needs_frame_;
1263 bool must_construct_frame_;
1264 bool must_deconstruct_frame_;
1265 RpoNumber last_deferred_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001266};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001267
1268typedef ZoneDeque<Constant> ConstantDeque;
1269typedef std::map<int, Constant, std::less<int>,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001270 zone_allocator<std::pair<const int, Constant> > > ConstantMap;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001271
1272typedef ZoneDeque<Instruction*> InstructionDeque;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001273typedef ZoneDeque<ReferenceMap*> ReferenceMapDeque;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001274typedef ZoneVector<InstructionBlock*> InstructionBlocks;
1275
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001276
1277// Forward declarations.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001278struct PrintableInstructionSequence;
1279
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001280
1281// Represents architecture-specific generated code before, during, and after
1282// register allocation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001283class InstructionSequence final : public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001284 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001285 static InstructionBlocks* InstructionBlocksFor(Zone* zone,
1286 const Schedule* schedule);
1287 // Puts the deferred blocks last.
1288 static void ComputeAssemblyOrder(InstructionBlocks* blocks);
1289
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001290 InstructionSequence(Isolate* isolate, Zone* zone,
1291 InstructionBlocks* instruction_blocks);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001292
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001293 int NextVirtualRegister();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001294 int VirtualRegisterCount() const { return next_virtual_register_; }
1295
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001296 const InstructionBlocks& instruction_blocks() const {
1297 return *instruction_blocks_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001298 }
1299
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001300 int InstructionBlockCount() const {
1301 return static_cast<int>(instruction_blocks_->size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001302 }
1303
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001304 InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001305 return instruction_blocks_->at(rpo_number.ToSize());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001306 }
1307
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001308 int LastLoopInstructionIndex(const InstructionBlock* block) {
1309 return instruction_blocks_->at(block->loop_end().ToSize() - 1)
1310 ->last_instruction_index();
1311 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001312
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001313 const InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001314 return instruction_blocks_->at(rpo_number.ToSize());
1315 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001316
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001317 InstructionBlock* GetInstructionBlock(int instruction_index) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001318
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001319 static MachineRepresentation DefaultRepresentation() {
1320 return MachineType::PointerRepresentation();
1321 }
1322 MachineRepresentation GetRepresentation(int virtual_register) const;
1323 void MarkAsRepresentation(MachineRepresentation rep, int virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001324
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001325 bool IsReference(int virtual_register) const {
1326 return GetRepresentation(virtual_register) ==
1327 MachineRepresentation::kTagged;
1328 }
1329 bool IsFloat(int virtual_register) const {
1330 return IsFloatingPoint(GetRepresentation(virtual_register));
1331 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001332
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001333 Instruction* GetBlockStart(RpoNumber rpo) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001334
1335 typedef InstructionDeque::const_iterator const_iterator;
1336 const_iterator begin() const { return instructions_.begin(); }
1337 const_iterator end() const { return instructions_.end(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001338 const InstructionDeque& instructions() const { return instructions_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001339 int LastInstructionIndex() const {
1340 return static_cast<int>(instructions().size()) - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001341 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001342
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001343 Instruction* InstructionAt(int index) const {
1344 DCHECK(index >= 0);
1345 DCHECK(index < static_cast<int>(instructions_.size()));
1346 return instructions_[index];
1347 }
1348
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001349 Isolate* isolate() const { return isolate_; }
1350 const ReferenceMapDeque* reference_maps() const { return &reference_maps_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001351 Zone* zone() const { return zone_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001352
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001353 // Used by the instruction selector while adding instructions.
1354 int AddInstruction(Instruction* instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001355 void StartBlock(RpoNumber rpo);
1356 void EndBlock(RpoNumber rpo);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001357
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001358 int AddConstant(int virtual_register, Constant constant) {
1359 // TODO(titzer): allow RPO numbers as constants?
1360 DCHECK(constant.type() != Constant::kRpoNumber);
1361 DCHECK(virtual_register >= 0 && virtual_register < next_virtual_register_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001362 DCHECK(constants_.find(virtual_register) == constants_.end());
1363 constants_.insert(std::make_pair(virtual_register, constant));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001364 return virtual_register;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001365 }
1366 Constant GetConstant(int virtual_register) const {
1367 ConstantMap::const_iterator it = constants_.find(virtual_register);
1368 DCHECK(it != constants_.end());
1369 DCHECK_EQ(virtual_register, it->first);
1370 return it->second;
1371 }
1372
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001373 typedef ZoneVector<Constant> Immediates;
1374 Immediates& immediates() { return immediates_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001375
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001376 ImmediateOperand AddImmediate(const Constant& constant) {
Ben Murdochc5610432016-08-08 18:44:38 +01001377 if (constant.type() == Constant::kInt32 &&
1378 RelocInfo::IsNone(constant.rmode())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001379 return ImmediateOperand(ImmediateOperand::INLINE, constant.ToInt32());
1380 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001381 int index = static_cast<int>(immediates_.size());
1382 immediates_.push_back(constant);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001383 return ImmediateOperand(ImmediateOperand::INDEXED, index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001384 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001385
1386 Constant GetImmediate(const ImmediateOperand* op) const {
1387 switch (op->type()) {
1388 case ImmediateOperand::INLINE:
1389 return Constant(op->inline_value());
1390 case ImmediateOperand::INDEXED: {
1391 int index = op->indexed_value();
1392 DCHECK(index >= 0);
1393 DCHECK(index < static_cast<int>(immediates_.size()));
1394 return immediates_[index];
1395 }
1396 }
1397 UNREACHABLE();
1398 return Constant(static_cast<int32_t>(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001399 }
1400
1401 class StateId {
1402 public:
1403 static StateId FromInt(int id) { return StateId(id); }
1404 int ToInt() const { return id_; }
1405
1406 private:
1407 explicit StateId(int id) : id_(id) {}
1408 int id_;
1409 };
1410
1411 StateId AddFrameStateDescriptor(FrameStateDescriptor* descriptor);
1412 FrameStateDescriptor* GetFrameStateDescriptor(StateId deoptimization_id);
1413 int GetFrameStateDescriptorCount();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001414 DeoptimizationVector const& frame_state_descriptors() const {
1415 return deoptimization_entries_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001416 }
1417
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001418 RpoNumber InputRpo(Instruction* instr, size_t index);
1419
1420 bool GetSourcePosition(const Instruction* instr,
1421 SourcePosition* result) const;
1422 void SetSourcePosition(const Instruction* instr, SourcePosition value);
1423
1424 bool ContainsCall() const {
1425 for (Instruction* instr : instructions_) {
1426 if (instr->IsCall()) return true;
1427 }
1428 return false;
1429 }
1430 void Print(const RegisterConfiguration* config) const;
1431 void Print() const;
1432
Ben Murdoch097c5b22016-05-18 11:27:45 +01001433 void PrintBlock(const RegisterConfiguration* config, int block_id) const;
1434 void PrintBlock(int block_id) const;
1435
Ben Murdochc5610432016-08-08 18:44:38 +01001436 void ValidateEdgeSplitForm() const;
1437 void ValidateDeferredBlockExitPaths() const;
1438 void ValidateDeferredBlockEntryPaths() const;
1439 void ValidateSSA() const;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001440
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001441 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001442 friend std::ostream& operator<<(std::ostream& os,
1443 const PrintableInstructionSequence& code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001444
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001445 typedef ZoneMap<const Instruction*, SourcePosition> SourcePositionMap;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001446
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001447 Isolate* isolate_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001448 Zone* const zone_;
1449 InstructionBlocks* const instruction_blocks_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001450 SourcePositionMap source_positions_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001451 ConstantMap constants_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001452 Immediates immediates_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001453 InstructionDeque instructions_;
1454 int next_virtual_register_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001455 ReferenceMapDeque reference_maps_;
1456 ZoneVector<MachineRepresentation> representations_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001457 DeoptimizationVector deoptimization_entries_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001458
Ben Murdochc5610432016-08-08 18:44:38 +01001459 // Used at construction time
1460 InstructionBlock* current_block_;
1461
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001462 DISALLOW_COPY_AND_ASSIGN(InstructionSequence);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001463};
1464
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001465
1466struct PrintableInstructionSequence {
1467 const RegisterConfiguration* register_configuration_;
1468 const InstructionSequence* sequence_;
1469};
1470
1471
1472std::ostream& operator<<(std::ostream& os,
1473 const PrintableInstructionSequence& code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001474
1475} // namespace compiler
1476} // namespace internal
1477} // namespace v8
1478
1479#endif // V8_COMPILER_INSTRUCTION_H_