Skip to content

Commit 48bc63b

Browse files
committed
[Constant Evaluator] Add support for tracking types with aggregate
symbolic values, which are used to represent constant struct and tuple instances. Associating those symbolic values with the types of the aggregate they are representing will allow writing some sanity checks, and will also make constant folding of the symbolic values easier and more robust.
1 parent 3a4c4d0 commit 48bc63b

File tree

4 files changed

+121
-53
lines changed

4 files changed

+121
-53
lines changed

include/swift/SIL/SILConstants.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class SILValue;
2828
class SILBuilder;
2929
class SerializedSILLoader;
3030

31+
struct AggregateSymbolicValue;
3132
struct SymbolicArrayStorage;
3233
struct DerivedAddressValue;
3334
struct EnumWithPayloadSymbolicValue;
@@ -307,8 +308,8 @@ class SymbolicValue {
307308
const char *string;
308309

309310
/// When this SymbolicValue is of "Aggregate" kind, this pointer stores
310-
/// information about the array elements and count.
311-
const SymbolicValue *aggregate;
311+
/// information about the aggregate elements, its type and count.
312+
const AggregateSymbolicValue *aggregate;
312313

313314
/// When this SymbolicValue is of "Enum" kind, this pointer stores
314315
/// information about the enum case type.
@@ -365,9 +366,6 @@ class SymbolicValue {
365366

366367
/// This is the number of bytes for an RK_String representation.
367368
unsigned stringNumBytes;
368-
369-
/// This is the number of elements for an RK_Aggregate representation.
370-
unsigned aggregateNumElements;
371369
} auxInfo;
372370

373371
public:
@@ -488,11 +486,15 @@ class SymbolicValue {
488486
StringRef getStringValue() const;
489487

490488
/// This returns an aggregate value with the specified elements in it. This
491-
/// copies the elements into the specified Allocator.
492-
static SymbolicValue getAggregate(ArrayRef<SymbolicValue> elements,
489+
/// copies the member values into the specified Allocator.
490+
static SymbolicValue getAggregate(ArrayRef<SymbolicValue> members,
491+
Type aggregateType,
493492
SymbolicValueAllocator &allocator);
494493

495-
ArrayRef<SymbolicValue> getAggregateValue() const;
494+
ArrayRef<SymbolicValue> getAggregateMembers() const;
495+
496+
/// Return the type of this aggregate symbolic value.
497+
Type getAggregateType() const;
496498

497499
/// This returns a constant Symbolic value for the enum case in `decl`, which
498500
/// must not have an associated value.
@@ -617,7 +619,12 @@ struct SymbolicValueMemoryObject {
617619
Type getType() const { return type; }
618620

619621
SymbolicValue getValue() const { return value; }
620-
void setValue(SymbolicValue newValue) { value = newValue; }
622+
void setValue(SymbolicValue newValue) {
623+
assert((newValue.getKind() != SymbolicValue::Aggregate ||
624+
newValue.getAggregateType()->isEqual(type)) &&
625+
"Memory object type does not match the type of the symbolic value");
626+
value = newValue;
627+
}
621628

622629
/// Create a new memory object whose overall type is as specified.
623630
static SymbolicValueMemoryObject *create(Type type, SymbolicValue value,

lib/SIL/SILConstants.cpp

Lines changed: 71 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ void SymbolicValue::print(llvm::raw_ostream &os, unsigned indent) const {
6666
os << "string: \"" << getStringValue() << "\"\n";
6767
return;
6868
case RK_Aggregate: {
69-
ArrayRef<SymbolicValue> elements = getAggregateValue();
69+
ArrayRef<SymbolicValue> elements = getAggregateMembers();
7070
switch (elements.size()) {
7171
case 0:
7272
os << "agg: 0 elements []\n";
@@ -211,12 +211,12 @@ SymbolicValue::cloneInto(SymbolicValueAllocator &allocator) const {
211211
case RK_String:
212212
return SymbolicValue::getString(getStringValue(), allocator);
213213
case RK_Aggregate: {
214-
auto elts = getAggregateValue();
214+
auto elts = getAggregateMembers();
215215
SmallVector<SymbolicValue, 4> results;
216216
results.reserve(elts.size());
217217
for (auto elt : elts)
218218
results.push_back(elt.cloneInto(allocator));
219-
return getAggregate(results, allocator);
219+
return getAggregate(results, getAggregateType(), allocator);
220220
}
221221
case RK_EnumWithPayload: {
222222
return getEnumWithPayload(
@@ -350,24 +350,71 @@ StringRef SymbolicValue::getStringValue() const {
350350
// Aggregates
351351
//===----------------------------------------------------------------------===//
352352

353-
/// This returns a constant Symbolic value with the specified elements in it.
354-
/// This assumes that the elements lifetime has been managed for this.
355-
SymbolicValue SymbolicValue::getAggregate(ArrayRef<SymbolicValue> elements,
356-
SymbolicValueAllocator &allocator) {
357-
// Copy the elements into the bump pointer.
358-
auto *resultElts = allocator.allocate<SymbolicValue>(elements.size());
359-
std::uninitialized_copy(elements.begin(), elements.end(), resultElts);
353+
namespace swift {
354+
355+
/// Representation of a constant aggregate namely a struct or a tuple.
356+
struct AggregateSymbolicValue final
357+
: private llvm::TrailingObjects<AggregateSymbolicValue, SymbolicValue> {
358+
friend class llvm::TrailingObjects<AggregateSymbolicValue, SymbolicValue>;
359+
360+
const Type aggregateType;
361+
362+
const unsigned numElements;
363+
364+
static AggregateSymbolicValue *create(ArrayRef<SymbolicValue> members,
365+
Type aggregateType,
366+
SymbolicValueAllocator &allocator) {
367+
auto byteSize =
368+
AggregateSymbolicValue::totalSizeToAlloc<SymbolicValue>(members.size());
369+
auto rawMem = allocator.allocate(byteSize, alignof(AggregateSymbolicValue));
370+
371+
// Placement initialize the object.
372+
auto *aggregate =
373+
::new (rawMem) AggregateSymbolicValue(aggregateType, members.size());
374+
std::uninitialized_copy(members.begin(), members.end(),
375+
aggregate->getTrailingObjects<SymbolicValue>());
376+
return aggregate;
377+
}
378+
379+
/// Return the type of the aggregate.
380+
Type getAggregateType() const { return aggregateType; }
360381

382+
/// Return the symbolic values of members.
383+
ArrayRef<SymbolicValue> getMemberValues() const {
384+
return {getTrailingObjects<SymbolicValue>(), numElements};
385+
}
386+
387+
// This is used by the llvm::TrailingObjects base class.
388+
size_t numTrailingObjects(OverloadToken<SymbolicValue>) const {
389+
return numElements;
390+
}
391+
392+
private:
393+
AggregateSymbolicValue() = delete;
394+
AggregateSymbolicValue(const AggregateSymbolicValue &) = delete;
395+
AggregateSymbolicValue(Type aggregateType, unsigned numElements)
396+
: aggregateType(aggregateType), numElements(numElements) {}
397+
};
398+
} // namespace swift
399+
400+
SymbolicValue SymbolicValue::getAggregate(ArrayRef<SymbolicValue> members,
401+
Type aggregateType,
402+
SymbolicValueAllocator &allocator) {
361403
SymbolicValue result;
362404
result.representationKind = RK_Aggregate;
363-
result.value.aggregate = resultElts;
364-
result.auxInfo.aggregateNumElements = elements.size();
405+
result.value.aggregate =
406+
AggregateSymbolicValue::create(members, aggregateType, allocator);
365407
return result;
366408
}
367409

368-
ArrayRef<SymbolicValue> SymbolicValue::getAggregateValue() const {
410+
ArrayRef<SymbolicValue> SymbolicValue::getAggregateMembers() const {
369411
assert(getKind() == Aggregate);
370-
return ArrayRef<SymbolicValue>(value.aggregate, auxInfo.aggregateNumElements);
412+
return value.aggregate->getMemberValues();
413+
}
414+
415+
Type SymbolicValue::getAggregateType() const {
416+
assert(getKind() == Aggregate);
417+
return value.aggregate->getAggregateType();
371418
}
372419

373420
//===----------------------------------------------------------------------===//
@@ -770,7 +817,7 @@ SymbolicValue SymbolicValue::lookThroughSingleElementAggregates() const {
770817
while (1) {
771818
if (result.getKind() != Aggregate)
772819
return result;
773-
auto elts = result.getAggregateValue();
820+
auto elts = result.getAggregateMembers();
774821
if (elts.size() != 1)
775822
return result;
776823
result = elts[0];
@@ -1009,7 +1056,7 @@ static SymbolicValue getIndexedElement(SymbolicValue aggregate,
10091056
elt = aggregate.getStoredElements(arrayEltTy)[elementNo];
10101057
eltType = arrayEltTy;
10111058
} else {
1012-
elt = aggregate.getAggregateValue()[elementNo];
1059+
elt = aggregate.getAggregateMembers()[elementNo];
10131060
if (auto *decl = type->getStructOrBoundGenericStruct()) {
10141061
eltType = decl->getStoredProperties()[elementNo]->getType();
10151062
} else if (auto tuple = type->getAs<TupleType>()) {
@@ -1063,7 +1110,7 @@ static SymbolicValue setIndexedElement(SymbolicValue aggregate,
10631110

10641111
SmallVector<SymbolicValue, 4> newElts(numMembers,
10651112
SymbolicValue::getUninitMemory());
1066-
aggregate = SymbolicValue::getAggregate(newElts, allocator);
1113+
aggregate = SymbolicValue::getAggregate(newElts, type, allocator);
10671114
}
10681115

10691116
assert((aggregate.getKind() == SymbolicValue::Aggregate ||
@@ -1080,7 +1127,7 @@ static SymbolicValue setIndexedElement(SymbolicValue aggregate,
10801127
oldElts = aggregate.getStoredElements(arrayEltTy);
10811128
eltType = arrayEltTy;
10821129
} else {
1083-
oldElts = aggregate.getAggregateValue();
1130+
oldElts = aggregate.getAggregateMembers();
10841131
if (auto *decl = type->getStructOrBoundGenericStruct()) {
10851132
eltType = decl->getStoredProperties()[elementNo]->getType();
10861133
} else if (auto tuple = type->getAs<TupleType>()) {
@@ -1097,8 +1144,12 @@ static SymbolicValue setIndexedElement(SymbolicValue aggregate,
10971144
setIndexedElement(newElts[elementNo], accessPath.drop_front(), newElement,
10981145
eltType, allocator);
10991146

1100-
if (aggregate.getKind() == SymbolicValue::Aggregate)
1101-
return SymbolicValue::getAggregate(newElts, allocator);
1147+
if (aggregate.getKind() == SymbolicValue::Aggregate) {
1148+
Type aggregateType = aggregate.getAggregateType();
1149+
assert(aggregateType->isEqual(type) &&
1150+
"input type does not match the type of the aggregate");
1151+
return SymbolicValue::getAggregate(newElts, aggregateType, allocator);
1152+
}
11021153

11031154
return aggregate = SymbolicValue::getSymbolicArrayStorage(
11041155
newElts, eltType->getCanonicalType(), allocator);

lib/SILOptimizer/Mandatory/OSLogOptimization.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ static bool checkOSLogMessageIsConstant(SingleValueInstruction *osLogMessage,
722722
// The first (and only) property of OSLogMessage is the OSLogInterpolation
723723
// instance.
724724
SymbolicValue osLogInterpolationValue =
725-
osLogMessageValueOpt->getAggregateValue()[0];
725+
osLogMessageValueOpt->getAggregateMembers()[0];
726726
if (!osLogInterpolationValue.isConstant()) {
727727
diagnose(astContext, sourceLoc, diag::oslog_non_constant_interpolation);
728728
return true;
@@ -743,7 +743,7 @@ static bool checkOSLogMessageIsConstant(SingleValueInstruction *osLogMessage,
743743

744744
auto propertyDecls = interpolationStruct->getStoredProperties();
745745
ArrayRef<SymbolicValue> propertyValues =
746-
osLogInterpolationValue.getAggregateValue();
746+
osLogInterpolationValue.getAggregateMembers();
747747
auto propValueI = propertyValues.begin();
748748
bool errorDetected = false;
749749

0 commit comments

Comments
 (0)