Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
locations.h
Go to the documentation of this file.
1// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_COMPILER_BACKEND_LOCATIONS_H_
6#define RUNTIME_VM_COMPILER_BACKEND_LOCATIONS_H_
7
8#if defined(DART_PRECOMPILED_RUNTIME)
9#error "AOT runtime should not use compiler sources (including header files)"
10#endif // defined(DART_PRECOMPILED_RUNTIME)
11
12#include "vm/allocation.h"
13#include "vm/bitfield.h"
14#include "vm/bitmap.h"
16#include "vm/constants.h"
17#include "vm/cpu.h"
18
19namespace dart {
20
21class BaseTextBuffer;
22class ConstantInstr;
23class Definition;
24class FlowGraphDeserializer;
25class FlowGraphSerializer;
26class PairLocation;
27class Value;
28
29// All unboxed integer representations.
30// Format: (representation name, name for printing, is unsigned, value type)
31#define FOR_EACH_INTEGER_REPRESENTATION_KIND(M) \
32 M(UnboxedInt8, int8, false, int8_t) \
33 M(UnboxedUint8, uint8, true, uint8_t) \
34 M(UnboxedInt16, int16, false, int16_t) \
35 M(UnboxedUint16, uint16, true, uint16_t) \
36 M(UnboxedInt32, int32, false, int32_t) \
37 M(UnboxedUint32, uint32, true, uint32_t) \
38 M(UnboxedInt64, int64, false, int64_t)
39
40// All unboxed representations.
41// Format: (representation name, name for printing, _, value type)
42#define FOR_EACH_UNBOXED_REPRESENTATION_KIND(M) \
43 M(UnboxedDouble, double, _, double_t) \
44 M(UnboxedFloat, float, _, float_t) \
45 FOR_EACH_INTEGER_REPRESENTATION_KIND(M) \
46 M(UnboxedFloat32x4, float32x4, _, simd128_value_t) \
47 M(UnboxedInt32x4, int32x4, _, simd128_value_t) \
48 M(UnboxedFloat64x2, float64x2, _, simd128_value_t)
49
50// All representations that represent a single boxed or unboxed value.
51// (Note that packed SIMD values are considered a single value here.)
52// Format: (representation name, name for printing, _, value type)
53#define FOR_EACH_SIMPLE_REPRESENTATION_KIND(M) \
54 M(Tagged, tagged, _, compiler::target::word) \
55 M(Untagged, untagged, _, compiler::target::word) \
56 FOR_EACH_UNBOXED_REPRESENTATION_KIND(M)
57
58// All representations, including sentinel and multi-value representations.
59// Format: (representation name, name for printing, _, _)
60// Ordered so that NoRepresentation is first (and thus 0 in the enum).
61#define FOR_EACH_REPRESENTATION_KIND(M) \
62 M(NoRepresentation, none, _, _) \
63 FOR_EACH_SIMPLE_REPRESENTATION_KIND(M) \
64 M(PairOfTagged, tagged_pair, _, _)
65
67#define DECLARE_REPRESENTATION(name, __, ___, ____) k##name,
69#undef DECLARE_REPRESENTATION
71};
72
73static constexpr intptr_t kMaxLocationCount = 2;
74
75inline intptr_t LocationCount(Representation rep) {
76 switch (rep) {
77 case kPairOfTagged:
78 return 2;
79 case kUnboxedInt64:
80 return compiler::target::kWordSize == 8 ? 1 : 2;
81 default:
82 return 1;
83 }
84}
85
87#define REP_IN_SET_CLAUSE(name, __, ___, ____) \
88 case k##name: \
89 return true;
90
91 // Whether the representation is for a type of unboxed integer.
92 static constexpr bool IsUnboxedInteger(Representation rep) {
93 switch (rep) {
95 default:
96 return false;
97 }
98 }
99
100 // Whether the representation is for a type of unboxed value.
101 static constexpr bool IsUnboxed(Representation rep) {
102 switch (rep) {
104 default:
105 return false;
106 }
107 }
108
109#undef REP_IN_SET_CLAUSE
110
111 // The size of values described by this representation.
112 static constexpr size_t ValueSize(Representation rep) {
113 switch (rep) {
114#define REP_SIZEOF_CLAUSE(name, __, ___, type) \
115 case k##name: \
116 return sizeof(type);
118#undef REP_SIZEOF_CLAUSE
119 default:
120 UNREACHABLE();
121 return compiler::target::kWordSize;
122 }
123 }
124
125 // Whether the values described by this representation are unsigned integers.
127 switch (rep) {
128#define REP_IS_UNSIGNED_CLAUSE(name, __, unsigned, ___) \
129 case k##name: \
130 return unsigned;
132#undef REP_IS_UNSIGNED_CLAUSE
133 default:
134 return false;
135 }
136 }
137
138 // The OperandSize that should be used in the assembler for operations on
139 // values with the given representation.
141
142 // The minimum integral value that can be represented.
143 // Assumes that [rep] is an unboxed integer.
144 static int64_t MinValue(Representation rep);
145
146 // The maximum integral value that can be represented.
147 // Assumes that [rep] is an unboxed integer.
148 static int64_t MaxValue(Representation rep);
149
150 // Whether the given value is representable in the given representation.
151 // Assumes that [rep] is an unboxed integer.
152 static bool IsRepresentable(Representation rep, int64_t value);
153
154 // Returns the representation of the elements stored in an array with the
155 // given cid.
157
158 // Returns a descriptive name as a C string for the given representation
159 // suitable for use in debugging or error information.
160 static const char* ToCString(Representation rep);
161};
162
163// The representation for word-sized unboxed fields.
164static constexpr Representation kUnboxedWord =
165 compiler::target::kWordSize == 4 ? kUnboxedInt32 : kUnboxedInt64;
166// The representation for unsigned word-sized unboxed fields.
167//
168// Note: 64-bit kUnboxedUword is identical to kUnboxedWord until range analysis
169// can handle unsigned 64-bit ranges. This means that range analysis will give
170// signed results for unboxed uword field values.
172 compiler::target::kWordSize == 4 ? kUnboxedUint32 : kUnboxedInt64;
173
174// The representation which can be used for native pointers. We use signed 32/64
175// bit representation to be able to do arithmetic on pointers.
177
178// The representation used for pointers being exposed to users as Dart integers,
179// or stored in a way that could be eventually exposed to users. In particular,
180// this ensures that a 32-bit address, when extended to a 64-bit Dart integer,
181// is zero-extended, not sign extended.
183
184// Location objects are used to connect register allocator and code generator.
185// Instruction templates used by code generator have a corresponding
186// LocationSummary object which specifies expected location for every input
187// and output.
188// Each location is encoded as a single word: for non-constant locations
189// low 4 bits denote location kind, rest is kind specific location payload
190// e.g. for REGISTER kind payload is register code (value of the Register
191// enumeration), constant locations contain a tagged (low 2 bits are set to 01)
192// Object handle.
193//
194// Locations must satisfy the following invariant: if two locations' encodings
195// are bitwise unequal then these two locations are guaranteed to be disjoint.
196// Properties like representation belong to the value that is stored in
197// the location not to the location itself.
198class Location : public ValueObject {
199 private:
200 enum {
201 // Number of bits required to encode Kind value.
202 kKindBitsPos = 0,
203 kKindBitsSize = 5,
204
205 kPayloadBitsPos = kKindBitsPos + kKindBitsSize,
206 kPayloadBitsSize = kBitsPerWord - kPayloadBitsPos,
207 };
208
209 static constexpr uword kInvalidLocation = 0;
210 static constexpr uword kLocationTagMask = 0x3;
211
212 public:
213 // Constant payload can overlap with kind field so Kind values
214 // have to be chosen in a way that their last 2 bits are never
215 // the same as kConstantTag or kPairLocationTag.
216 // Note that two locations with different kinds should never point to
217 // the same place. For example kQuadStackSlot location should never intersect
218 // with kDoubleStackSlot location.
219 enum Kind : intptr_t {
220 // This location is invalid. Payload must be zero.
222
223 // Constant value. This location contains a tagged Object handle.
225
226 // This location contains a tagged pointer to a PairLocation.
228
229 // Unallocated location represents a location that is not fixed and can be
230 // allocated by a register allocator. Each unallocated location has
231 // a policy that specifies what kind of location is suitable. Payload
232 // contains register allocation policy.
233 kUnallocated = 1 << 2,
234
235 // Spill slots allocated by the register allocator. Payload contains
236 // a spill index.
237 kStackSlot = 2 << 2, // Word size slot.
238 kDoubleStackSlot = 3 << 2, // 64bit stack slot.
239 kQuadStackSlot = 4 << 2, // 128bit stack slot.
240
241 // Register location represents a fixed register. Payload contains
242 // register code.
243 kRegister = 5 << 2,
244
245 // FpuRegister location represents a fixed fpu register. Payload contains
246 // its code.
247 kFpuRegister = 6 << 2,
248 };
249
250 Location() : value_(kInvalidLocation) {
251 // Verify that non-tagged location kinds do not interfere with location tags
252 // (kConstantTag and kPairLocationTag).
253 COMPILE_ASSERT((kInvalid & kLocationTagMask) != kConstantTag);
254 COMPILE_ASSERT((kInvalid & kLocationTagMask) != kPairLocationTag);
255
256 COMPILE_ASSERT((kUnallocated & kLocationTagMask) != kConstantTag);
257 COMPILE_ASSERT((kUnallocated & kLocationTagMask) != kPairLocationTag);
258
259 COMPILE_ASSERT((kStackSlot & kLocationTagMask) != kConstantTag);
260 COMPILE_ASSERT((kStackSlot & kLocationTagMask) != kPairLocationTag);
261
262 COMPILE_ASSERT((kDoubleStackSlot & kLocationTagMask) != kConstantTag);
263 COMPILE_ASSERT((kDoubleStackSlot & kLocationTagMask) != kPairLocationTag);
264
265 COMPILE_ASSERT((kQuadStackSlot & kLocationTagMask) != kConstantTag);
266 COMPILE_ASSERT((kQuadStackSlot & kLocationTagMask) != kPairLocationTag);
267
268 COMPILE_ASSERT((kRegister & kLocationTagMask) != kConstantTag);
269 COMPILE_ASSERT((kRegister & kLocationTagMask) != kPairLocationTag);
270
271 COMPILE_ASSERT((kFpuRegister & kLocationTagMask) != kConstantTag);
272 COMPILE_ASSERT((kFpuRegister & kLocationTagMask) != kPairLocationTag);
273
274 // Verify tags and tagmask.
275 COMPILE_ASSERT((kConstantTag & kLocationTagMask) == kConstantTag);
276
277 COMPILE_ASSERT((kPairLocationTag & kLocationTagMask) == kPairLocationTag);
278
279 ASSERT(IsInvalid());
280 }
281
282 Location(const Location& other) : ValueObject(), value_(other.value_) {}
283
284 Location& operator=(const Location& other) {
285 value_ = other.value_;
286 return *this;
287 }
288
289 bool IsInvalid() const { return value_ == kInvalidLocation; }
290
291 // Constants.
292 bool IsConstant() const { return (value_ & kConstantTag) == kConstantTag; }
293
294 static Location Constant(const ConstantInstr* obj, int pair_index = 0) {
295 ASSERT((pair_index == 0) || (pair_index == 1));
296 Location loc(reinterpret_cast<uword>(obj) |
297 (pair_index != 0 ? static_cast<uword>(kPairLocationTag) : 0) |
298 static_cast<uword>(kConstantTag));
299 ASSERT(obj == loc.constant_instruction());
300 ASSERT(loc.pair_index() == pair_index);
301 return loc;
302 }
303
304 intptr_t pair_index() const {
306 return (value_ & kPairLocationTag) != 0 ? 1 : 0;
307 }
308
311 return reinterpret_cast<ConstantInstr*>(value_ & ~kLocationTagMask);
312 }
313
314 const Object& constant() const;
315
316 bool IsPairLocation() const {
317 return (value_ & kLocationTagMask) == kPairLocationTag;
318 }
319
320 static Location Pair(Location first, Location second);
321
323
324 // For pair locations, returns the ith component (for i in {0, 1}).
325 Location Component(intptr_t i) const;
326
327 // Unallocated locations.
328 enum Policy {
335 // Forces the location to be spilled to the stack.
336 // Currently only used for `Handle` arguments in `FfiCall` instructions.
337 // Only available in optimized mode.
339 };
340
341 bool IsUnallocated() const { return kind() == kUnallocated; }
342
344 return !Equals(Any()) && !Equals(RequiresStack());
345 }
346
350
351 // Any free register is suitable to replace this unallocated location.
352 static Location Any() { return UnallocatedLocation(kAny); }
353
357
361
362 // Blocks a CPU register for the entirety of the IL instruction.
363 //
364 // The register value _must_ be preserved by the machine code.
368
372
373 // Blocks a CPU register for the entirety of the IL instruction.
374 //
375 // The register value does not have to be preserved by the machine code.
379
380 // The location of the first input to the instruction will be
381 // used to replace this unallocated location.
385
386 // Empty location. Used if there the location should be ignored.
387 static Location NoLocation() { return Location(); }
388
389 Policy policy() const {
391 return PolicyField::decode(payload());
392 }
393
394 // Blocks `reg` for the entirety of the IL instruction.
395 //
396 // The register value does not have to be preserved by the machine code.
397 // TODO(https://dartbug.com/51409): Rename to WritableRegisterLocation.
401
402 bool IsRegister() const { return kind() == kRegister; }
403
404 Register reg() const {
406 return static_cast<Register>(payload());
407 }
408
409 // FpuRegister locations.
413
414 bool IsFpuRegister() const { return kind() == kFpuRegister; }
415
418 return static_cast<FpuRegister>(payload());
419 }
420
422 return (kind == kRegister) || (kind == kFpuRegister);
423 }
424
426 if (kind == kRegister) {
427 return RegisterLocation(static_cast<Register>(reg));
428 } else {
430 return FpuRegisterLocation(static_cast<FpuRegister>(reg));
431 }
432 }
433
434 bool IsMachineRegister() const { return IsMachineRegisterKind(kind()); }
435
436 intptr_t register_code() const {
438 return static_cast<intptr_t>(payload());
439 }
440
442 ASSERT((-kStackIndexBias <= stack_index) &&
443 (stack_index < kStackIndexBias));
444 return static_cast<uword>(kStackIndexBias + stack_index);
445 }
446
450 Location loc(kStackSlot, payload);
451 // Ensure that sign is preserved.
453 return loc;
454 }
455
456 bool IsStackSlot() const { return kind() == kStackSlot; }
457
461 Location loc(kDoubleStackSlot, payload);
462 // Ensure that sign is preserved.
464 return loc;
465 }
466
467 bool IsDoubleStackSlot() const { return kind() == kDoubleStackSlot; }
468
472 Location loc(kQuadStackSlot, payload);
473 // Ensure that sign is preserved.
475 return loc;
476 }
477
478 bool IsQuadStackSlot() const { return kind() == kQuadStackSlot; }
479
482 return StackSlotBaseField::decode(payload());
483 }
484
485 intptr_t stack_index() const {
487 // Decode stack index manually to preserve sign.
488 return StackIndexField::decode(payload()) - kStackIndexBias;
489 }
490
491 bool HasStackIndex() const {
493 }
494
495 // Returns the offset from the frame pointer for stack slot locations.
496 intptr_t ToStackSlotOffset() const;
497
498 // If the given location is FP relative stack location this returns
499 // corresponding SP relative location assuming that FP-SP is equal to
500 // |fp_to_sp_delta|.
501 Location ToSpRelative(intptr_t fp_to_sp_delta) const;
502
503 // If the given location is FP relative stack location this returns
504 // corresponding SP relative location assuming that SP is equal to SP
505 // at the entry (i.e. no additional frame was setup on the stack).
507
508 // If the given location is FP relative stack location this returns
509 // corresponding SP relative location assuming that SP is equal to SP
510 // of caller before the call.
512
513 const char* Name() const;
514 void PrintTo(BaseTextBuffer* f) const;
515 void Print() const;
516 const char* ToCString() const;
517
518 // Compare two locations.
519 bool Equals(Location other) const { return value_ == other.value_; }
520
521 // If current location is constant might return something that
522 // is not equal to any Kind.
523 Kind kind() const { return KindField::decode(value_); }
524
525 Location Copy() const;
526
527 void Write(FlowGraphSerializer* s) const;
529
530 private:
531 explicit Location(uword value) : value_(value) {}
532
533 void set_stack_index(intptr_t index) {
535 value_ = PayloadField::update(
536 StackIndexField::update(EncodeStackIndex(index), payload()), value_);
537 }
538
539 void set_base_reg(Register reg) {
542 value_);
543 }
544
545 Location(Kind kind, uword payload)
546 : value_(KindField::encode(kind) | PayloadField::encode(payload)) {}
547
548 uword payload() const { return PayloadField::decode(value_); }
549
550 class KindField : public BitField<uword, Kind, kKindBitsPos, kKindBitsSize> {
551 };
552 class PayloadField
553 : public BitField<uword, uword, kPayloadBitsPos, kPayloadBitsSize> {};
554
555 // Layout for kUnallocated locations payload.
556 typedef BitField<uword, Policy, 0, 3> PolicyField;
557
558// Layout for stack slots.
559#if defined(ARCH_IS_64_BIT)
560 static constexpr intptr_t kBitsForBaseReg = 6;
561#else
562 static constexpr intptr_t kBitsForBaseReg = 5;
563#endif
564 static constexpr intptr_t kBitsForStackIndex =
565 kPayloadBitsSize - kBitsForBaseReg;
566 class StackSlotBaseField
567 : public BitField<uword, Register, 0, kBitsForBaseReg> {};
568 class StackIndexField
569 : public BitField<uword, intptr_t, kBitsForBaseReg, kBitsForStackIndex> {
570 };
571 COMPILE_ASSERT(1 << kBitsForBaseReg >= kNumberOfCpuRegisters);
572
573 static constexpr intptr_t kStackIndexBias = static_cast<intptr_t>(1)
574 << (kBitsForStackIndex - 1);
575
576 // Location either contains kind and payload fields or a tagged handle for
577 // a constant locations. Values of enumeration Kind are selected in such a
578 // way that none of them can be interpreted as a kConstant tag.
579 uword value_;
580};
581
585// Constants.
588 Value* value,
589 intptr_t min_value = compiler::target::kSmiMin,
590 intptr_t max_value = compiler::target::kSmiMax);
593 Value* value,
594 intptr_t min_value = compiler::target::kSmiMin,
595 intptr_t max_value = compiler::target::kSmiMax);
599
601 Definition* def,
602 intptr_t* cpu_reg_slots,
603 intptr_t* fpu_reg_slots);
604
605// Return a memory operand for stack slot locations.
606compiler::Address LocationToStackSlotAddress(Location loc);
607
609 public:
611 for (intptr_t i = 0; i < kPairLength; i++) {
612 ASSERT(locations_[i].IsInvalid());
613 }
614 }
615
616 intptr_t length() const { return kPairLength; }
617
618 Location At(intptr_t i) const {
619 ASSERT(i >= 0);
620 ASSERT(i < kPairLength);
621 return locations_[i];
622 }
623
624 void SetAt(intptr_t i, Location loc) {
625 ASSERT(i >= 0);
626 ASSERT(i < kPairLength);
627 locations_[i] = loc;
628 }
629
630 Location* SlotAt(intptr_t i) {
631 ASSERT(i >= 0);
632 ASSERT(i < kPairLength);
633 return &locations_[i];
634 }
635
636 private:
637 static constexpr intptr_t kPairLength = 2;
638 Location locations_[kPairLength];
639};
640
641template <typename T>
642class SmallSet {
643 public:
644 SmallSet() : data_(0) {}
645
646 explicit SmallSet(uintptr_t data) : data_(data) {}
647
648 bool Contains(T value) const { return (data_ & ToMask(value)) != 0; }
649
650 void Add(T value) { data_ |= ToMask(value); }
651
652 void Remove(T value) { data_ &= ~ToMask(value); }
653
654 bool IsEmpty() const { return data_ == 0; }
655
656 void Clear() { data_ = 0; }
657
658 uintptr_t data() const { return data_; }
659
660 private:
661 static uintptr_t ToMask(T value) {
662 ASSERT(static_cast<uintptr_t>(value) < (kWordSize * kBitsPerByte));
663 return static_cast<uintptr_t>(1) << static_cast<uintptr_t>(value);
664 }
665
666 uintptr_t data_;
667};
668
669class RegisterSet : public ValueObject {
670 public:
672 : cpu_registers_(), untagged_cpu_registers_(), fpu_registers_() {
675 }
676
677 explicit RegisterSet(uintptr_t cpu_register_mask, uintptr_t fpu_register_mask)
678 : RegisterSet() {
679 AddTaggedRegisters(cpu_register_mask, fpu_register_mask);
680 }
681
682 void AddAllNonReservedRegisters(bool include_fpu_registers) {
683 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; --i) {
684 if ((kReservedCpuRegisters & (1 << i)) != 0u) continue;
685 Add(Location::RegisterLocation(static_cast<Register>(i)));
686 }
687
688 if (include_fpu_registers) {
689 for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; --i) {
691 }
692 }
693 }
694
695 // Adds all registers which don't have a special purpose (e.g. FP, SP, PC,
696 // CSP, etc.).
698 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; --i) {
699 Register reg = static_cast<Register>(i);
700 if (reg == FPREG || reg == SPREG) continue;
701#if defined(TARGET_ARCH_ARM)
702 if (reg == PC) continue;
703#elif defined(TARGET_ARCH_ARM64)
704 if (reg == R31) continue;
705#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
706 if (reg == ZR || reg == TP || reg == GP) continue;
707#endif
709 }
710
711 for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; --i) {
713 }
714 }
715
717 // All (native) arguments are passed on the stack in IA32.
718#if !defined(TARGET_ARCH_IA32)
719 for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
720 const Register reg = static_cast<Register>(i);
721 if (IsArgumentRegister(reg)) {
723 }
724 }
725 for (intptr_t i = 0; i < kNumberOfFpuRegisters; ++i) {
726 const FpuRegister reg = static_cast<FpuRegister>(i);
727 if (IsFpuArgumentRegister(reg)) {
729 }
730 }
731#endif
732 }
733
734 void AddTaggedRegisters(uintptr_t cpu_register_mask,
735 uintptr_t fpu_register_mask) {
736 for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
737 if (Utils::TestBit(cpu_register_mask, i)) {
738 const Register reg = static_cast<Register>(i);
740 }
741 }
742 for (intptr_t i = 0; i < kNumberOfFpuRegisters; ++i) {
743 if (Utils::TestBit(fpu_register_mask, i)) {
744 const FpuRegister reg = static_cast<FpuRegister>(i);
746 }
747 }
748 }
749
750 void AddRegister(Register reg, Representation rep = kTagged) {
752 }
753
754 void Add(Location loc, Representation rep = kTagged) {
755 if (loc.IsRegister()) {
756 cpu_registers_.Add(loc.reg());
757 if (rep != kTagged) {
758 // CPU register contains an untagged value.
759 MarkUntagged(loc);
760 }
761 } else if (loc.IsFpuRegister()) {
762 fpu_registers_.Add(loc.fpu_reg());
763 }
764 }
765
766 void Remove(Location loc) {
767 if (loc.IsRegister()) {
768 cpu_registers_.Remove(loc.reg());
769 } else if (loc.IsFpuRegister()) {
770 fpu_registers_.Remove(loc.fpu_reg());
771 }
772 }
773
774 bool Contains(Location loc) {
775 if (loc.IsRegister()) {
776 return ContainsRegister(loc.reg());
777 } else if (loc.IsFpuRegister()) {
778 return ContainsFpuRegister(loc.fpu_reg());
779 } else {
780 UNREACHABLE();
781 return false;
782 }
783 }
784
785 void DebugPrint();
786
788 ASSERT(loc.IsRegister());
789 untagged_cpu_registers_.Add(loc.reg());
790 }
791
792 bool HasUntaggedValues() const {
793 return !untagged_cpu_registers_.IsEmpty() || !fpu_registers_.IsEmpty();
794 }
795
796 bool IsTagged(Register reg) const {
797 return !untagged_cpu_registers_.Contains(reg);
798 }
799
800 bool ContainsRegister(Register reg) const {
801 return cpu_registers_.Contains(reg);
802 }
803
804 bool ContainsFpuRegister(FpuRegister fpu_reg) const {
805 return fpu_registers_.Contains(fpu_reg);
806 }
807
808 intptr_t CpuRegisterCount() const { return RegisterCount(cpu_registers()); }
809 intptr_t FpuRegisterCount() const { return RegisterCount(fpu_registers()); }
810
811 bool IsEmpty() const {
812 return CpuRegisterCount() == 0 && FpuRegisterCount() == 0;
813 }
814
815 static intptr_t RegisterCount(intptr_t registers);
816 static bool Contains(uintptr_t register_set, intptr_t reg) {
817 return (register_set & (static_cast<uintptr_t>(1) << reg)) != 0;
818 }
819
820 uintptr_t cpu_registers() const { return cpu_registers_.data(); }
821 uintptr_t fpu_registers() const { return fpu_registers_.data(); }
822
823 void Clear() {
824 cpu_registers_.Clear();
825 fpu_registers_.Clear();
826 untagged_cpu_registers_.Clear();
827 }
828
829 void Write(FlowGraphSerializer* s) const;
831
832 private:
833 SmallSet<Register> cpu_registers_;
834 SmallSet<Register> untagged_cpu_registers_;
835 SmallSet<FpuRegister> fpu_registers_;
836
838};
839
840// Specification of locations for inputs and output.
842 public:
844 // Used registers must be reserved as tmp.
846 // Registers have been saved and can be used without reservation.
848 // Registers will be saved by the callee.
850 // Used registers must be reserved as tmp.
852 // Registers used to invoke shared stub must be reserved as tmp.
854 // Location is a native leaf call so any register not in the native ABI
855 // callee-save (or input/output/tmp) set might get clobbered.
857 };
858
859 LocationSummary(Zone* zone,
860 intptr_t input_count,
861 intptr_t temp_count,
862 LocationSummary::ContainsCall contains_call);
863
864 intptr_t input_count() const { return num_inputs_; }
865
866 Location in(intptr_t index) const {
867 ASSERT(index >= 0);
868 ASSERT(index < num_inputs_);
869 return input_locations_[index];
870 }
871
872 Location* in_slot(intptr_t index) {
873 ASSERT(index >= 0);
874 ASSERT(index < num_inputs_);
875 return &input_locations_[index];
876 }
877
878 void set_in(intptr_t index, Location loc);
879
880 intptr_t temp_count() const { return num_temps_; }
881
882 Location temp(intptr_t index) const {
883 ASSERT(index >= 0);
884 ASSERT(index < num_temps_);
885 return temp_locations_[index];
886 }
887
888 Location* temp_slot(intptr_t index) {
889 ASSERT(index >= 0);
890 ASSERT(index < num_temps_);
891 return &temp_locations_[index];
892 }
893
894 void set_temp(intptr_t index, Location loc) {
895 ASSERT(index >= 0);
896 ASSERT(index < num_temps_);
898 temp_locations_[index] = loc;
899 }
900
901 intptr_t output_count() const { return 1; }
902
903 Location out(intptr_t index) const {
904 ASSERT(index == 0);
905 return output_location_;
906 }
907
908 Location* out_slot(intptr_t index) {
909 ASSERT(index == 0);
910 return &output_location_;
911 }
912
913 void set_out(intptr_t index, Location loc);
914
915 const BitmapBuilder& stack_bitmap() { return EnsureStackBitmap(); }
916 void SetStackBit(intptr_t index) { EnsureStackBitmap().Set(index, true); }
917
918 bool always_calls() const {
919 return contains_call_ == kCall || contains_call_ == kCallCalleeSafe;
920 }
921
922 bool callee_safe_call() const { return contains_call_ == kCallCalleeSafe; }
923
924 bool can_call() { return contains_call_ != kNoCall; }
925
926 bool HasCallOnSlowPath() { return can_call() && !always_calls(); }
927
929 return contains_call_ == kCallOnSharedSlowPath;
930 }
931
932 bool native_leaf_call() const { return contains_call_ == kNativeLeafCall; }
933
934 void PrintTo(BaseTextBuffer* f) const;
935
936 static LocationSummary* Make(Zone* zone,
937 intptr_t input_count,
939 ContainsCall contains_call);
940
941 RegisterSet* live_registers() { return &live_registers_; }
942
943#if defined(DEBUG)
944 // Debug only verification that ensures that writable registers are correctly
945 // preserved on the slow path.
946 void DiscoverWritableInputs();
947 void CheckWritableInputs();
948#endif
949
950 void Write(FlowGraphSerializer* s) const;
952
953 private:
954 BitmapBuilder& EnsureStackBitmap() {
955 if (stack_bitmap_ == nullptr) {
956 stack_bitmap_ = new BitmapBuilder();
957 }
958 return *stack_bitmap_;
959 }
960
961 const intptr_t num_inputs_;
962 Location* input_locations_;
963 const intptr_t num_temps_;
964 Location* temp_locations_;
965 Location output_location_;
966
967 BitmapBuilder* stack_bitmap_;
968
969 const ContainsCall contains_call_;
970 RegisterSet live_registers_;
971
972#if defined(DEBUG)
973 intptr_t writable_inputs_;
974#endif
975};
976
977} // namespace dart
978
979#endif // RUNTIME_VM_COMPILER_BACKEND_LOCATIONS_H_
static void encode(uint8_t output[16], const uint32_t input[4])
Definition SkMD5.cpp:240
SweepLineTestingPeer TP
#define UNREACHABLE()
Definition assert.h:248
#define COMPILE_ASSERT(expr)
Definition assert.h:339
static constexpr T decode(S value)
Definition bitfield.h:173
static constexpr uword update(uword value, uword original)
Definition bitfield.h:190
static constexpr S encode(T value)
Definition bitfield.h:167
void Set(intptr_t bit_offset, bool value)
Definition bitmap.cc:44
Location * in_slot(intptr_t index)
Definition locations.h:872
Location temp(intptr_t index) const
Definition locations.h:882
void SetStackBit(intptr_t index)
Definition locations.h:916
bool callee_safe_call() const
Definition locations.h:922
void Write(FlowGraphSerializer *s) const
Location out(intptr_t index) const
Definition locations.h:903
Location * temp_slot(intptr_t index)
Definition locations.h:888
const BitmapBuilder & stack_bitmap()
Definition locations.h:915
static LocationSummary * Make(Zone *zone, intptr_t input_count, Location out, ContainsCall contains_call)
Definition locations.cc:187
intptr_t input_count() const
Definition locations.h:864
bool native_leaf_call() const
Definition locations.h:932
void set_temp(intptr_t index, Location loc)
Definition locations.h:894
intptr_t output_count() const
Definition locations.h:901
intptr_t temp_count() const
Definition locations.h:880
RegisterSet * live_registers()
Definition locations.h:941
void set_out(intptr_t index, Location loc)
Definition locations.cc:232
bool always_calls() const
Definition locations.h:918
bool call_on_shared_slow_path() const
Definition locations.h:928
Location * out_slot(intptr_t index)
Definition locations.h:908
Location in(intptr_t index) const
Definition locations.h:866
void set_in(intptr_t index, Location loc)
Definition locations.cc:205
void PrintTo(BaseTextBuffer *f) const
Definition locations.cc:554
static Location StackSlot(intptr_t stack_index, Register base)
Definition locations.h:447
static Location MachineRegisterLocation(Kind kind, intptr_t reg)
Definition locations.h:425
bool IsInvalid() const
Definition locations.h:289
void Print() const
Definition locations.cc:452
Location ToCallerSpRelative() const
Definition locations.cc:265
static Location NoLocation()
Definition locations.h:387
static Location QuadStackSlot(intptr_t stack_index, Register base)
Definition locations.h:469
static Location SameAsFirstInput()
Definition locations.h:382
const char * Name() const
Definition locations.cc:377
bool IsFpuRegister() const
Definition locations.h:414
ConstantInstr * constant_instruction() const
Definition locations.h:309
bool IsRegister() const
Definition locations.h:402
void Write(FlowGraphSerializer *s) const
static Location RequiresStack()
Definition locations.h:354
intptr_t ToStackSlotOffset() const
Definition locations.cc:369
Location ToEntrySpRelative() const
Definition locations.cc:258
bool IsDoubleStackSlot() const
Definition locations.h:467
Register reg() const
Definition locations.h:404
static Location FpuRegisterLocation(FpuRegister reg)
Definition locations.h:410
const char * ToCString() const
Definition locations.cc:445
static Location DoubleStackSlot(intptr_t stack_index, Register base)
Definition locations.h:458
static uword EncodeStackIndex(intptr_t stack_index)
Definition locations.h:441
intptr_t stack_index() const
Definition locations.h:485
Policy policy() const
Definition locations.h:389
Location & operator=(const Location &other)
Definition locations.h:284
static bool IsMachineRegisterKind(Kind kind)
Definition locations.h:421
intptr_t pair_index() const
Definition locations.h:304
Location Copy() const
Definition locations.cc:468
Location Component(intptr_t i) const
Definition locations.cc:285
static Location WritableRegister()
Definition locations.h:376
Kind kind() const
Definition locations.h:523
bool IsConstant() const
Definition locations.h:292
bool IsRegisterBeneficial()
Definition locations.h:343
static Location UnallocatedLocation(Policy policy)
Definition locations.h:347
bool IsQuadStackSlot() const
Definition locations.h:478
Register base_reg() const
Definition locations.h:480
static Location Read(FlowGraphDeserializer *d)
Location(const Location &other)
Definition locations.h:282
static Location RegisterLocation(Register reg)
Definition locations.h:398
static Location PrefersRegister()
Definition locations.h:358
static Location Any()
Definition locations.h:352
PairLocation * AsPairLocation() const
Definition locations.cc:280
bool Equals(Location other) const
Definition locations.h:519
static Location RequiresRegister()
Definition locations.h:365
bool IsPairLocation() const
Definition locations.h:316
void PrintTo(BaseTextBuffer *f) const
Definition locations.cc:420
bool IsUnallocated() const
Definition locations.h:341
bool IsMachineRegister() const
Definition locations.h:434
static Location RequiresFpuRegister()
Definition locations.h:369
bool IsStackSlot() const
Definition locations.h:456
FpuRegister fpu_reg() const
Definition locations.h:416
const Object & constant() const
Definition locations.cc:373
Location ToSpRelative(intptr_t fp_to_sp_delta) const
Definition locations.cc:240
bool HasStackIndex() const
Definition locations.h:491
intptr_t register_code() const
Definition locations.h:436
static Location Constant(const ConstantInstr *obj, int pair_index=0)
Definition locations.h:294
void SetAt(intptr_t i, Location loc)
Definition locations.h:624
Location * SlotAt(intptr_t i)
Definition locations.h:630
Location At(intptr_t i) const
Definition locations.h:618
intptr_t length() const
Definition locations.h:616
void Write(FlowGraphSerializer *s) const
static bool Contains(uintptr_t register_set, intptr_t reg)
Definition locations.h:816
bool IsEmpty() const
Definition locations.h:811
intptr_t FpuRegisterCount() const
Definition locations.h:809
bool ContainsFpuRegister(FpuRegister fpu_reg) const
Definition locations.h:804
uintptr_t fpu_registers() const
Definition locations.h:821
void AddAllGeneralRegisters()
Definition locations.h:697
void MarkUntagged(Location loc)
Definition locations.h:787
uintptr_t cpu_registers() const
Definition locations.h:820
RegisterSet(uintptr_t cpu_register_mask, uintptr_t fpu_register_mask)
Definition locations.h:677
void AddRegister(Register reg, Representation rep=kTagged)
Definition locations.h:750
void AddAllArgumentRegisters()
Definition locations.h:716
bool HasUntaggedValues() const
Definition locations.h:792
static intptr_t RegisterCount(intptr_t registers)
Definition locations.cc:142
bool Contains(Location loc)
Definition locations.h:774
void AddTaggedRegisters(uintptr_t cpu_register_mask, uintptr_t fpu_register_mask)
Definition locations.h:734
void Add(Location loc, Representation rep=kTagged)
Definition locations.h:754
intptr_t CpuRegisterCount() const
Definition locations.h:808
void AddAllNonReservedRegisters(bool include_fpu_registers)
Definition locations.h:682
bool ContainsRegister(Register reg) const
Definition locations.h:800
bool IsTagged(Register reg) const
Definition locations.h:796
void Remove(Location loc)
Definition locations.h:766
bool Contains(T value) const
Definition locations.h:648
void Add(T value)
Definition locations.h:650
bool IsEmpty() const
Definition locations.h:654
uintptr_t data() const
Definition locations.h:658
void Remove(T value)
Definition locations.h:652
SmallSet(uintptr_t data)
Definition locations.h:646
static constexpr bool TestBit(T mask, size_t position)
Definition utils.h:549
#define ASSERT(E)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
struct MyStruct s
uint8_t value
#define REP_SIZEOF_CLAUSE(name, __, ___, type)
#define FOR_EACH_REPRESENTATION_KIND(M)
Definition locations.h:61
#define FOR_EACH_INTEGER_REPRESENTATION_KIND(M)
Definition locations.h:31
#define REP_IS_UNSIGNED_CLAUSE(name, __, unsigned, ___)
#define FOR_EACH_UNBOXED_REPRESENTATION_KIND(M)
Definition locations.h:42
#define FOR_EACH_SIMPLE_REPRESENTATION_KIND(M)
Definition locations.h:53
#define REP_IN_SET_CLAUSE(name, __, ___, ____)
Definition locations.h:87
#define DECLARE_REPRESENTATION(name, __, ___, ____)
Definition locations.h:67
Location LocationAnyOrConstant(Value *value)
Definition locations.cc:357
Location LocationRegisterOrConstant(Value *value)
Definition locations.cc:289
constexpr intptr_t kBitsPerWord
Definition globals.h:514
static constexpr Representation kUnboxedUword
Definition locations.h:171
const RegList kReservedCpuRegisters
static constexpr intptr_t kMaxLocationCount
Definition locations.h:73
Location LocationExceptionLocation()
Definition locations.cc:484
int32_t classid_t
Definition globals.h:524
Representation
Definition locations.h:66
@ kNumRepresentations
Definition locations.h:70
constexpr intptr_t kBitsPerByte
Definition globals.h:463
intptr_t LocationCount(Representation rep)
Definition locations.h:75
uintptr_t uword
Definition globals.h:501
@ kNumberOfCpuRegisters
Location LocationFixedRegisterOrConstant(Value *value, Register reg)
Definition locations.cc:339
const int kNumberOfFpuRegisters
Location LocationWritableRegisterOrSmiConstant(Value *value, intptr_t min_value, intptr_t max_value)
Definition locations.cc:322
Location LocationArgumentsDescriptorLocation()
Definition locations.cc:480
Location LocationRemapForSlowPath(Location loc, Definition *def, intptr_t *cpu_reg_slots, intptr_t *fpu_reg_slots)
Definition locations.cc:492
static constexpr bool IsArgumentRegister(Register reg)
Definition constants.h:77
const Register FPREG
const intptr_t cid
static constexpr bool IsFpuArgumentRegister(FpuRegister reg)
Definition constants.h:81
static constexpr Representation kUnboxedAddress
Definition locations.h:182
compiler::Address LocationToStackSlotAddress(Location loc)
Definition locations.cc:365
Location LocationStackTraceLocation()
Definition locations.cc:488
constexpr intptr_t kWordSize
Definition globals.h:509
Location LocationWritableRegisterOrConstant(Value *value)
Definition locations.cc:314
static constexpr Representation kUnboxedIntPtr
Definition locations.h:176
static constexpr Representation kUnboxedWord
Definition locations.h:164
Location LocationFixedRegisterOrSmiConstant(Value *value, Register reg)
Definition locations.cc:348
Location LocationRegisterOrSmiConstant(Value *value, intptr_t min_value, intptr_t max_value)
Definition locations.cc:297
const Register SPREG
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition globals.h:581
#define T
static constexpr size_t ValueSize(Representation rep)
Definition locations.h:112
static constexpr bool IsUnboxedInteger(Representation rep)
Definition locations.h:92
static bool IsRepresentable(Representation rep, int64_t value)
Definition locations.cc:72
static int64_t MaxValue(Representation rep)
Definition locations.cc:62
static compiler::OperandSize OperandSize(Representation rep)
Definition locations.cc:16
static int64_t MinValue(Representation rep)
Definition locations.cc:49
static constexpr bool IsUnboxed(Representation rep)
Definition locations.h:101
static const char * ToCString(Representation rep)
Definition locations.cc:129
static bool IsUnsignedInteger(Representation rep)
Definition locations.h:126
static Representation RepresentationOfArrayElement(classid_t cid)
Definition locations.cc:79