Skip to content

Commit d61165c

Browse files
author
Marc Rasi
committed
const evaluator: array values and initialization
1 parent af43ae7 commit d61165c

File tree

6 files changed

+365
-21
lines changed

6 files changed

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

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

659770
unsigned elementNo = accessPath.front();
660771

661-
SymbolicValue elt = aggregate.getAggregateValue()[elementNo];
772+
SymbolicValue elt;
662773
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();
774+
775+
// We need to have an array, struct or a tuple type.
776+
if (aggregate.getKind() == SymbolicValue::Array) {
777+
CanType arrayEltTy;
778+
elt = aggregate.getArrayValue(arrayEltTy)[elementNo];
779+
eltType = arrayEltTy;
670780
} else {
671-
llvm_unreachable("the accessPath is invalid for this type");
781+
elt = aggregate.getAggregateValue()[elementNo];
782+
if (auto *decl = type->getStructOrBoundGenericStruct()) {
783+
auto it = decl->getStoredProperties().begin();
784+
std::advance(it, elementNo);
785+
eltType = (*it)->getType();
786+
} else if (auto tuple = type->getAs<TupleType>()) {
787+
assert(elementNo < tuple->getNumElements() && "invalid index");
788+
eltType = tuple->getElement(elementNo).getType();
789+
} else {
790+
llvm_unreachable("the accessPath is invalid for this type");
791+
}
672792
}
673793

674794
return getIndexedElement(elt, accessPath.drop_front(), eltType);
@@ -718,22 +838,33 @@ static SymbolicValue setIndexedElement(SymbolicValue aggregate,
718838
aggregate = SymbolicValue::getAggregate(newElts, astCtx);
719839
}
720840

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

724845
unsigned elementNo = accessPath.front();
725846

726-
ArrayRef<SymbolicValue> oldElts = aggregate.getAggregateValue();
847+
ArrayRef<SymbolicValue> oldElts;
727848
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();
849+
850+
// We need to have an array, struct or a tuple type.
851+
if (aggregate.getKind() == SymbolicValue::Array) {
852+
CanType arrayEltTy;
853+
oldElts = aggregate.getArrayValue(arrayEltTy);
854+
eltType = arrayEltTy;
735855
} else {
736-
llvm_unreachable("the accessPath is invalid for this type");
856+
oldElts = aggregate.getAggregateValue();
857+
858+
if (auto *decl = type->getStructOrBoundGenericStruct()) {
859+
auto it = decl->getStoredProperties().begin();
860+
std::advance(it, elementNo);
861+
eltType = (*it)->getType();
862+
} else if (auto tuple = type->getAs<TupleType>()) {
863+
assert(elementNo < tuple->getNumElements() && "invalid index");
864+
eltType = tuple->getElement(elementNo).getType();
865+
} else {
866+
llvm_unreachable("the accessPath is invalid for this type");
867+
}
737868
}
738869

739870
// Update the indexed element of the aggregate.
@@ -742,7 +873,11 @@ static SymbolicValue setIndexedElement(SymbolicValue aggregate,
742873
accessPath.drop_front(), newElement,
743874
eltType, astCtx);
744875

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

747882
return aggregate;
748883
}

0 commit comments

Comments
 (0)