[llvm] [VPlan] Add poisoning value handle for VPValue. (NFCI) (PR #185054)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 10 06:40:56 PDT 2026
================
@@ -427,6 +430,140 @@ class VPDef {
unsigned getNumDefinedValues() const { return DefinedValues.size(); }
};
+/// Value handle that poisons itself when the referenced VPValue is deleted,
+/// catching dangling pointer bugs (e.g. stale DenseMap keys). Only
+/// VPRecipeValues with a retrievable VPlan are tracked; other VPValue types
+/// work but are not poisoned. Does *not* follow RAUW.
+class LLVM_ABI_FOR_TEST PoisoningVPValueHandle {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
+ const VPValue *VP = nullptr;
+ const VPlan *Plan = nullptr;
+ bool Poisoned = false;
+ PoisoningVPValueHandle *Next = nullptr;
+
+ /// Returns true if \p V is not null and not a DenseMap sentinel.
+ static bool isValid(const VPValue *V) {
+ return V && V != DenseMapInfo<const VPValue *>::getEmptyKey() &&
+ V != DenseMapInfo<const VPValue *>::getTombstoneKey();
+ }
+
+ /// Return the VPlan owning \p V, or nullptr if not available.
+ static const VPlan *getVPlan(const VPValue *V);
+
+ const VPValue *getRawValPtr() const { return VP; }
+ void setRawValPtr(const VPValue *P) {
+ if (isValid(VP) && !Poisoned)
+ removeFromList();
+ VP = P;
+ Poisoned = false;
+ Plan = nullptr;
+ if (isValid(VP))
+ addToList();
+ }
+
+ void addToList();
+ void removeFromList();
+
+ friend struct DenseMapInfo<PoisoningVPValueHandle>;
+#else
+ const VPValue *VP = nullptr;
+
+ const VPValue *getRawValPtr() const { return VP; }
+ void setRawValPtr(const VPValue *P) { VP = P; }
+#endif
+
+ const VPValue *getValPtr() const {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
+ assert(!Poisoned && "Accessed a poisoned VPValue handle!");
+#endif
+ return VP;
+ }
+
+public:
+ PoisoningVPValueHandle() = default;
+ PoisoningVPValueHandle(const VPValue *V) : VP(V) {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
+ if (isValid(VP))
+ addToList();
+#endif
+ }
+
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
+ PoisoningVPValueHandle(const PoisoningVPValueHandle &RHS)
+ : VP(RHS.VP), Poisoned(RHS.Poisoned) {
+ if (isValid(VP) && !Poisoned)
+ addToList();
+ }
+
+ ~PoisoningVPValueHandle() {
+ if (isValid(VP) && !Poisoned)
+ removeFromList();
+ }
+
+ PoisoningVPValueHandle &operator=(const PoisoningVPValueHandle &RHS) {
+ if (this == &RHS)
+ return *this;
+ if (isValid(VP) && !Poisoned)
+ removeFromList();
+ VP = RHS.VP;
+ Poisoned = RHS.Poisoned;
+ if (isValid(VP) && !Poisoned)
+ addToList();
+ return *this;
+ }
+#endif
+
+ operator const VPValue *() const { return getValPtr(); }
+ const VPValue *operator->() const { return getValPtr(); }
+ const VPValue &operator*() const { return *getValPtr(); }
+
+ static void poisonAll(const VPlan *Plan, const VPValue *V);
+};
+
+template <> struct DenseMapInfo<PoisoningVPValueHandle> {
+ static inline PoisoningVPValueHandle getEmptyKey() {
+ PoisoningVPValueHandle Res;
+ Res.setRawValPtr(DenseMapInfo<const VPValue *>::getEmptyKey());
+ return Res;
----------------
fhahn wrote:
Yep that works, updated, thanks! Same for below
https://github.com/llvm/llvm-project/pull/185054
More information about the llvm-commits
mailing list