@@ -45,12 +45,7 @@ class ValueHandleBase {
45
45
// /
46
46
// / This is to avoid having a vtable for the light-weight handle pointers. The
47
47
// / fully general Callback version does have a vtable.
48
- enum HandleBaseKind {
49
- Assert,
50
- Callback,
51
- Tracking,
52
- Weak
53
- };
48
+ enum HandleBaseKind { Assert, Callback, Weak };
54
49
55
50
private:
56
51
PointerIntPair<ValueHandleBase**, 2 , HandleBaseKind> PrevPair;
@@ -165,6 +160,10 @@ class WeakVH : public ValueHandleBase {
165
160
operator Value*() const {
166
161
return getValPtr ();
167
162
}
163
+
164
+ bool pointsToAliveValue () const {
165
+ return ValueHandleBase::isValid (getValPtr ());
166
+ }
168
167
};
169
168
170
169
// Specialize simplify_type to allow WeakVH to participate in
@@ -275,46 +274,65 @@ struct isPodLike<AssertingVH<T> > {
275
274
#endif
276
275
};
277
276
278
-
279
277
// / \brief Value handle that tracks a Value across RAUW.
280
278
// /
281
279
// / TrackingVH is designed for situations where a client needs to hold a handle
282
280
// / to a Value (or subclass) across some operations which may move that value,
283
281
// / but should never destroy it or replace it with some unacceptable type.
284
282
// /
285
- // / It is an error to do anything with a TrackingVH whose value has been
286
- // / destroyed, except to destruct it.
287
- // /
288
283
// / It is an error to attempt to replace a value with one of a type which is
289
284
// / incompatible with any of its outstanding TrackingVHs.
290
- template <typename ValueTy>
291
- class TrackingVH : public ValueHandleBase {
292
- void CheckValidity () const {
293
- Value *VP = ValueHandleBase::getValPtr ();
294
-
295
- // Null is always ok.
296
- if (!VP) return ;
285
+ // /
286
+ // / It is an error to read from a TrackingVH that does not point to a valid
287
+ // / value. A TrackingVH is said to not point to a valid value if either it
288
+ // / hasn't yet been assigned a value yet or because the value it was tracking
289
+ // / has since been deleted.
290
+ // /
291
+ // / Assigning a value to a TrackingVH is always allowed, even if said TrackingVH
292
+ // / no longer points to a valid value.
293
+ template <typename ValueTy> class TrackingVH {
294
+ WeakVH InnerHandle;
297
295
298
- // Check that this value is valid (i.e., it hasn't been deleted). We
299
- // explicitly delay this check until access to avoid requiring clients to be
300
- // unnecessarily careful w.r.t. destruction.
301
- assert (ValueHandleBase::isValid (VP) && " Tracked Value was deleted!" );
296
+ public:
297
+ ValueTy *getValPtr () const {
298
+ // HLSL Change begin
299
+ // The original upstream change will assert here when accessing a TrackingVH
300
+ // is deleted.
301
+ //
302
+ // However, the llvm code that DXC forked has the implicit code like:
303
+ // TrackingVH V = nullptr;
304
+ //
305
+ // It will invoke setValPtr(nullptr) and then getValPtr(nullptr). So pull in
306
+ // the original upstream change in DXC will always assert here for debug
307
+ // build even this code is valid.
308
+ //
309
+ // The original upstream change works because of another upstream change
310
+ // https://github.com/llvm/llvm-project/commit/70a6051ddfd5f04777f2bc42503bb11bc8f1723a
311
+ // cleaned up the problematic code in DXC already.
312
+ //
313
+ // Untill we decide to pull that upstream change into DXC, DXC should follow
314
+ // the original TrackingVH implementation. return Null is always ok here
315
+ // instead of assert it.
316
+ if (InnerHandle.operator llvm::Value *() == nullptr )
317
+ return nullptr ;
318
+ // HLSL Change end.
319
+
320
+ assert (InnerHandle.pointsToAliveValue () &&
321
+ " TrackingVH must be non-null and valid on dereference!" );
302
322
303
323
// Check that the value is a member of the correct subclass. We would like
304
324
// to check this property on assignment for better debugging, but we don't
305
325
// want to require a virtual interface on this VH. Instead we allow RAUW to
306
326
// replace this value with a value of an invalid type, and check it here.
307
- assert (isa<ValueTy>(VP ) &&
327
+ assert (isa<ValueTy>(InnerHandle ) &&
308
328
" Tracked Value was replaced by one with an invalid type!" );
329
+ return cast<ValueTy>(InnerHandle);
309
330
}
310
331
311
- ValueTy *getValPtr () const {
312
- CheckValidity ();
313
- return (ValueTy*)ValueHandleBase::getValPtr ();
314
- }
315
332
void setValPtr (ValueTy *P) {
316
- CheckValidity ();
317
- ValueHandleBase::operator =(GetAsValue (P));
333
+ // Assigning to non-valid TrackingVH's are fine so we just unconditionally
334
+ // assign here.
335
+ InnerHandle = GetAsValue (P);
318
336
}
319
337
320
338
// Convert a ValueTy*, which may be const, to the type the base
@@ -323,9 +341,11 @@ class TrackingVH : public ValueHandleBase {
323
341
static Value *GetAsValue (const Value *V) { return const_cast <Value*>(V); }
324
342
325
343
public:
326
- TrackingVH () : ValueHandleBase(Tracking) {}
327
- TrackingVH (ValueTy *P) : ValueHandleBase(Tracking, GetAsValue(P)) {}
328
- TrackingVH (const TrackingVH &RHS) : ValueHandleBase(Tracking, RHS) {}
344
+ TrackingVH () {}
345
+ TrackingVH (ValueTy *P) { setValPtr (P); }
346
+ TrackingVH (const TrackingVH &RHS) {
347
+ setValPtr (RHS.getValPtr ());
348
+ } // HLSL Change
329
349
330
350
operator ValueTy*() const {
331
351
return getValPtr ();
0 commit comments