Skip to content

Commit 3cfbce6

Browse files
author
Marc Rasi
committed
const evaluator: array values and initialization
1 parent 87604fe commit 3cfbce6

File tree

4 files changed

+368
-21
lines changed

4 files changed

+368
-21
lines changed

include/swift/SIL/SILConstants.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ class SymbolicValue {
114114

115115
/// This represents an index *into* a memory object.
116116
RK_DerivedAddress,
117+
118+
/// This represents an array value.
119+
RK_Array,
120+
121+
/// This represents an address of a memory object containing an array.
122+
RK_ArrayAddress,
117123
};
118124

119125
union {
@@ -157,6 +163,12 @@ class SymbolicValue {
157163
/// When this SymbolicValue is of "DerivedAddress" kind, this pointer stores
158164
/// information about the memory object and access path of the access.
159165
DerivedAddressValue *derivedAddress;
166+
167+
/// For RK_Array, this is the elements of the array.
168+
ArraySymbolicValue *array;
169+
170+
/// For RK_ArrayAddress, this is the memory object referenced.
171+
SymbolicValueMemoryObject *arrayAddress;
160172
} value;
161173

162174
RepresentationKind representationKind : 8;
@@ -209,6 +221,9 @@ class SymbolicValue {
209221
/// This value represents the address of, or into, a memory object.
210222
Address,
211223

224+
/// This represents an array value.
225+
Array,
226+
212227
/// These values are generally only seen internally to the system, external
213228
/// clients shouldn't have to deal with them.
214229
UninitMemory
@@ -332,6 +347,20 @@ class SymbolicValue {
332347
/// Return just the memory object for an address value.
333348
SymbolicValueMemoryObject *getAddressValueMemoryObject() const;
334349

350+
/// Produce an array of elements.
351+
static SymbolicValue getArray(ArrayRef<SymbolicValue> elements,
352+
CanType elementType,
353+
ASTContext &astContext);
354+
static SymbolicValue
355+
getArrayAddress(SymbolicValueMemoryObject *memoryObject) {
356+
SymbolicValue result;
357+
result.representationKind = RK_ArrayAddress;
358+
result.value.directAddress = memoryObject;
359+
return result;
360+
}
361+
362+
ArrayRef<SymbolicValue> getArrayValue(CanType &elementType) const;
363+
335364
//===--------------------------------------------------------------------===//
336365
// Helpers
337366

lib/SIL/SILConstants.cpp

Lines changed: 155 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,27 @@ void SymbolicValue::print(llvm::raw_ostream &os, unsigned indent) const {
106106
os << "\n";
107107
break;
108108
}
109+
case RK_Array:
110+
case RK_ArrayAddress: {
111+
CanType elementType;
112+
ArrayRef<SymbolicValue> elements = getArrayValue(elementType);
113+
os << "array<" << elementType << ">: " << elements.size();
114+
switch (elements.size()) {
115+
case 0:
116+
os << " elements []\n";
117+
return;
118+
case 1:
119+
os << " elt: ";
120+
elements[0].print(os, indent + 2);
121+
return;
122+
default:
123+
os << " elements [\n";
124+
for (auto elt : elements)
125+
elt.print(os, indent + 2);
126+
os.indent(indent) << "]\n";
127+
return;
128+
}
129+
}
109130
}
110131
}
111132

@@ -137,6 +158,9 @@ SymbolicValue::Kind SymbolicValue::getKind() const {
137158
case RK_DirectAddress:
138159
case RK_DerivedAddress:
139160
return Address;
161+
case RK_Array:
162+
case RK_ArrayAddress:
163+
return Array;
140164
}
141165
}
142166

@@ -177,6 +201,16 @@ SymbolicValue::cloneInto(ASTContext &astContext) const {
177201
memObject->getType(), memObject->getValue(), astContext);
178202
return getAddress(newMemObject, accessPath, astContext);
179203
}
204+
case RK_Array:
205+
case RK_ArrayAddress: {
206+
CanType elementType;
207+
auto elts = getArrayValue(elementType);
208+
SmallVector<SymbolicValue, 4> results;
209+
results.reserve(elts.size());
210+
for (auto elt : elts)
211+
results.push_back(elt.cloneInto(astContext));
212+
return getArray(results, elementType, astContext);
213+
}
180214
}
181215
}
182216

@@ -520,6 +554,81 @@ SymbolicValueMemoryObject *SymbolicValue::getAddressValueMemoryObject() const {
520554
return value.derivedAddress->memoryObject;
521555
}
522556

557+
//===----------------------------------------------------------------------===//
558+
// Arrays
559+
//===----------------------------------------------------------------------===//
560+
561+
namespace swift {
562+
563+
/// This is the representation of an array.
564+
struct ArraySymbolicValue final
565+
: private llvm::TrailingObjects<ArraySymbolicValue, SymbolicValue> {
566+
friend class llvm::TrailingObjects<ArraySymbolicValue, SymbolicValue>;
567+
568+
const CanType elementType;
569+
570+
/// This is the number of indices in the derived address.
571+
const unsigned numElements;
572+
573+
static ArraySymbolicValue *create(ArrayRef<SymbolicValue> elements,
574+
CanType elementType,
575+
ASTContext &astContext) {
576+
auto byteSize =
577+
ArraySymbolicValue::totalSizeToAlloc<SymbolicValue>(elements.size());
578+
auto rawMem = astContext.Allocate(byteSize, alignof(ArraySymbolicValue));
579+
580+
// Placement initialize the object.
581+
auto asv = ::new (rawMem) ArraySymbolicValue(elementType, elements.size());
582+
std::uninitialized_copy(elements.begin(), elements.end(),
583+
asv->getTrailingObjects<SymbolicValue>());
584+
return asv;
585+
}
586+
587+
/// Return the element constants for this aggregate constant. These are
588+
/// known to all be constants.
589+
ArrayRef<SymbolicValue> getElements() const {
590+
return {getTrailingObjects<SymbolicValue>(), numElements};
591+
}
592+
593+
// This is used by the llvm::TrailingObjects base class.
594+
size_t numTrailingObjects(OverloadToken<SymbolicValue>) const {
595+
return numElements;
596+
}
597+
598+
private:
599+
ArraySymbolicValue() = delete;
600+
ArraySymbolicValue(const ArraySymbolicValue &) = delete;
601+
ArraySymbolicValue(CanType elementType, unsigned numElements)
602+
: elementType(elementType), numElements(numElements) {}
603+
};
604+
} // end namespace swift
605+
606+
/// Produce an array of elements.
607+
SymbolicValue SymbolicValue::getArray(ArrayRef<SymbolicValue> elements,
608+
CanType elementType,
609+
ASTContext &astContext) {
610+
// TODO: Could compress the empty array representation if there were a reason
611+
// to.
612+
auto asv = ArraySymbolicValue::create(elements, elementType, astContext);
613+
SymbolicValue result;
614+
result.representationKind = RK_Array;
615+
result.value.array = asv;
616+
return result;
617+
}
618+
619+
ArrayRef<SymbolicValue>
620+
SymbolicValue::getArrayValue(CanType &elementType) const {
621+
assert(getKind() == Array);
622+
auto val = *this;
623+
if (representationKind == RK_ArrayAddress)
624+
val = value.arrayAddress->getValue();
625+
626+
assert(val.representationKind == RK_Array);
627+
628+
elementType = val.value.array->elementType;
629+
return val.value.array->getElements();
630+
}
631+
523632
//===----------------------------------------------------------------------===//
524633
// Higher level code
525634
//===----------------------------------------------------------------------===//
@@ -653,22 +762,32 @@ static SymbolicValue getIndexedElement(SymbolicValue aggregate,
653762
if (aggregate.getKind() == SymbolicValue::UninitMemory)
654763
return SymbolicValue::getUninitMemory();
655764

656-
assert(aggregate.getKind() == SymbolicValue::Aggregate &&
765+
assert((aggregate.getKind() == SymbolicValue::Aggregate ||
766+
aggregate.getKind() == SymbolicValue::Array) &&
657767
"the accessPath is invalid for this type");
658768

659769
unsigned elementNo = accessPath.front();
660770

661-
SymbolicValue elt = aggregate.getAggregateValue()[elementNo];
771+
SymbolicValue elt;
662772
Type eltType;
663-
if (auto *decl = type->getStructOrBoundGenericStruct()) {
664-
auto it = decl->getStoredProperties().begin();
665-
std::advance(it, elementNo);
666-
eltType = (*it)->getType();
667-
} else if (auto tuple = type->getAs<TupleType>()) {
668-
assert(elementNo < tuple->getNumElements() && "invalid index");
669-
eltType = tuple->getElement(elementNo).getType();
773+
774+
// We need to have an array, struct or a tuple type.
775+
if (aggregate.getKind() == SymbolicValue::Array) {
776+
CanType arrayEltTy;
777+
elt = aggregate.getArrayValue(arrayEltTy)[elementNo];
778+
eltType = arrayEltTy;
670779
} else {
671-
llvm_unreachable("the accessPath is invalid for this type");
780+
elt = aggregate.getAggregateValue()[elementNo];
781+
if (auto *decl = type->getStructOrBoundGenericStruct()) {
782+
auto it = decl->getStoredProperties().begin();
783+
std::advance(it, elementNo);
784+
eltType = (*it)->getType();
785+
} else if (auto tuple = type->getAs<TupleType>()) {
786+
assert(elementNo < tuple->getNumElements() && "invalid index");
787+
eltType = tuple->getElement(elementNo).getType();
788+
} else {
789+
llvm_unreachable("the accessPath is invalid for this type");
790+
}
672791
}
673792

674793
return getIndexedElement(elt, accessPath.drop_front(), eltType);
@@ -718,22 +837,33 @@ static SymbolicValue setIndexedElement(SymbolicValue aggregate,
718837
aggregate = SymbolicValue::getAggregate(newElts, astCtx);
719838
}
720839

721-
assert(aggregate.getKind() == SymbolicValue::Aggregate &&
840+
assert((aggregate.getKind() == SymbolicValue::Aggregate ||
841+
aggregate.getKind() == SymbolicValue::Array) &&
722842
"the accessPath is invalid for this type");
723843

724844
unsigned elementNo = accessPath.front();
725845

726-
ArrayRef<SymbolicValue> oldElts = aggregate.getAggregateValue();
846+
ArrayRef<SymbolicValue> oldElts;
727847
Type eltType;
728-
if (auto *decl = type->getStructOrBoundGenericStruct()) {
729-
auto it = decl->getStoredProperties().begin();
730-
std::advance(it, elementNo);
731-
eltType = (*it)->getType();
732-
} else if (auto tuple = type->getAs<TupleType>()) {
733-
assert(elementNo < tuple->getNumElements() && "invalid index");
734-
eltType = tuple->getElement(elementNo).getType();
848+
849+
// We need to have an array, struct or a tuple type.
850+
if (aggregate.getKind() == SymbolicValue::Array) {
851+
CanType arrayEltTy;
852+
oldElts = aggregate.getArrayValue(arrayEltTy);
853+
eltType = arrayEltTy;
735854
} else {
736-
llvm_unreachable("the accessPath is invalid for this type");
855+
oldElts = aggregate.getAggregateValue();
856+
857+
if (auto *decl = type->getStructOrBoundGenericStruct()) {
858+
auto it = decl->getStoredProperties().begin();
859+
std::advance(it, elementNo);
860+
eltType = (*it)->getType();
861+
} else if (auto tuple = type->getAs<TupleType>()) {
862+
assert(elementNo < tuple->getNumElements() && "invalid index");
863+
eltType = tuple->getElement(elementNo).getType();
864+
} else {
865+
llvm_unreachable("the accessPath is invalid for this type");
866+
}
737867
}
738868

739869
// Update the indexed element of the aggregate.
@@ -742,7 +872,11 @@ static SymbolicValue setIndexedElement(SymbolicValue aggregate,
742872
accessPath.drop_front(), newElement,
743873
eltType, astCtx);
744874

745-
aggregate = SymbolicValue::getAggregate(newElts, astCtx);
875+
if (aggregate.getKind() == SymbolicValue::Aggregate)
876+
aggregate = SymbolicValue::getAggregate(newElts, astCtx);
877+
else
878+
aggregate = SymbolicValue::getArray(newElts, eltType->getCanonicalType(),
879+
astCtx);
746880

747881
return aggregate;
748882
}

0 commit comments

Comments
 (0)