@@ -44,16 +44,21 @@ class DeclRefExpr;
44
44
class FloatLiteralExpr ;
45
45
class FuncDecl ;
46
46
class IntegerLiteralExpr ;
47
+ class SingleValueInstruction ;
48
+ class MultipleValueInstruction ;
49
+ class MultipleValueInstructionResult ;
47
50
class NonValueInstruction ;
48
51
class SILBasicBlock ;
49
52
class SILBuilder ;
50
53
class SILDebugLocation ;
51
54
class SILDebugScope ;
52
55
class SILFunction ;
53
56
class SILGlobalVariable ;
57
+ class SILInstructionResultArray ;
54
58
class SILOpenedArchetypesState ;
55
59
class SILType ;
56
60
class SILArgument ;
61
+ class SILUndef ;
57
62
class Stmt ;
58
63
class StringLiteralExpr ;
59
64
class Substitution ;
@@ -96,13 +101,37 @@ StringRef getSILInstructionName(SILInstructionKind Kind);
96
101
// /
97
102
// / *NOTE* Most of this defined out of line further down in the file to work
98
103
// / around forward declaration issues.
104
+ // /
105
+ // / *NOTE* The reason why this does not store the size of the stored element is
106
+ // / that just from the number of elements we can infer the size of each element
107
+ // / due to the restricted problem space. Specificially:
108
+ // /
109
+ // / 1. Size == 0 implies nothing is stored and thus element size is irrelevent.
110
+ // / 2. Size == 1 implies we either had a single value instruction or a multiple
111
+ // / value instruction, but no matter what instruction we had, we are going to
112
+ // / store the results at the same starting location so element size is
113
+ // / irrelevent.
114
+ // / 3. Size > 1 implies we must be storing multiple value instruction results
115
+ // / implying that the size of each stored element must be
116
+ // / sizeof(MultipleValueInstructionResult).
117
+ // /
118
+ // / If we ever allow for subclasses of MultipleValueInstructionResult of
119
+ // / different sizes, we will need to store a stride into
120
+ // / SILInstructionResultArray. We always assume all results are the same
121
+ // / subclass of MultipleValueInstructionResult.
99
122
class SILInstructionResultArray {
123
+ friend class MultipleValueInstruction ;
124
+
125
+ // / Byte pointer to our data. nullptr for empty arrays.
100
126
const uint8_t *Pointer;
127
+
128
+ // / The number of stored elements.
101
129
unsigned Size;
102
130
103
131
public:
104
132
SILInstructionResultArray () : Pointer(nullptr ), Size(0 ) {}
105
133
SILInstructionResultArray (const SingleValueInstruction *SVI);
134
+ SILInstructionResultArray (ArrayRef<MultipleValueInstructionResult> MVResults);
106
135
107
136
SILInstructionResultArray (const SILInstructionResultArray &Other) = default ;
108
137
SILInstructionResultArray &
@@ -141,6 +170,18 @@ class SILInstructionResultArray {
141
170
bool hasSameTypes (const SILInstructionResultArray &rhs);
142
171
143
172
private:
173
+ // / Return the first element of the array. Asserts if the array is empty.
174
+ // /
175
+ // / Please do not use this outside of this class. It is only meant to speedup
176
+ // / MultipleValueInstruction::getIndexOfResult(SILValue).
177
+ const ValueBase *front () const ;
178
+
179
+ // / Return the last element of the array. Asserts if the array is empty.
180
+ // /
181
+ // / Please do not use this outside of this class. It is only meant to speedup
182
+ // / MultipleValueInstruction::getIndexOfResult(SILValue).
183
+ const ValueBase *back () const ;
184
+
144
185
// / Return the offset 1 past the end of the array or None if we are not
145
186
// / actually storing anything.
146
187
Optional<unsigned > getStartOffset () const {
@@ -188,6 +229,17 @@ class SILInstructionResultArray::iterator
188
229
return copy;
189
230
}
190
231
232
+ iterator &operator --() {
233
+ --Index.getValue ();
234
+ return *this ;
235
+ }
236
+
237
+ iterator operator --(int ) {
238
+ iterator copy = *this ;
239
+ --Index.getValue ();
240
+ return copy;
241
+ }
242
+
191
243
friend bool operator ==(iterator lhs, iterator rhs) {
192
244
assert (lhs.Parent .Pointer == rhs.Parent .Pointer );
193
245
return lhs.Index == rhs.Index ;
@@ -256,7 +308,8 @@ class SILInstruction
256
308
257
309
protected:
258
310
SILInstruction (SILInstructionKind kind, SILDebugLocation DebugLoc)
259
- : SILNode(SILNodeKind(kind), SILNodeStorageLocation::Instruction),
311
+ : SILNode(SILNodeKind(kind), SILNodeStorageLocation::Instruction,
312
+ IsRepresentative::Yes),
260
313
ParentBB (nullptr ), Location(DebugLoc) {
261
314
NumCreatedInstructions++;
262
315
}
@@ -303,12 +356,12 @@ class SILInstruction
303
356
}
304
357
305
358
SILNode *getCanonicalSILNodeInObject () {
306
- assert (isCanonicalSILNodeInObject () &&
359
+ assert (isRepresentativeSILNodeInObject () &&
307
360
" the SILInstruction subobject is always canonical" );
308
361
return this ;
309
362
}
310
363
const SILNode *getCanonicalSILNodeInObject () const {
311
- assert (isCanonicalSILNodeInObject () &&
364
+ assert (isRepresentativeSILNodeInObject () &&
312
365
" the SILInstruction subobject is always canonical" );
313
366
return this ;
314
367
}
@@ -614,9 +667,8 @@ class SingleValueInstruction : public SILInstruction, public ValueBase {
614
667
public:
615
668
SingleValueInstruction (SILInstructionKind kind, SILDebugLocation loc,
616
669
SILType type)
617
- : SILInstruction(kind, loc),
618
- ValueBase (ValueKind(kind), type) {
619
- }
670
+ : SILInstruction(kind, loc),
671
+ ValueBase (ValueKind(kind), type, IsRepresentative::No) {}
620
672
621
673
using SILInstruction::getFunction;
622
674
using SILInstruction::getModule;
@@ -636,12 +688,12 @@ class SingleValueInstruction : public SILInstruction, public ValueBase {
636
688
}
637
689
638
690
SILNode *getCanonicalSILNodeInObject () {
639
- assert (SILInstruction::isCanonicalSILNodeInObject () &&
691
+ assert (SILInstruction::isRepresentativeSILNodeInObject () &&
640
692
" the SILInstruction subobject is always canonical" );
641
693
return static_cast <SILInstruction*>(this );
642
694
}
643
695
const SILNode *getCanonicalSILNodeInObject () const {
644
- assert (SILInstruction::isCanonicalSILNodeInObject () &&
696
+ assert (SILInstruction::isRepresentativeSILNodeInObject () &&
645
697
" the SILInstruction subobject is always canonical" );
646
698
return static_cast <const SILInstruction*>(this );
647
699
}
@@ -693,6 +745,182 @@ inline SingleValueInstruction *SILNode::castToSingleValueInstruction() {
693
745
inst->getKind () <= SILInstructionKind::Last_##ID; \
694
746
}
695
747
748
+ // / A value base result of a multiple value instruction.
749
+ // /
750
+ // / *NOTE* We want this to be a pure abstract class that does not add /any/ size
751
+ // / to subclasses.
752
+ class MultipleValueInstructionResult : public ValueBase {
753
+ public:
754
+ // / Create a new multiple value instruction result.
755
+ // /
756
+ // / \arg subclassDeltaOffset This is the delta offset in our parent object's
757
+ // / layout in between the end of the MultipleValueInstruction object and the
758
+ // / end of the specific subclass object.
759
+ // /
760
+ // / *NOTE* subclassDeltaOffset must be use only 5 bits. This gives us to
761
+ // / support subclasses up to 32 bytes in size. We can scavange up to 6 more
762
+ // / bits from ValueBase if this is not large enough.
763
+ MultipleValueInstructionResult (ValueKind valueKind, unsigned index,
764
+ SILType type,
765
+ ValueOwnershipKind ownershipKind);
766
+
767
+ // / Return the parent instruction of this result.
768
+ MultipleValueInstruction *getParent ();
769
+
770
+ const MultipleValueInstruction *getParent () const {
771
+ return const_cast <MultipleValueInstructionResult *>(this )->getParent ();
772
+ }
773
+
774
+ unsigned getIndex () const ;
775
+
776
+ // / Get the ownership kind assigned to this result by its parent.
777
+ // /
778
+ // / This is stored in the bottom 3 bits of ValueBase's subclass data.
779
+ ValueOwnershipKind getOwnershipKind () const ;
780
+
781
+ SILNode *getCanonicalSILNodeInObject ();
782
+ const SILNode *getCanonicalSILNodeInObject () const ;
783
+
784
+ static bool classof (const SILInstruction *) = delete;
785
+ static bool classof (const SILUndef *) = delete;
786
+ static bool classof (const SILArgument *) = delete;
787
+ static bool classof (const MultipleValueInstructionResult *) { return true ; }
788
+ static bool classof (const SILNode *node) {
789
+ // This is an abstract class without anything implementing it right now, so
790
+ // just return false. This will be fixed in a subsequent commit.
791
+ return false ;
792
+ }
793
+
794
+ protected:
795
+ // / Set the ownership kind assigned to this result.
796
+ // /
797
+ // / This is stored in SILNode in the subclass data.
798
+ void setOwnershipKind (ValueOwnershipKind Kind);
799
+
800
+ // / Set the index of this result.
801
+ void setIndex (unsigned NewIndex);
802
+
803
+ static constexpr unsigned NumIndexBits = 24 ;
804
+ static constexpr uint64_t IndexMask = (uint64_t (1 ) << 24 ) - 1 ;
805
+ static constexpr uint64_t IndexBitOffset = ValueOwnershipKind::NumBits;
806
+ };
807
+
808
+ // / An instruction that may produce an arbitrary number of values.
809
+ class MultipleValueInstruction : public SILInstruction {
810
+ friend class SILInstruction ;
811
+ friend class SILInstructionResultArray ;
812
+
813
+ protected:
814
+ MultipleValueInstruction (SILInstructionKind kind, SILDebugLocation loc)
815
+ : SILInstruction(kind, loc) {}
816
+
817
+ public:
818
+ void operator delete (void *Ptr, size_t )SWIFT_DELETE_OPERATOR_DELETED;
819
+
820
+ MultipleValueInstruction *clone (SILInstruction *insertPt = nullptr ) {
821
+ return cast<MultipleValueInstruction>(SILInstruction::clone (insertPt));
822
+ }
823
+
824
+ SILValue getResult (unsigned Index) const { return getResults ()[Index]; }
825
+
826
+ // / Return the index of \p Target if it is a result in the given
827
+ // / MultipleValueInstructionResult. Otherwise, returns None.
828
+ Optional<unsigned > getIndexOfResult (SILValue Target) const ;
829
+
830
+ unsigned getNumResults () const { return getResults ().size (); }
831
+
832
+ static bool classof (const SILNode *node) {
833
+ // This is an abstract class without anything implementing it right now, so
834
+ // just return false. This will be fixed in a subsequent commit.
835
+ return false ;
836
+ }
837
+ };
838
+
839
+ // / A utility mixin class that must be used by /all/ subclasses of
840
+ // / MultipleValueInstruction to store their results.
841
+ template <SILInstructionKind Kind, typename Derived, typename DerivedResult,
842
+ typename ... OtherTrailingTypes>
843
+ class MultipleValueInstructionTrailingObjects
844
+ : protected llvm::TrailingObjects<Derived, MultipleValueInstruction *,
845
+ DerivedResult, OtherTrailingTypes...> {
846
+ static_assert (LLVM_IS_FINAL(DerivedResult),
847
+ " Expected DerivedResult to be final" );
848
+ static_assert (
849
+ std::is_base_of<MultipleValueInstructionResult, DerivedResult>::value,
850
+ " Expected DerivedResult to be a subclass of "
851
+ " MultipleValueInstructionResult" );
852
+ static_assert (sizeof (MultipleValueInstructionResult) == sizeof (DerivedResult),
853
+ " Expected DerivedResult to be the same size as a "
854
+ " MultipleValueInstructionResult" );
855
+
856
+ protected:
857
+ using TrailingObjects =
858
+ llvm::TrailingObjects<Derived, MultipleValueInstruction *, DerivedResult,
859
+ OtherTrailingTypes...>;
860
+ friend TrailingObjects;
861
+
862
+ using TrailingObjects::totalSizeToAlloc;
863
+ using TrailingObjects::getTrailingObjects;
864
+
865
+ unsigned NumResults;
866
+
867
+ size_t numTrailingObjects (typename TrailingObjects::template OverloadToken<
868
+ MultipleValueInstruction *>) const {
869
+ return 1 ;
870
+ }
871
+
872
+ size_t numTrailingObjects (
873
+ typename TrailingObjects::template OverloadToken<DerivedResult>) const {
874
+ return NumResults;
875
+ }
876
+
877
+ template <typename ... Args>
878
+ MultipleValueInstructionTrailingObjects (
879
+ Derived *Parent, ArrayRef<SILType> Types,
880
+ ArrayRef<ValueOwnershipKind> OwnershipKinds, Args &&... OtherArgs)
881
+ : NumResults(Types.size()) {
882
+
883
+ // If we do not have any results, then we do not need to initialize even the
884
+ // parent pointer since we do not have any results that will attempt to get
885
+ // our parent pointer.
886
+ if (!NumResults)
887
+ return ;
888
+
889
+ auto **ParentPtr =
890
+ this ->template getTrailingObjects <MultipleValueInstruction *>();
891
+ *ParentPtr = static_cast <MultipleValueInstruction *>(Parent);
892
+
893
+ auto *DataPtr = this ->template getTrailingObjects <DerivedResult>();
894
+ for (unsigned i : range (NumResults)) {
895
+ ::new (&DataPtr[i]) DerivedResult (i, Types[i], OwnershipKinds[i],
896
+ std::forward<Args>(OtherArgs)...);
897
+ assert (DataPtr[i].getParent () == Parent &&
898
+ " Failed to setup parent reference correctly?!" );
899
+ }
900
+ }
901
+
902
+ // Destruct the Derived Results.
903
+ ~MultipleValueInstructionTrailingObjects () {
904
+ if (!NumResults)
905
+ return ;
906
+ auto *DataPtr = this ->template getTrailingObjects <DerivedResult>();
907
+ for (unsigned i : range (NumResults))
908
+ DataPtr[i].~DerivedResult ();
909
+ }
910
+
911
+ public:
912
+ SILInstructionResultArray getAllResults () const {
913
+ // Our results start at element 1 since we stash the pointer to our parent
914
+ // MultipleValueInstruction in the 0 elt slot. This allows all
915
+ // MultipleValueInstructionResult to find their parent
916
+ // MultipleValueInstruction by using pointer arithmetic.
917
+ auto *Result = this ->template getTrailingObjects <DerivedResult>();
918
+ return SILInstructionResultArray (
919
+ {static_cast <const MultipleValueInstructionResult *>(Result),
920
+ NumResults});
921
+ };
922
+ };
923
+
696
924
// / A subclass of SILInstruction which does not produce any values.
697
925
class NonValueInstruction : public SILInstruction {
698
926
public:
@@ -7037,6 +7265,15 @@ SILFunction *ApplyInstBase<Impl, Base, false>::getCalleeFunction() const {
7037
7265
}
7038
7266
}
7039
7267
7268
+ inline SILNode *MultipleValueInstructionResult::getCanonicalSILNodeInObject () {
7269
+ return getParent ();
7270
+ }
7271
+
7272
+ inline const SILNode *
7273
+ MultipleValueInstructionResult::getCanonicalSILNodeInObject () const {
7274
+ return getParent ();
7275
+ }
7276
+
7040
7277
} // end swift namespace
7041
7278
7042
7279
// ===----------------------------------------------------------------------===//
0 commit comments