1 | //===- ValueHandle.h - Value Smart Pointer classes --------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file declares the ValueHandle class and its sub-classes. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_IR_VALUEHANDLE_H |
14 | #define LLVM_IR_VALUEHANDLE_H |
15 | |
16 | #include "llvm/ADT/DenseMapInfo.h" |
17 | #include "llvm/ADT/PointerIntPair.h" |
18 | #include "llvm/IR/Value.h" |
19 | #include "llvm/Support/Casting.h" |
20 | #include <cassert> |
21 | |
22 | namespace llvm { |
23 | |
24 | /// This is the common base class of value handles. |
25 | /// |
26 | /// ValueHandle's are smart pointers to Value's that have special behavior when |
27 | /// the value is deleted or ReplaceAllUsesWith'd. See the specific handles |
28 | /// below for details. |
29 | class ValueHandleBase { |
30 | friend class Value; |
31 | |
32 | protected: |
33 | /// This indicates what sub class the handle actually is. |
34 | /// |
35 | /// This is to avoid having a vtable for the light-weight handle pointers. The |
36 | /// fully general Callback version does have a vtable. |
37 | enum HandleBaseKind { Assert, Callback, Weak, WeakTracking }; |
38 | |
39 | ValueHandleBase(const ValueHandleBase &RHS) |
40 | : ValueHandleBase(RHS.PrevPair.getInt(), RHS) {} |
41 | |
42 | ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS) |
43 | : PrevPair(nullptr, Kind), Val(RHS.getValPtr()) { |
44 | if (isValid(V: getValPtr())) |
45 | AddToExistingUseList(List: RHS.getPrevPtr()); |
46 | } |
47 | |
48 | private: |
49 | PointerIntPair<ValueHandleBase**, 2, HandleBaseKind> PrevPair; |
50 | ValueHandleBase *Next = nullptr; |
51 | Value *Val = nullptr; |
52 | |
53 | void setValPtr(Value *V) { Val = V; } |
54 | |
55 | public: |
56 | explicit ValueHandleBase(HandleBaseKind Kind) |
57 | : PrevPair(nullptr, Kind) {} |
58 | ValueHandleBase(HandleBaseKind Kind, Value *V) |
59 | : PrevPair(nullptr, Kind), Val(V) { |
60 | if (isValid(V: getValPtr())) |
61 | AddToUseList(); |
62 | } |
63 | |
64 | ~ValueHandleBase() { |
65 | if (isValid(V: getValPtr())) |
66 | RemoveFromUseList(); |
67 | } |
68 | |
69 | Value *operator=(Value *RHS) { |
70 | if (getValPtr() == RHS) |
71 | return RHS; |
72 | if (isValid(V: getValPtr())) |
73 | RemoveFromUseList(); |
74 | setValPtr(RHS); |
75 | if (isValid(V: getValPtr())) |
76 | AddToUseList(); |
77 | return RHS; |
78 | } |
79 | |
80 | Value *operator=(const ValueHandleBase &RHS) { |
81 | if (getValPtr() == RHS.getValPtr()) |
82 | return RHS.getValPtr(); |
83 | if (isValid(V: getValPtr())) |
84 | RemoveFromUseList(); |
85 | setValPtr(RHS.getValPtr()); |
86 | if (isValid(V: getValPtr())) |
87 | AddToExistingUseList(List: RHS.getPrevPtr()); |
88 | return getValPtr(); |
89 | } |
90 | |
91 | Value *operator->() const { return getValPtr(); } |
92 | Value &operator*() const { |
93 | Value *V = getValPtr(); |
94 | assert(V && "Dereferencing deleted ValueHandle" ); |
95 | return *V; |
96 | } |
97 | |
98 | protected: |
99 | Value *getValPtr() const { return Val; } |
100 | |
101 | static bool isValid(Value *V) { |
102 | return V && |
103 | V != DenseMapInfo<Value *>::getEmptyKey() && |
104 | V != DenseMapInfo<Value *>::getTombstoneKey(); |
105 | } |
106 | |
107 | /// Remove this ValueHandle from its current use list. |
108 | void RemoveFromUseList(); |
109 | |
110 | /// Clear the underlying pointer without clearing the use list. |
111 | /// |
112 | /// This should only be used if a derived class has manually removed the |
113 | /// handle from the use list. |
114 | void clearValPtr() { setValPtr(nullptr); } |
115 | |
116 | public: |
117 | // Callbacks made from Value. |
118 | static void ValueIsDeleted(Value *V); |
119 | static void ValueIsRAUWd(Value *Old, Value *New); |
120 | |
121 | private: |
122 | // Internal implementation details. |
123 | ValueHandleBase **getPrevPtr() const { return PrevPair.getPointer(); } |
124 | HandleBaseKind getKind() const { return PrevPair.getInt(); } |
125 | void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); } |
126 | |
127 | /// Add this ValueHandle to the use list for V. |
128 | /// |
129 | /// List is the address of either the head of the list or a Next node within |
130 | /// the existing use list. |
131 | void AddToExistingUseList(ValueHandleBase **List); |
132 | |
133 | /// Add this ValueHandle to the use list after Node. |
134 | void AddToExistingUseListAfter(ValueHandleBase *Node); |
135 | |
136 | /// Add this ValueHandle to the use list for V. |
137 | void AddToUseList(); |
138 | }; |
139 | |
140 | /// A nullable Value handle that is nullable. |
141 | /// |
142 | /// This is a value handle that points to a value, and nulls itself |
143 | /// out if that value is deleted. |
144 | class WeakVH : public ValueHandleBase { |
145 | public: |
146 | WeakVH() : ValueHandleBase(Weak) {} |
147 | WeakVH(Value *P) : ValueHandleBase(Weak, P) {} |
148 | WeakVH(const WeakVH &RHS) |
149 | : ValueHandleBase(Weak, RHS) {} |
150 | |
151 | WeakVH &operator=(const WeakVH &RHS) = default; |
152 | |
153 | Value *operator=(Value *RHS) { |
154 | return ValueHandleBase::operator=(RHS); |
155 | } |
156 | Value *operator=(const ValueHandleBase &RHS) { |
157 | return ValueHandleBase::operator=(RHS); |
158 | } |
159 | |
160 | operator Value*() const { |
161 | return getValPtr(); |
162 | } |
163 | }; |
164 | |
165 | // Specialize simplify_type to allow WeakVH to participate in |
166 | // dyn_cast, isa, etc. |
167 | template <> struct simplify_type<WeakVH> { |
168 | using SimpleType = Value *; |
169 | |
170 | static SimpleType getSimplifiedValue(WeakVH &WVH) { return WVH; } |
171 | }; |
172 | template <> struct simplify_type<const WeakVH> { |
173 | using SimpleType = Value *; |
174 | |
175 | static SimpleType getSimplifiedValue(const WeakVH &WVH) { return WVH; } |
176 | }; |
177 | |
178 | // Specialize DenseMapInfo to allow WeakVH to participate in DenseMap. |
179 | template <> struct DenseMapInfo<WeakVH> { |
180 | static inline WeakVH getEmptyKey() { |
181 | return WeakVH(DenseMapInfo<Value *>::getEmptyKey()); |
182 | } |
183 | |
184 | static inline WeakVH getTombstoneKey() { |
185 | return WeakVH(DenseMapInfo<Value *>::getTombstoneKey()); |
186 | } |
187 | |
188 | static unsigned getHashValue(const WeakVH &Val) { |
189 | return DenseMapInfo<Value *>::getHashValue(PtrVal: Val); |
190 | } |
191 | |
192 | static bool isEqual(const WeakVH &LHS, const WeakVH &RHS) { |
193 | return DenseMapInfo<Value *>::isEqual(LHS, RHS); |
194 | } |
195 | }; |
196 | |
197 | /// Value handle that is nullable, but tries to track the Value. |
198 | /// |
199 | /// This is a value handle that tries hard to point to a Value, even across |
200 | /// RAUW operations, but will null itself out if the value is destroyed. this |
201 | /// is useful for advisory sorts of information, but should not be used as the |
202 | /// key of a map (since the map would have to rearrange itself when the pointer |
203 | /// changes). |
204 | class WeakTrackingVH : public ValueHandleBase { |
205 | public: |
206 | WeakTrackingVH() : ValueHandleBase(WeakTracking) {} |
207 | WeakTrackingVH(Value *P) : ValueHandleBase(WeakTracking, P) {} |
208 | WeakTrackingVH(const WeakTrackingVH &RHS) |
209 | : ValueHandleBase(WeakTracking, RHS) {} |
210 | |
211 | WeakTrackingVH &operator=(const WeakTrackingVH &RHS) = default; |
212 | |
213 | Value *operator=(Value *RHS) { |
214 | return ValueHandleBase::operator=(RHS); |
215 | } |
216 | Value *operator=(const ValueHandleBase &RHS) { |
217 | return ValueHandleBase::operator=(RHS); |
218 | } |
219 | |
220 | operator Value*() const { |
221 | return getValPtr(); |
222 | } |
223 | |
224 | bool pointsToAliveValue() const { |
225 | return ValueHandleBase::isValid(V: getValPtr()); |
226 | } |
227 | }; |
228 | |
229 | // Specialize simplify_type to allow WeakTrackingVH to participate in |
230 | // dyn_cast, isa, etc. |
231 | template <> struct simplify_type<WeakTrackingVH> { |
232 | using SimpleType = Value *; |
233 | |
234 | static SimpleType getSimplifiedValue(WeakTrackingVH &WVH) { return WVH; } |
235 | }; |
236 | template <> struct simplify_type<const WeakTrackingVH> { |
237 | using SimpleType = Value *; |
238 | |
239 | static SimpleType getSimplifiedValue(const WeakTrackingVH &WVH) { |
240 | return WVH; |
241 | } |
242 | }; |
243 | |
244 | /// Value handle that asserts if the Value is deleted. |
245 | /// |
246 | /// This is a Value Handle that points to a value and asserts out if the value |
247 | /// is destroyed while the handle is still live. This is very useful for |
248 | /// catching dangling pointer bugs and other things which can be non-obvious. |
249 | /// One particularly useful place to use this is as the Key of a map. Dangling |
250 | /// pointer bugs often lead to really subtle bugs that only occur if another |
251 | /// object happens to get allocated to the same address as the old one. Using |
252 | /// an AssertingVH ensures that an assert is triggered as soon as the bad |
253 | /// delete occurs. |
254 | /// |
255 | /// Note that an AssertingVH handle does *not* follow values across RAUW |
256 | /// operations. This means that RAUW's need to explicitly update the |
257 | /// AssertingVH's as it moves. This is required because in non-assert mode this |
258 | /// class turns into a trivial wrapper around a pointer. |
259 | template <typename ValueTy> |
260 | class AssertingVH |
261 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
262 | : public ValueHandleBase |
263 | #endif |
264 | { |
265 | friend struct DenseMapInfo<AssertingVH<ValueTy>>; |
266 | |
267 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
268 | Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); } |
269 | void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); } |
270 | #else |
271 | Value *ThePtr; |
272 | Value *getRawValPtr() const { return ThePtr; } |
273 | void setRawValPtr(Value *P) { ThePtr = P; } |
274 | #endif |
275 | // Convert a ValueTy*, which may be const, to the raw Value*. |
276 | static Value *GetAsValue(Value *V) { return V; } |
277 | static Value *GetAsValue(const Value *V) { return const_cast<Value*>(V); } |
278 | |
279 | ValueTy *getValPtr() const { return static_cast<ValueTy *>(getRawValPtr()); } |
280 | void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); } |
281 | |
282 | public: |
283 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
284 | AssertingVH() : ValueHandleBase(Assert) {} |
285 | AssertingVH(ValueTy *P) : ValueHandleBase(Assert, GetAsValue(P)) {} |
286 | AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {} |
287 | #else |
288 | AssertingVH() : ThePtr(nullptr) {} |
289 | AssertingVH(ValueTy *P) : ThePtr(GetAsValue(P)) {} |
290 | AssertingVH(const AssertingVH &) = default; |
291 | #endif |
292 | |
293 | operator ValueTy*() const { |
294 | return getValPtr(); |
295 | } |
296 | |
297 | ValueTy *operator=(ValueTy *RHS) { |
298 | setValPtr(RHS); |
299 | return getValPtr(); |
300 | } |
301 | ValueTy *operator=(const AssertingVH<ValueTy> &RHS) { |
302 | setValPtr(RHS.getValPtr()); |
303 | return getValPtr(); |
304 | } |
305 | |
306 | ValueTy *operator->() const { return getValPtr(); } |
307 | ValueTy &operator*() const { return *getValPtr(); } |
308 | }; |
309 | |
310 | // Treat AssertingVH<T> like T* inside maps. This also allows using find_as() |
311 | // to look up a value without constructing a value handle. |
312 | template<typename T> |
313 | struct DenseMapInfo<AssertingVH<T>> : DenseMapInfo<T *> {}; |
314 | |
315 | /// Value handle that tracks a Value across RAUW. |
316 | /// |
317 | /// TrackingVH is designed for situations where a client needs to hold a handle |
318 | /// to a Value (or subclass) across some operations which may move that value, |
319 | /// but should never destroy it or replace it with some unacceptable type. |
320 | /// |
321 | /// It is an error to attempt to replace a value with one of a type which is |
322 | /// incompatible with any of its outstanding TrackingVHs. |
323 | /// |
324 | /// It is an error to read from a TrackingVH that does not point to a valid |
325 | /// value. A TrackingVH is said to not point to a valid value if either it |
326 | /// hasn't yet been assigned a value yet or because the value it was tracking |
327 | /// has since been deleted. |
328 | /// |
329 | /// Assigning a value to a TrackingVH is always allowed, even if said TrackingVH |
330 | /// no longer points to a valid value. |
331 | template <typename ValueTy> class TrackingVH { |
332 | WeakTrackingVH InnerHandle; |
333 | |
334 | public: |
335 | ValueTy *getValPtr() const { |
336 | assert(InnerHandle.pointsToAliveValue() && |
337 | "TrackingVH must be non-null and valid on dereference!" ); |
338 | |
339 | // Check that the value is a member of the correct subclass. We would like |
340 | // to check this property on assignment for better debugging, but we don't |
341 | // want to require a virtual interface on this VH. Instead we allow RAUW to |
342 | // replace this value with a value of an invalid type, and check it here. |
343 | assert(isa<ValueTy>(InnerHandle) && |
344 | "Tracked Value was replaced by one with an invalid type!" ); |
345 | return cast<ValueTy>(InnerHandle); |
346 | } |
347 | |
348 | void setValPtr(ValueTy *P) { |
349 | // Assigning to non-valid TrackingVH's are fine so we just unconditionally |
350 | // assign here. |
351 | InnerHandle = GetAsValue(P); |
352 | } |
353 | |
354 | // Convert a ValueTy*, which may be const, to the type the base |
355 | // class expects. |
356 | static Value *GetAsValue(Value *V) { return V; } |
357 | static Value *GetAsValue(const Value *V) { return const_cast<Value*>(V); } |
358 | |
359 | public: |
360 | TrackingVH() = default; |
361 | TrackingVH(ValueTy *P) { setValPtr(P); } |
362 | |
363 | operator ValueTy*() const { |
364 | return getValPtr(); |
365 | } |
366 | |
367 | ValueTy *operator=(ValueTy *RHS) { |
368 | setValPtr(RHS); |
369 | return getValPtr(); |
370 | } |
371 | |
372 | ValueTy *operator->() const { return getValPtr(); } |
373 | ValueTy &operator*() const { return *getValPtr(); } |
374 | }; |
375 | |
376 | /// Value handle with callbacks on RAUW and destruction. |
377 | /// |
378 | /// This is a value handle that allows subclasses to define callbacks that run |
379 | /// when the underlying Value has RAUW called on it or is destroyed. This |
380 | /// class can be used as the key of a map, as long as the user takes it out of |
381 | /// the map before calling setValPtr() (since the map has to rearrange itself |
382 | /// when the pointer changes). Unlike ValueHandleBase, this class has a vtable. |
383 | class CallbackVH : public ValueHandleBase { |
384 | virtual void anchor(); |
385 | protected: |
386 | ~CallbackVH() = default; |
387 | CallbackVH(const CallbackVH &) = default; |
388 | CallbackVH &operator=(const CallbackVH &) = default; |
389 | |
390 | void setValPtr(Value *P) { |
391 | ValueHandleBase::operator=(RHS: P); |
392 | } |
393 | |
394 | public: |
395 | CallbackVH() : ValueHandleBase(Callback) {} |
396 | CallbackVH(Value *P) : ValueHandleBase(Callback, P) {} |
397 | CallbackVH(const Value *P) : CallbackVH(const_cast<Value *>(P)) {} |
398 | |
399 | operator Value*() const { |
400 | return getValPtr(); |
401 | } |
402 | |
403 | /// Callback for Value destruction. |
404 | /// |
405 | /// Called when this->getValPtr() is destroyed, inside ~Value(), so you |
406 | /// may call any non-virtual Value method on getValPtr(), but no subclass |
407 | /// methods. If WeakTrackingVH were implemented as a CallbackVH, it would use |
408 | /// this |
409 | /// method to call setValPtr(NULL). AssertingVH would use this method to |
410 | /// cause an assertion failure. |
411 | /// |
412 | /// All implementations must remove the reference from this object to the |
413 | /// Value that's being destroyed. |
414 | virtual void deleted() { setValPtr(nullptr); } |
415 | |
416 | /// Callback for Value RAUW. |
417 | /// |
418 | /// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called, |
419 | /// _before_ any of the uses have actually been replaced. If WeakTrackingVH |
420 | /// were |
421 | /// implemented as a CallbackVH, it would use this method to call |
422 | /// setValPtr(new_value). AssertingVH would do nothing in this method. |
423 | virtual void allUsesReplacedWith(Value *) {} |
424 | }; |
425 | |
426 | /// Value handle that poisons itself if the Value is deleted. |
427 | /// |
428 | /// This is a Value Handle that points to a value and poisons itself if the |
429 | /// value is destroyed while the handle is still live. This is very useful for |
430 | /// catching dangling pointer bugs where an \c AssertingVH cannot be used |
431 | /// because the dangling handle needs to outlive the value without ever being |
432 | /// used. |
433 | /// |
434 | /// One particularly useful place to use this is as the Key of a map. Dangling |
435 | /// pointer bugs often lead to really subtle bugs that only occur if another |
436 | /// object happens to get allocated to the same address as the old one. Using |
437 | /// a PoisoningVH ensures that an assert is triggered if looking up a new value |
438 | /// in the map finds a handle from the old value. |
439 | /// |
440 | /// Note that a PoisoningVH handle does *not* follow values across RAUW |
441 | /// operations. This means that RAUW's need to explicitly update the |
442 | /// PoisoningVH's as it moves. This is required because in non-assert mode this |
443 | /// class turns into a trivial wrapper around a pointer. |
444 | template <typename ValueTy> |
445 | class PoisoningVH final |
446 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
447 | : public CallbackVH |
448 | #endif |
449 | { |
450 | friend struct DenseMapInfo<PoisoningVH<ValueTy>>; |
451 | |
452 | // Convert a ValueTy*, which may be const, to the raw Value*. |
453 | static Value *GetAsValue(Value *V) { return V; } |
454 | static Value *GetAsValue(const Value *V) { return const_cast<Value *>(V); } |
455 | |
456 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
457 | /// A flag tracking whether this value has been poisoned. |
458 | /// |
459 | /// On delete and RAUW, we leave the value pointer alone so that as a raw |
460 | /// pointer it produces the same value (and we fit into the same key of |
461 | /// a hash table, etc), but we poison the handle so that any top-level usage |
462 | /// will fail. |
463 | bool Poisoned = false; |
464 | |
465 | Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); } |
466 | void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); } |
467 | |
468 | /// Handle deletion by poisoning the handle. |
469 | void deleted() override { |
470 | assert(!Poisoned && "Tried to delete an already poisoned handle!" ); |
471 | Poisoned = true; |
472 | RemoveFromUseList(); |
473 | } |
474 | |
475 | /// Handle RAUW by poisoning the handle. |
476 | void allUsesReplacedWith(Value *) override { |
477 | assert(!Poisoned && "Tried to RAUW an already poisoned handle!" ); |
478 | Poisoned = true; |
479 | RemoveFromUseList(); |
480 | } |
481 | #else // LLVM_ENABLE_ABI_BREAKING_CHECKS |
482 | Value *ThePtr = nullptr; |
483 | |
484 | Value *getRawValPtr() const { return ThePtr; } |
485 | void setRawValPtr(Value *P) { ThePtr = P; } |
486 | #endif |
487 | |
488 | ValueTy *getValPtr() const { |
489 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
490 | assert(!Poisoned && "Accessed a poisoned value handle!" ); |
491 | #endif |
492 | return static_cast<ValueTy *>(getRawValPtr()); |
493 | } |
494 | void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); } |
495 | |
496 | public: |
497 | PoisoningVH() = default; |
498 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
499 | PoisoningVH(ValueTy *P) : CallbackVH(GetAsValue(P)) {} |
500 | PoisoningVH(const PoisoningVH &RHS) |
501 | : CallbackVH(RHS), Poisoned(RHS.Poisoned) {} |
502 | |
503 | ~PoisoningVH() { |
504 | if (Poisoned) |
505 | clearValPtr(); |
506 | } |
507 | |
508 | PoisoningVH &operator=(const PoisoningVH &RHS) { |
509 | if (Poisoned) |
510 | clearValPtr(); |
511 | CallbackVH::operator=(RHS); |
512 | Poisoned = RHS.Poisoned; |
513 | return *this; |
514 | } |
515 | #else |
516 | PoisoningVH(ValueTy *P) : ThePtr(GetAsValue(P)) {} |
517 | #endif |
518 | |
519 | operator ValueTy *() const { return getValPtr(); } |
520 | |
521 | ValueTy *operator->() const { return getValPtr(); } |
522 | ValueTy &operator*() const { return *getValPtr(); } |
523 | }; |
524 | |
525 | // Specialize DenseMapInfo to allow PoisoningVH to participate in DenseMap. |
526 | template <typename T> struct DenseMapInfo<PoisoningVH<T>> { |
527 | static inline PoisoningVH<T> getEmptyKey() { |
528 | PoisoningVH<T> Res; |
529 | Res.setRawValPtr(DenseMapInfo<Value *>::getEmptyKey()); |
530 | return Res; |
531 | } |
532 | |
533 | static inline PoisoningVH<T> getTombstoneKey() { |
534 | PoisoningVH<T> Res; |
535 | Res.setRawValPtr(DenseMapInfo<Value *>::getTombstoneKey()); |
536 | return Res; |
537 | } |
538 | |
539 | static unsigned getHashValue(const PoisoningVH<T> &Val) { |
540 | return DenseMapInfo<Value *>::getHashValue(PtrVal: Val.getRawValPtr()); |
541 | } |
542 | |
543 | static bool isEqual(const PoisoningVH<T> &LHS, const PoisoningVH<T> &RHS) { |
544 | return DenseMapInfo<Value *>::isEqual(LHS: LHS.getRawValPtr(), |
545 | RHS: RHS.getRawValPtr()); |
546 | } |
547 | |
548 | // Allow lookup by T* via find_as(), without constructing a temporary |
549 | // value handle. |
550 | |
551 | static unsigned getHashValue(const T *Val) { |
552 | return DenseMapInfo<Value *>::getHashValue(PtrVal: Val); |
553 | } |
554 | |
555 | static bool isEqual(const T *LHS, const PoisoningVH<T> &RHS) { |
556 | return DenseMapInfo<Value *>::isEqual(LHS, RHS: RHS.getRawValPtr()); |
557 | } |
558 | }; |
559 | |
560 | } // end namespace llvm |
561 | |
562 | #endif // LLVM_IR_VALUEHANDLE_H |
563 | |