Skip to content

Commit 3328daf

Browse files
author
Marc Rasi
committed
cont evaluator part 2: memory
1 parent c93e328 commit 3328daf

File tree

4 files changed

+478
-6
lines changed

4 files changed

+478
-6
lines changed

include/swift/SIL/SILConstants.h

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

2929
struct APIntSymbolicValue;
3030
struct ArraySymbolicValue;
31+
struct DerivedAddressValue;
3132
struct EnumWithPayloadSymbolicValue;
33+
struct SymbolicValueMemoryObject;
3234
struct UnknownSymbolicValue;
3335

3436
/// When we fail to constant fold a value, this captures a reason why,
@@ -65,6 +67,10 @@ enum class UnknownReason {
6567
class SymbolicValue {
6668
private:
6769
enum RepresentationKind {
70+
/// This value is an alloc stack that is has not (yet) been initialized
71+
/// by flow-sensitive analysis.
72+
RK_UninitMemory,
73+
6874
/// This symbolic value cannot be determined, carries multiple values
6975
/// (i.e., varies dynamically at the top level), or is of some type that
7076
/// we cannot analyze and propagate (e.g. NSObject).
@@ -88,6 +94,12 @@ class SymbolicValue {
8894
/// This value is an array, struct, or tuple of constants. This is
8995
/// tracked by the "aggregate" member of the value union.
9096
RK_Aggregate,
97+
98+
/// This represents a direct reference to the address of a memory object.
99+
RK_DirectAddress,
100+
101+
/// This represents an index *into* a memory object.
102+
RK_DerivedAddress,
91103
};
92104

93105
union {
@@ -111,6 +123,14 @@ class SymbolicValue {
111123
/// When this SymbolicValue is of "Aggregate" kind, this pointer stores
112124
/// information about the array elements and count.
113125
const SymbolicValue *aggregate;
126+
127+
/// When the representationKind is "DirectAddress", this pointer is the
128+
/// memory object referenced.
129+
SymbolicValueMemoryObject *directAddress;
130+
131+
/// When this SymbolicValue is of "DerivedAddress" kind, this pointer stores
132+
/// information about the memory object and access path of the access.
133+
DerivedAddressValue *derivedAddress;
114134
} value;
115135

116136
RepresentationKind representationKind : 8;
@@ -146,6 +166,13 @@ class SymbolicValue {
146166

147167
/// This can be an array, struct, tuple, etc.
148168
Aggregate,
169+
170+
/// This value represents the address of, or into, a memory object.
171+
Address,
172+
173+
/// These values are generally only seen internally to the system, external
174+
/// clients shouldn't have to deal with them.
175+
UninitMemory
149176
};
150177

151178
/// For constant values, return the type classification of this value.
@@ -154,7 +181,7 @@ class SymbolicValue {
154181
/// Return true if this represents a constant value.
155182
bool isConstant() const {
156183
auto kind = getKind();
157-
return kind != Unknown;
184+
return kind != Unknown && kind != UninitMemory;
158185
}
159186

160187
static SymbolicValue getUnknown(SILNode *node, UnknownReason reason,
@@ -173,6 +200,12 @@ class SymbolicValue {
173200
/// Return the reason an unknown result was generated.
174201
UnknownReason getUnknownReason() const;
175202

203+
static SymbolicValue getUninitMemory() {
204+
SymbolicValue result;
205+
result.representationKind = RK_UninitMemory;
206+
return result;
207+
}
208+
176209
static SymbolicValue getMetatype(CanType type) {
177210
SymbolicValue result;
178211
result.representationKind = RK_Metatype;
@@ -212,6 +245,25 @@ class SymbolicValue {
212245

213246
ArrayRef<SymbolicValue> getAggregateValue() const;
214247

248+
/// Return a symbolic value that represents the address of a memory object.
249+
static SymbolicValue getAddress(SymbolicValueMemoryObject *memoryObject) {
250+
SymbolicValue result;
251+
result.representationKind = RK_DirectAddress;
252+
result.value.directAddress = memoryObject;
253+
return result;
254+
}
255+
256+
/// Return a symbolic value that represents the address of a memory object
257+
/// indexed by a path.
258+
static SymbolicValue getAddress(SymbolicValueMemoryObject *memoryObject,
259+
ArrayRef<unsigned> indices,
260+
llvm::BumpPtrAllocator &allocator);
261+
262+
/// Return the memory object of this reference along with any access path
263+
/// indices involved.
264+
SymbolicValueMemoryObject *
265+
getAddressValue(SmallVectorImpl<unsigned> &accessPath) const;
266+
215267
//===--------------------------------------------------------------------===//
216268
// Helpers
217269

@@ -241,6 +293,29 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, SymbolicValue val) {
241293
return os;
242294
}
243295

296+
/// This is a representation of a memory object referred to be an address.
297+
/// Memory objects may be mutated over their lifetime, but their overall type
298+
/// remains the same.
299+
struct SymbolicValueMemoryObject {
300+
Type getType() const { return type; }
301+
302+
SymbolicValue getValue() const { return value; }
303+
void setValue(SymbolicValue newValue) { value = newValue; }
304+
305+
/// Create a new memory object whose overall type is as specified.
306+
static SymbolicValueMemoryObject *create(Type type, SymbolicValue value,
307+
llvm::BumpPtrAllocator &allocator);
308+
309+
private:
310+
const Type type;
311+
SymbolicValue value;
312+
313+
SymbolicValueMemoryObject(Type type, SymbolicValue value)
314+
: type(type), value(value) {}
315+
SymbolicValueMemoryObject(const SymbolicValueMemoryObject &) = delete;
316+
void operator=(const SymbolicValueMemoryObject &) = delete;
317+
};
318+
244319
} // end namespace swift
245320

246321
#endif

lib/SIL/SILConstants.cpp

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ static InFlightDiagnostic diagnose(ASTContext &Context, SourceLoc loc,
3030
void SymbolicValue::print(llvm::raw_ostream &os, unsigned indent) const {
3131
os.indent(indent);
3232
switch (representationKind) {
33+
case RK_UninitMemory:
34+
os << "uninit\n";
35+
return;
3336
case RK_Unknown: {
3437
os << "unknown(" << (int)getUnknownReason() << "): ";
3538
getUnknownNode()->dump();
@@ -69,6 +72,16 @@ void SymbolicValue::print(llvm::raw_ostream &os, unsigned indent) const {
6972
return;
7073
}
7174
}
75+
case RK_DirectAddress:
76+
case RK_DerivedAddress: {
77+
SmallVector<unsigned, 4> accessPath;
78+
SymbolicValueMemoryObject *memObject = getAddressValue(accessPath);
79+
os << "Address[" << memObject->getType() << "] ";
80+
interleave(accessPath.begin(), accessPath.end(),
81+
[&](unsigned idx) { os << idx; }, [&]() { os << ", "; });
82+
os << "\n";
83+
break;
84+
}
7285
}
7386
}
7487

@@ -78,6 +91,8 @@ void SymbolicValue::dump() const { print(llvm::errs()); }
7891
/// multiple forms for efficiency, but provide a simpler interface to clients.
7992
SymbolicValue::Kind SymbolicValue::getKind() const {
8093
switch (representationKind) {
94+
case RK_UninitMemory:
95+
return UninitMemory;
8196
case RK_Unknown:
8297
return Unknown;
8398
case RK_Metatype:
@@ -89,6 +104,9 @@ SymbolicValue::Kind SymbolicValue::getKind() const {
89104
case RK_Integer:
90105
case RK_IntegerInline:
91106
return Integer;
107+
case RK_DirectAddress:
108+
case RK_DerivedAddress:
109+
return Address;
92110
}
93111
}
94112

@@ -98,6 +116,7 @@ SymbolicValue
98116
SymbolicValue::cloneInto(llvm::BumpPtrAllocator &allocator) const {
99117
auto thisRK = representationKind;
100118
switch (thisRK) {
119+
case RK_UninitMemory:
101120
case RK_Unknown:
102121
case RK_Metatype:
103122
case RK_Function:
@@ -112,9 +131,29 @@ SymbolicValue::cloneInto(llvm::BumpPtrAllocator &allocator) const {
112131
results.push_back(elt.cloneInto(allocator));
113132
return getAggregate(results, allocator);
114133
}
134+
case RK_DirectAddress:
135+
case RK_DerivedAddress: {
136+
SmallVector<unsigned, 4> accessPath;
137+
auto *memObject = getAddressValue(accessPath);
138+
auto *newMemObject = SymbolicValueMemoryObject::create(
139+
memObject->getType(), memObject->getValue(), allocator);
140+
return getAddress(newMemObject, accessPath, allocator);
141+
}
115142
}
116143
}
117144

145+
//===----------------------------------------------------------------------===//
146+
// SymbolicValueMemoryObject implementation
147+
//===----------------------------------------------------------------------===//
148+
149+
SymbolicValueMemoryObject *
150+
SymbolicValueMemoryObject::create(Type type, SymbolicValue value,
151+
llvm::BumpPtrAllocator &allocator) {
152+
auto result = allocator.Allocate<SymbolicValueMemoryObject>();
153+
new (result) SymbolicValueMemoryObject(type, value);
154+
return result;
155+
}
156+
118157
//===----------------------------------------------------------------------===//
119158
// Integers
120159
//===----------------------------------------------------------------------===//
@@ -269,6 +308,91 @@ UnknownReason SymbolicValue::getUnknownReason() const {
269308
return value.unknown->reason;
270309
}
271310

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

0 commit comments

Comments
 (0)