@@ -44,6 +44,7 @@ class DeclRefExpr;
44
44
class FloatLiteralExpr ;
45
45
class FuncDecl ;
46
46
class IntegerLiteralExpr ;
47
+ class NonValueInstruction ;
47
48
class SILBasicBlock ;
48
49
class SILBuilder ;
49
50
class SILDebugLocation ;
@@ -87,6 +88,114 @@ SILInstructionKind getSILInstructionKind(StringRef InstName);
87
88
// / Map SILInstructionKind to a corresponding SILInstruction name.
88
89
StringRef getSILInstructionName (SILInstructionKind Kind);
89
90
91
+ // / A formal SIL reference to a list of values, suitable for use as the result
92
+ // / of a SILInstruction.
93
+ // /
94
+ // / *NOTE* Most multiple value instructions will not have many results, so if we
95
+ // / want we can cache up to 3 bytes in the lower bits of the value.
96
+ // /
97
+ // / *NOTE* Most of this defined out of line further down in the file to work
98
+ // / around forward declaration issues.
99
+ class SILInstructionResultArray {
100
+ const uint8_t *Pointer;
101
+ unsigned Size;
102
+
103
+ public:
104
+ SILInstructionResultArray () : Pointer(nullptr ), Size(0 ) {}
105
+ SILInstructionResultArray (const SingleValueInstruction *SVI);
106
+
107
+ SILInstructionResultArray (const SILInstructionResultArray &Other) = default ;
108
+ SILInstructionResultArray &
109
+ operator =(const SILInstructionResultArray &Other) = default ;
110
+ SILInstructionResultArray (SILInstructionResultArray &&Other) = default ;
111
+ SILInstructionResultArray &
112
+ operator =(SILInstructionResultArray &&Other) = default ;
113
+
114
+ SILValue operator [](size_t Index) const ;
115
+
116
+ bool empty () const { return Size == 0 ; }
117
+
118
+ size_t size () const { return Size; }
119
+
120
+ class iterator ;
121
+
122
+ iterator begin () const ;
123
+ iterator end () const ;
124
+
125
+ using range = llvm::iterator_range<iterator>;
126
+ range getValues () const ;
127
+
128
+ using type_range = llvm::iterator_range<
129
+ llvm::mapped_iterator<iterator, std::function<SILType(SILValue)>>>;
130
+ type_range getTypes () const ;
131
+
132
+ bool operator ==(const SILInstructionResultArray &rhs);
133
+ bool operator !=(const SILInstructionResultArray &other) {
134
+ return !(*this == other);
135
+ }
136
+
137
+ // / Returns true if both this and \p rhs have the same result types.
138
+ // /
139
+ // / *NOTE* This does not imply that the actual return SILValues are the
140
+ // / same. Just that the types are the same.
141
+ bool hasSameTypes (const SILInstructionResultArray &rhs);
142
+
143
+ private:
144
+ // / Return the offset 1 past the end of the array or None if we are not
145
+ // / actually storing anything.
146
+ Optional<unsigned > getStartOffset () const {
147
+ return empty () ? None : Optional<unsigned >(0 );
148
+ }
149
+
150
+ // / Return the offset 1 past the end of the array or None if we are not
151
+ // / actually storing anything.
152
+ Optional<unsigned > getEndOffset () const {
153
+ return empty () ? None : Optional<unsigned >(size ());
154
+ }
155
+ };
156
+
157
+ class SILInstructionResultArray ::iterator
158
+ : public std::iterator<std::bidirectional_iterator_tag, SILValue,
159
+ ptrdiff_t > {
160
+ // / Our "parent" array.
161
+ // /
162
+ // / This is actually a value type reference into a SILInstruction of some
163
+ // / sort. So we can just have our own copy. This also allows us to not worry
164
+ // / about our underlying array having too short of a lifetime.
165
+ SILInstructionResultArray Parent;
166
+
167
+ // / The index into the parent array.
168
+ Optional<unsigned > Index;
169
+
170
+ public:
171
+ iterator () = default ;
172
+ iterator (const SILInstructionResultArray &Parent,
173
+ Optional<unsigned > Index = 0 )
174
+ : Parent(Parent), Index(Index) {}
175
+
176
+ SILValue operator *() const { return Parent[Index.getValue ()]; }
177
+
178
+ SILValue operator ->() const { return operator *(); }
179
+
180
+ iterator &operator ++() {
181
+ ++Index.getValue ();
182
+ return *this ;
183
+ }
184
+
185
+ iterator operator ++(int ) {
186
+ iterator copy = *this ;
187
+ ++Index.getValue ();
188
+ return copy;
189
+ }
190
+
191
+ friend bool operator ==(iterator lhs, iterator rhs) {
192
+ assert (lhs.Parent .Pointer == rhs.Parent .Pointer );
193
+ return lhs.Index == rhs.Index ;
194
+ }
195
+
196
+ friend bool operator !=(iterator lhs, iterator rhs) { return !(lhs == rhs); }
197
+ };
198
+
90
199
// / This is the root class for all instructions that can be used as the
91
200
// / contents of a Swift SILBasicBlock.
92
201
// /
@@ -143,7 +252,7 @@ class SILInstruction
143
252
144
253
// / An internal method which retrieves the result values of the
145
254
// / instruction as an array of ValueBase objects.
146
- ArrayRef<ValueBase> getResultsImpl () const ;
255
+ SILInstructionResultArray getResultsImpl () const ;
147
256
148
257
protected:
149
258
SILInstruction (SILInstructionKind kind, SILDebugLocation DebugLoc)
@@ -318,18 +427,13 @@ class SILInstruction
318
427
getAllOperands ()[Num1].swap (getAllOperands ()[Num2]);
319
428
}
320
429
321
- using ResultArrayRef =
322
- ArrayRefView<ValueBase,SILValue,projectValueBaseAsSILValue>;
323
-
324
430
// / Return the list of results produced by this instruction.
325
- ResultArrayRef getResults () const { return getResultsImpl (); }
326
-
327
- using ResultTypeArrayRef =
328
- ArrayRefView<ValueBase,SILType,projectValueBaseType>;
431
+ SILInstructionResultArray getResults () const { return getResultsImpl (); }
432
+ unsigned getNumResults () const { return getResults ().size (); }
329
433
330
434
// / Return the types of the results produced by this instruction.
331
- ResultTypeArrayRef getResultTypes () const {
332
- return getResultsImpl ();
435
+ SILInstructionResultArray::type_range getResultTypes () const {
436
+ return getResultsImpl (). getTypes () ;
333
437
}
334
438
335
439
MemoryBehavior getMemoryBehavior () const ;
@@ -364,9 +468,9 @@ class SILInstruction
364
468
return false ;
365
469
}
366
470
367
- if (getResultTypes () != RHS->getResultTypes ( ))
471
+ if (! getResults (). hasSameTypes ( RHS->getResults () ))
368
472
return false ;
369
-
473
+
370
474
// Check operands.
371
475
for (unsigned i = 0 , e = getNumOperands (); i != e; ++i)
372
476
if (!opEqual (getOperand (i), RHS->getOperand (i)))
@@ -504,8 +608,8 @@ class SingleValueInstruction : public SILInstruction, public ValueBase {
504
608
}
505
609
506
610
friend class SILInstruction ;
507
- ArrayRef<ValueBase> getResultsImpl () const {
508
- return ArrayRef<ValueBase> (this , 1 );
611
+ SILInstructionResultArray getResultsImpl () const {
612
+ return SILInstructionResultArray (this );
509
613
}
510
614
public:
511
615
SingleValueInstruction (SILInstructionKind kind, SILDebugLocation loc,
@@ -547,9 +651,7 @@ class SingleValueInstruction : public SILInstruction, public ValueBase {
547
651
}
548
652
549
653
// / Override this to reflect the more efficient access pattern.
550
- ResultArrayRef getResults () const {
551
- return getResultsImpl ();
552
- }
654
+ SILInstructionResultArray getResults () const { return getResultsImpl (); }
553
655
554
656
static bool classof (const SILNode *node) {
555
657
return isSingleValueInstKind (node->getKind ());
@@ -599,7 +701,14 @@ class NonValueInstruction : public SILInstruction {
599
701
600
702
// / Doesn't produce any results.
601
703
SILType getType () const = delete;
602
- ResultArrayRef getResults () const = delete;
704
+ SILInstructionResultArray getResults () const = delete;
705
+
706
+ static bool classof (const ValueBase *value) = delete;
707
+ static bool classof (const SILNode *N) {
708
+ return N->getKind () >= SILNodeKind::First_NonValueInstruction &&
709
+ N->getKind () <= SILNodeKind::Last_NonValueInstruction;
710
+ }
711
+ static bool classof (const NonValueInstruction *) { return true ; }
603
712
};
604
713
#define DEFINE_ABSTRACT_NON_VALUE_INST_BOILERPLATE (ID ) \
605
714
static bool classof (const ValueBase *value) = delete; \
0 commit comments