@@ -101,12 +101,32 @@ void SymbolicValue::print(llvm::raw_ostream &os, unsigned indent) const {
101
101
case RK_DerivedAddress: {
102
102
SmallVector<unsigned , 4 > accessPath;
103
103
SymbolicValueMemoryObject *memObject = getAddressValue (accessPath);
104
- os << " Address [" << memObject->getType () << " ] " ;
104
+ os << " address [" << memObject->getType () << " ] " ;
105
105
interleave (accessPath.begin (), accessPath.end (),
106
106
[&](unsigned idx) { os << idx; }, [&]() { os << " , " ; });
107
107
os << " \n " ;
108
108
break ;
109
109
}
110
+ case RK_ArrayStorage: {
111
+ CanType elementType;
112
+ ArrayRef<SymbolicValue> elements = getStoredElements (elementType);
113
+ os << " elements type: " << elementType << " size: " << elements.size ();
114
+ switch (elements.size ()) {
115
+ case 0 :
116
+ os << " contents []\n " ;
117
+ return ;
118
+ default :
119
+ os << " contents [\n " ;
120
+ for (auto elt : elements)
121
+ elt.print (os, indent + 2 );
122
+ os.indent (indent) << " ]\n " ;
123
+ return ;
124
+ }
125
+ }
126
+ case RK_Array: {
127
+ os << getArrayType () << " : \n " ;
128
+ getStorageOfArray ().print (os, indent);
129
+ }
110
130
}
111
131
}
112
132
@@ -138,11 +158,15 @@ SymbolicValue::Kind SymbolicValue::getKind() const {
138
158
case RK_DirectAddress:
139
159
case RK_DerivedAddress:
140
160
return Address;
161
+ case RK_ArrayStorage:
162
+ return ArrayStorage;
163
+ case RK_Array:
164
+ return Array;
141
165
}
142
166
llvm_unreachable (" covered switch" );
143
167
}
144
168
145
- // / Clone this SymbolicValue into the specified ASTContext and return the new
169
+ // / Clone this SymbolicValue into the specified allocator and return the new
146
170
// / version. This only works for valid constants.
147
171
SymbolicValue
148
172
SymbolicValue::cloneInto (SymbolicValueAllocator &allocator) const {
@@ -169,16 +193,32 @@ SymbolicValue::cloneInto(SymbolicValueAllocator &allocator) const {
169
193
results.push_back (elt.cloneInto (allocator));
170
194
return getAggregate (results, allocator);
171
195
}
172
- case RK_EnumWithPayload:
173
- return getEnumWithPayload (getEnumValue (), getEnumPayloadValue (), allocator);
196
+ case RK_EnumWithPayload: {
197
+ return getEnumWithPayload (
198
+ getEnumValue (), getEnumPayloadValue ().cloneInto (allocator), allocator);
199
+ }
174
200
case RK_DirectAddress:
175
201
case RK_DerivedAddress: {
176
202
SmallVector<unsigned , 4 > accessPath;
177
203
auto *memObject = getAddressValue (accessPath);
178
204
auto *newMemObject = SymbolicValueMemoryObject::create (
179
- memObject->getType (), memObject->getValue (), allocator);
205
+ memObject->getType (), memObject->getValue ().cloneInto (allocator),
206
+ allocator);
180
207
return getAddress (newMemObject, accessPath, allocator);
181
208
}
209
+ case RK_ArrayStorage: {
210
+ CanType elementType;
211
+ ArrayRef<SymbolicValue> oldElements = getStoredElements (elementType);
212
+ SmallVector<SymbolicValue, 4 > clonedElements;
213
+ clonedElements.reserve (oldElements.size ());
214
+ for (auto elem : oldElements)
215
+ clonedElements.push_back (elem.cloneInto (allocator));
216
+ return getSymbolicArrayStorage (clonedElements, elementType, allocator);
217
+ }
218
+ case RK_Array: {
219
+ SymbolicValue clonedStorage = getStorageOfArray ().cloneInto (allocator);
220
+ return getArray (getArrayType (), clonedStorage, allocator);
221
+ }
182
222
}
183
223
llvm_unreachable (" covered switch" );
184
224
}
@@ -522,6 +562,105 @@ SymbolicValueMemoryObject *SymbolicValue::getAddressValueMemoryObject() const {
522
562
return value.derivedAddress ->memoryObject ;
523
563
}
524
564
565
+ // ===----------------------------------------------------------------------===//
566
+ // Arrays
567
+ // ===----------------------------------------------------------------------===//
568
+
569
+ namespace swift {
570
+
571
+ // / Representation of the internal storage of an array. This is a container for
572
+ // / a sequence of symbolic values corresponding to the elements of an array.
573
+ struct SymbolicArrayStorage final
574
+ : private llvm::TrailingObjects<SymbolicArrayStorage, SymbolicValue> {
575
+ friend class llvm ::TrailingObjects<SymbolicArrayStorage, SymbolicValue>;
576
+
577
+ const CanType elementType;
578
+
579
+ const unsigned numElements;
580
+
581
+ static SymbolicArrayStorage *create (ArrayRef<SymbolicValue> elements,
582
+ CanType elementType,
583
+ SymbolicValueAllocator &allocator) {
584
+ auto byteSize =
585
+ SymbolicArrayStorage::totalSizeToAlloc<SymbolicValue>(elements.size ());
586
+ auto rawMem = allocator.allocate (byteSize, alignof (SymbolicArrayStorage));
587
+
588
+ // Placement initialize the object.
589
+ auto *storage =
590
+ ::new (rawMem) SymbolicArrayStorage (elementType, elements.size ());
591
+ std::uninitialized_copy (elements.begin (), elements.end (),
592
+ storage->getTrailingObjects <SymbolicValue>());
593
+ return storage;
594
+ }
595
+
596
+ // / Return the stored elements.
597
+ ArrayRef<SymbolicValue> getElements () const {
598
+ return {getTrailingObjects<SymbolicValue>(), numElements};
599
+ }
600
+
601
+ // This is used by the llvm::TrailingObjects base class.
602
+ size_t numTrailingObjects (OverloadToken<SymbolicValue>) const {
603
+ return numElements;
604
+ }
605
+
606
+ private:
607
+ SymbolicArrayStorage () = delete ;
608
+ SymbolicArrayStorage (const SymbolicArrayStorage &) = delete ;
609
+ SymbolicArrayStorage (CanType elementType, unsigned numElements)
610
+ : elementType(elementType), numElements(numElements) {}
611
+ };
612
+ } // namespace swift
613
+ // end namespace swift
614
+
615
+ SymbolicValue
616
+ SymbolicValue::getSymbolicArrayStorage (ArrayRef<SymbolicValue> elements,
617
+ CanType elementType,
618
+ SymbolicValueAllocator &allocator) {
619
+ // TODO: Could compress the empty array representation if there were a reason
620
+ // to.
621
+ auto *arrayStorage =
622
+ SymbolicArrayStorage::create (elements, elementType, allocator);
623
+ SymbolicValue result;
624
+ result.representationKind = RK_ArrayStorage;
625
+ result.value .arrayStorage = arrayStorage;
626
+ return result;
627
+ }
628
+
629
+ ArrayRef<SymbolicValue>
630
+ SymbolicValue::getStoredElements (CanType &elementType) const {
631
+ assert (getKind () == ArrayStorage);
632
+ elementType = value.arrayStorage ->elementType ;
633
+ return value.arrayStorage ->getElements ();
634
+ }
635
+
636
+ SymbolicValue SymbolicValue::getArray (Type arrayType,
637
+ SymbolicValue arrayStorage,
638
+ SymbolicValueAllocator &allocator) {
639
+ assert (arrayStorage.getKind () == ArrayStorage);
640
+ SymbolicValue result;
641
+ result.representationKind = RK_Array;
642
+ result.value .array =
643
+ SymbolicValueMemoryObject::create (arrayType, arrayStorage, allocator);
644
+ return result;
645
+ }
646
+
647
+ SymbolicValue
648
+ SymbolicValue::getAddressOfArrayElement (SymbolicValueAllocator &allocator,
649
+ unsigned index) const {
650
+ assert (getKind () == Array);
651
+ return SymbolicValue::getAddress (value.array , {index}, allocator);
652
+ }
653
+
654
+ SymbolicValue SymbolicValue::getStorageOfArray () const {
655
+ assert (getKind () == Array);
656
+ return value.array ->getValue ();
657
+ }
658
+
659
+ Type SymbolicValue::getArrayType () const {
660
+ assert (getKind () == Array);
661
+ return value.array ->getType ();
662
+ }
663
+
525
664
// ===----------------------------------------------------------------------===//
526
665
// Higher level code
527
666
// ===----------------------------------------------------------------------===//
@@ -766,20 +905,29 @@ static SymbolicValue getIndexedElement(SymbolicValue aggregate,
766
905
if (aggregate.getKind () == SymbolicValue::UninitMemory)
767
906
return SymbolicValue::getUninitMemory ();
768
907
769
- assert (aggregate.getKind () == SymbolicValue::Aggregate &&
908
+ assert ((aggregate.getKind () == SymbolicValue::Aggregate ||
909
+ aggregate.getKind () == SymbolicValue::ArrayStorage) &&
770
910
" the accessPath is invalid for this type" );
771
911
772
912
unsigned elementNo = accessPath.front ();
773
913
774
- SymbolicValue elt = aggregate. getAggregateValue ()[elementNo] ;
914
+ SymbolicValue elt;
775
915
Type eltType;
776
- if ( auto *decl = type-> getStructOrBoundGenericStruct ()) {
777
- eltType = decl-> getStoredProperties ()[elementNo]-> getType ();
778
- } else if ( auto tuple = type-> getAs <TupleType>()) {
779
- assert (elementNo < tuple-> getNumElements () && " invalid index " ) ;
780
- eltType = tuple-> getElement (elementNo). getType () ;
916
+
917
+ if (aggregate. getKind () == SymbolicValue::ArrayStorage) {
918
+ CanType arrayEltTy;
919
+ elt = aggregate. getStoredElements (arrayEltTy)[elementNo] ;
920
+ eltType = arrayEltTy ;
781
921
} else {
782
- llvm_unreachable (" the accessPath is invalid for this type" );
922
+ elt = aggregate.getAggregateValue ()[elementNo];
923
+ if (auto *decl = type->getStructOrBoundGenericStruct ()) {
924
+ eltType = decl->getStoredProperties ()[elementNo]->getType ();
925
+ } else if (auto tuple = type->getAs <TupleType>()) {
926
+ assert (elementNo < tuple->getNumElements () && " invalid index" );
927
+ eltType = tuple->getElement (elementNo).getType ();
928
+ } else {
929
+ llvm_unreachable (" the accessPath is invalid for this type" );
930
+ }
783
931
}
784
932
785
933
return getIndexedElement (elt, accessPath.drop_front (), eltType);
@@ -828,20 +976,29 @@ static SymbolicValue setIndexedElement(SymbolicValue aggregate,
828
976
aggregate = SymbolicValue::getAggregate (newElts, allocator);
829
977
}
830
978
831
- assert (aggregate.getKind () == SymbolicValue::Aggregate &&
979
+ assert ((aggregate.getKind () == SymbolicValue::Aggregate ||
980
+ aggregate.getKind () == SymbolicValue::ArrayStorage) &&
832
981
" the accessPath is invalid for this type" );
833
982
834
983
unsigned elementNo = accessPath.front ();
835
984
836
- ArrayRef<SymbolicValue> oldElts = aggregate. getAggregateValue () ;
985
+ ArrayRef<SymbolicValue> oldElts;
837
986
Type eltType;
838
- if ( auto *decl = type-> getStructOrBoundGenericStruct ()) {
839
- eltType = decl-> getStoredProperties ()[elementNo]-> getType ();
840
- } else if ( auto tuple = type-> getAs <TupleType>()) {
841
- assert (elementNo < tuple-> getNumElements () && " invalid index " );
842
- eltType = tuple-> getElement (elementNo). getType () ;
987
+
988
+ if (aggregate. getKind () == SymbolicValue::ArrayStorage) {
989
+ CanType arrayEltTy;
990
+ oldElts = aggregate. getStoredElements (arrayEltTy );
991
+ eltType = arrayEltTy ;
843
992
} else {
844
- llvm_unreachable (" the accessPath is invalid for this type" );
993
+ oldElts = aggregate.getAggregateValue ();
994
+ if (auto *decl = type->getStructOrBoundGenericStruct ()) {
995
+ eltType = decl->getStoredProperties ()[elementNo]->getType ();
996
+ } else if (auto tuple = type->getAs <TupleType>()) {
997
+ assert (elementNo < tuple->getNumElements () && " invalid index" );
998
+ eltType = tuple->getElement (elementNo).getType ();
999
+ } else {
1000
+ llvm_unreachable (" the accessPath is invalid for this type" );
1001
+ }
845
1002
}
846
1003
847
1004
// Update the indexed element of the aggregate.
@@ -850,7 +1007,11 @@ static SymbolicValue setIndexedElement(SymbolicValue aggregate,
850
1007
setIndexedElement (newElts[elementNo], accessPath.drop_front (), newElement,
851
1008
eltType, allocator);
852
1009
853
- aggregate = SymbolicValue::getAggregate (newElts, allocator);
1010
+ if (aggregate.getKind () == SymbolicValue::Aggregate)
1011
+ return SymbolicValue::getAggregate (newElts, allocator);
1012
+
1013
+ return aggregate = SymbolicValue::getSymbolicArrayStorage (
1014
+ newElts, eltType->getCanonicalType (), allocator);
854
1015
return aggregate;
855
1016
}
856
1017
0 commit comments