Skip to content

Commit 518f26a

Browse files
authored
Merge pull request #19657 from apple/marcrasi-const-evaluator-part-2
2 parents b463f52 + 8dcf89c commit 518f26a

File tree

5 files changed

+577
-18
lines changed

5 files changed

+577
-18
lines changed

include/swift/SIL/SILConstants.h

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ class SerializedSILLoader;
3030

3131
struct APIntSymbolicValue;
3232
struct ArraySymbolicValue;
33+
struct DerivedAddressValue;
3334
struct EnumWithPayloadSymbolicValue;
35+
struct SymbolicValueMemoryObject;
3436
struct UnknownSymbolicValue;
3537

3638
extern llvm::cl::opt<unsigned> ConstExprLimit;
@@ -69,6 +71,10 @@ enum class UnknownReason {
6971
class SymbolicValue {
7072
private:
7173
enum RepresentationKind {
74+
/// This value is an alloc stack that has not (yet) been initialized
75+
/// by flow-sensitive analysis.
76+
RK_UninitMemory,
77+
7278
/// This symbolic value cannot be determined, carries multiple values
7379
/// (i.e., varies dynamically at the top level), or is of some type that
7480
/// we cannot analyze and propagate (e.g. NSObject).
@@ -92,6 +98,12 @@ class SymbolicValue {
9298
/// This value is a struct or tuple of constants. This is tracked by the
9399
/// "aggregate" member of the value union.
94100
RK_Aggregate,
101+
102+
/// This represents the address of a memory object.
103+
RK_DirectAddress,
104+
105+
/// This represents an index *into* a memory object.
106+
RK_DerivedAddress,
95107
};
96108

97109
union {
@@ -115,6 +127,14 @@ class SymbolicValue {
115127
/// When this SymbolicValue is of "Aggregate" kind, this pointer stores
116128
/// information about the array elements and count.
117129
const SymbolicValue *aggregate;
130+
131+
/// When the representationKind is "DirectAddress", this pointer is the
132+
/// memory object referenced.
133+
SymbolicValueMemoryObject *directAddress;
134+
135+
/// When this SymbolicValue is of "DerivedAddress" kind, this pointer stores
136+
/// information about the memory object and access path of the access.
137+
DerivedAddressValue *derivedAddress;
118138
} value;
119139

120140
RepresentationKind representationKind : 8;
@@ -150,6 +170,13 @@ class SymbolicValue {
150170

151171
/// This can be an array, struct, tuple, etc.
152172
Aggregate,
173+
174+
/// This value represents the address of, or into, a memory object.
175+
Address,
176+
177+
/// These values are generally only seen internally to the system, external
178+
/// clients shouldn't have to deal with them.
179+
UninitMemory
153180
};
154181

155182
/// For constant values, return the type classification of this value.
@@ -158,7 +185,7 @@ class SymbolicValue {
158185
/// Return true if this represents a constant value.
159186
bool isConstant() const {
160187
auto kind = getKind();
161-
return kind != Unknown;
188+
return kind != Unknown && kind != UninitMemory;
162189
}
163190

164191
static SymbolicValue getUnknown(SILNode *node, UnknownReason reason,
@@ -177,6 +204,12 @@ class SymbolicValue {
177204
/// Return the reason an unknown result was generated.
178205
UnknownReason getUnknownReason() const;
179206

207+
static SymbolicValue getUninitMemory() {
208+
SymbolicValue result;
209+
result.representationKind = RK_UninitMemory;
210+
return result;
211+
}
212+
180213
static SymbolicValue getMetatype(CanType type) {
181214
SymbolicValue result;
182215
result.representationKind = RK_Metatype;
@@ -216,6 +249,25 @@ class SymbolicValue {
216249

217250
ArrayRef<SymbolicValue> getAggregateValue() const;
218251

252+
/// Return a symbolic value that represents the address of a memory object.
253+
static SymbolicValue getAddress(SymbolicValueMemoryObject *memoryObject) {
254+
SymbolicValue result;
255+
result.representationKind = RK_DirectAddress;
256+
result.value.directAddress = memoryObject;
257+
return result;
258+
}
259+
260+
/// Return a symbolic value that represents the address of a memory object
261+
/// indexed by a path.
262+
static SymbolicValue getAddress(SymbolicValueMemoryObject *memoryObject,
263+
ArrayRef<unsigned> indices,
264+
ASTContext &astContext);
265+
266+
/// Return the memory object of this reference along with any access path
267+
/// indices involved.
268+
SymbolicValueMemoryObject *
269+
getAddressValue(SmallVectorImpl<unsigned> &accessPath) const;
270+
219271
//===--------------------------------------------------------------------===//
220272
// Helpers
221273

@@ -247,6 +299,29 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, SymbolicValue val) {
247299
return os;
248300
}
249301

302+
/// This is a representation of a memory object referred to by an address.
303+
/// Memory objects may be mutated over their lifetime, but their overall type
304+
/// remains the same.
305+
struct SymbolicValueMemoryObject {
306+
Type getType() const { return type; }
307+
308+
SymbolicValue getValue() const { return value; }
309+
void setValue(SymbolicValue newValue) { value = newValue; }
310+
311+
/// Create a new memory object whose overall type is as specified.
312+
static SymbolicValueMemoryObject *create(Type type, SymbolicValue value,
313+
ASTContext &astContext);
314+
315+
private:
316+
const Type type;
317+
SymbolicValue value;
318+
319+
SymbolicValueMemoryObject(Type type, SymbolicValue value)
320+
: type(type), value(value) {}
321+
SymbolicValueMemoryObject(const SymbolicValueMemoryObject &) = delete;
322+
void operator=(const SymbolicValueMemoryObject &) = delete;
323+
};
324+
250325
} // end namespace swift
251326

252327
#endif

lib/SIL/SILConstants.cpp

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ static InFlightDiagnostic diagnose(ASTContext &Context, SourceLoc loc,
3737
void SymbolicValue::print(llvm::raw_ostream &os, unsigned indent) const {
3838
os.indent(indent);
3939
switch (representationKind) {
40+
case RK_UninitMemory:
41+
os << "uninit\n";
42+
return;
4043
case RK_Unknown: {
4144
os << "unknown(" << (int)getUnknownReason() << "): ";
4245
getUnknownNode()->dump();
@@ -76,6 +79,16 @@ void SymbolicValue::print(llvm::raw_ostream &os, unsigned indent) const {
7679
return;
7780
}
7881
}
82+
case RK_DirectAddress:
83+
case RK_DerivedAddress: {
84+
SmallVector<unsigned, 4> accessPath;
85+
SymbolicValueMemoryObject *memObject = getAddressValue(accessPath);
86+
os << "Address[" << memObject->getType() << "] ";
87+
interleave(accessPath.begin(), accessPath.end(),
88+
[&](unsigned idx) { os << idx; }, [&]() { os << ", "; });
89+
os << "\n";
90+
break;
91+
}
7992
}
8093
}
8194

@@ -85,6 +98,8 @@ void SymbolicValue::dump() const { print(llvm::errs()); }
8598
/// multiple forms for efficiency, but provide a simpler interface to clients.
8699
SymbolicValue::Kind SymbolicValue::getKind() const {
87100
switch (representationKind) {
101+
case RK_UninitMemory:
102+
return UninitMemory;
88103
case RK_Unknown:
89104
return Unknown;
90105
case RK_Metatype:
@@ -96,6 +111,9 @@ SymbolicValue::Kind SymbolicValue::getKind() const {
96111
case RK_Integer:
97112
case RK_IntegerInline:
98113
return Integer;
114+
case RK_DirectAddress:
115+
case RK_DerivedAddress:
116+
return Address;
99117
}
100118
}
101119

@@ -105,6 +123,7 @@ SymbolicValue
105123
SymbolicValue::cloneInto(ASTContext &astContext) const {
106124
auto thisRK = representationKind;
107125
switch (thisRK) {
126+
case RK_UninitMemory:
108127
case RK_Unknown:
109128
case RK_Metatype:
110129
case RK_Function:
@@ -120,9 +139,30 @@ SymbolicValue::cloneInto(ASTContext &astContext) const {
120139
results.push_back(elt.cloneInto(astContext));
121140
return getAggregate(results, astContext);
122141
}
142+
case RK_DirectAddress:
143+
case RK_DerivedAddress: {
144+
SmallVector<unsigned, 4> accessPath;
145+
auto *memObject = getAddressValue(accessPath);
146+
auto *newMemObject = SymbolicValueMemoryObject::create(
147+
memObject->getType(), memObject->getValue(), astContext);
148+
return getAddress(newMemObject, accessPath, astContext);
149+
}
123150
}
124151
}
125152

153+
//===----------------------------------------------------------------------===//
154+
// SymbolicValueMemoryObject implementation
155+
//===----------------------------------------------------------------------===//
156+
157+
SymbolicValueMemoryObject *
158+
SymbolicValueMemoryObject::create(Type type, SymbolicValue value,
159+
ASTContext &astContext) {
160+
auto *result = astContext.Allocate(sizeof(SymbolicValueMemoryObject),
161+
alignof(SymbolicValueMemoryObject));
162+
new (result) SymbolicValueMemoryObject(type, value);
163+
return (SymbolicValueMemoryObject *)result;
164+
}
165+
126166
//===----------------------------------------------------------------------===//
127167
// Integers
128168
//===----------------------------------------------------------------------===//
@@ -225,7 +265,7 @@ struct alignas(SourceLoc) UnknownSymbolicValue final
225265
ASTContext &astContext) {
226266
auto byteSize =
227267
UnknownSymbolicValue::totalSizeToAlloc<SourceLoc>(elements.size());
228-
auto rawMem = astContext.Allocate(byteSize, alignof(UnknownSymbolicValue));
268+
auto *rawMem = astContext.Allocate(byteSize, alignof(UnknownSymbolicValue));
229269

230270
// Placement-new the value inside the memory we just allocated.
231271
auto value = ::new (rawMem) UnknownSymbolicValue(
@@ -279,6 +319,91 @@ UnknownReason SymbolicValue::getUnknownReason() const {
279319
return value.unknown->reason;
280320
}
281321

322+
//===----------------------------------------------------------------------===//
323+
// Addresses
324+
//===----------------------------------------------------------------------===//
325+
326+
namespace swift {
327+
328+
/// This is the representation of a derived address. A derived address refers
329+
/// to a memory object along with an access path that drills into it.
330+
struct DerivedAddressValue final
331+
: private llvm::TrailingObjects<DerivedAddressValue, unsigned> {
332+
friend class llvm::TrailingObjects<DerivedAddressValue, unsigned>;
333+
334+
SymbolicValueMemoryObject *memoryObject;
335+
336+
/// This is the number of indices in the derived address.
337+
const unsigned numElements;
338+
339+
static DerivedAddressValue *create(SymbolicValueMemoryObject *memoryObject,
340+
ArrayRef<unsigned> elements,
341+
ASTContext &astContext) {
342+
auto byteSize =
343+
DerivedAddressValue::totalSizeToAlloc<unsigned>(elements.size());
344+
auto *rawMem = astContext.Allocate(byteSize, alignof(DerivedAddressValue));
345+
346+
// Placement initialize the object.
347+
auto dav =
348+
::new (rawMem) DerivedAddressValue(memoryObject, elements.size());
349+
std::uninitialized_copy(elements.begin(), elements.end(),
350+
dav->getTrailingObjects<unsigned>());
351+
return dav;
352+
}
353+
354+
/// Return the access path for this derived address, which is an array of
355+
/// indices drilling into the memory object.
356+
ArrayRef<unsigned> getElements() const {
357+
return {getTrailingObjects<unsigned>(), numElements};
358+
}
359+
360+
// This is used by the llvm::TrailingObjects base class.
361+
size_t numTrailingObjects(OverloadToken<unsigned>) const {
362+
return numElements;
363+
}
364+
365+
private:
366+
DerivedAddressValue() = delete;
367+
DerivedAddressValue(const DerivedAddressValue &) = delete;
368+
DerivedAddressValue(SymbolicValueMemoryObject *memoryObject,
369+
unsigned numElements)
370+
: memoryObject(memoryObject), numElements(numElements) {}
371+
};
372+
} // end namespace swift
373+
374+
/// Return a symbolic value that represents the address of a memory object
375+
/// indexed by a path.
376+
SymbolicValue SymbolicValue::getAddress(SymbolicValueMemoryObject *memoryObject,
377+
ArrayRef<unsigned> indices,
378+
ASTContext &astContext) {
379+
if (indices.empty())
380+
return getAddress(memoryObject);
381+
382+
auto dav = DerivedAddressValue::create(memoryObject, indices, astContext);
383+
SymbolicValue result;
384+
result.representationKind = RK_DerivedAddress;
385+
result.value.derivedAddress = dav;
386+
return result;
387+
}
388+
389+
/// Return the memory object of this reference along with any access path
390+
/// indices involved.
391+
SymbolicValueMemoryObject *
392+
SymbolicValue::getAddressValue(SmallVectorImpl<unsigned> &accessPath) const {
393+
assert(getKind() == Address);
394+
395+
accessPath.clear();
396+
if (representationKind == RK_DirectAddress)
397+
return value.directAddress;
398+
assert(representationKind == RK_DerivedAddress);
399+
400+
auto *dav = value.derivedAddress;
401+
402+
// The first entry is the object ID, the rest are indices in the accessPath.
403+
accessPath.assign(dav->getElements().begin(), dav->getElements().end());
404+
return dav->memoryObject;
405+
}
406+
282407
//===----------------------------------------------------------------------===//
283408
// Higher level code
284409
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)