Author: Marc Auberer Date: 2026-01-22T08:24:43Z New Revision: aba17bb896b75b2a64753b937599b44eb76678a9
URL: https://github.com/llvm/llvm-project/commit/aba17bb896b75b2a64753b937599b44eb76678a9 DIFF: https://github.com/llvm/llvm-project/commit/aba17bb896b75b2a64753b937599b44eb76678a9.diff LOG: [IR] Use alloc markers for operator delete variants (#138261) Follow-up to https://github.com/llvm/llvm-project/pull/129914 This fixes the problem properly by using the data via the allocation markers. PS: Sorry for the long delay ;) (cherry picked from commit 72d5925412522d01e48f8d6027e51c2dead11617) Added: Modified: llvm/include/llvm/Analysis/MemorySSA.h llvm/include/llvm/IR/Constants.h llvm/include/llvm/IR/GlobalAlias.h llvm/include/llvm/IR/GlobalIFunc.h llvm/include/llvm/IR/GlobalVariable.h llvm/include/llvm/IR/InstrTypes.h llvm/include/llvm/IR/Instructions.h llvm/include/llvm/IR/User.h llvm/lib/IR/ConstantsContext.h llvm/lib/IR/User.cpp Removed: ################################################################################ diff --git a/llvm/include/llvm/Analysis/MemorySSA.h b/llvm/include/llvm/Analysis/MemorySSA.h index 07d39ab3e10a9..ab44bc09d9550 100644 --- a/llvm/include/llvm/Analysis/MemorySSA.h +++ b/llvm/include/llvm/Analysis/MemorySSA.h @@ -318,7 +318,7 @@ class MemoryUse final : public MemoryUseOrDef { // allocate space for exactly one operand void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } static bool classof(const Value *MA) { return MA->getValueID() == MemoryUseVal; @@ -383,7 +383,7 @@ class MemoryDef final : public MemoryUseOrDef { // allocate space for exactly two operands void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } static bool classof(const Value *MA) { return MA->getValueID() == MemoryDefVal; @@ -483,7 +483,7 @@ class MemoryPhi final : public MemoryAccess { void *operator new(size_t S) { return User::operator new(S, AllocMarker); } public: - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess); diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h index 3bb2fa28cced8..6bf990c69e19f 100644 --- a/llvm/include/llvm/IR/Constants.h +++ b/llvm/include/llvm/IR/Constants.h @@ -917,7 +917,7 @@ class BlockAddress final : public Constant { Value *handleOperandChangeImpl(Value *From, Value *To); public: - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } /// Return a BlockAddress for the specified function and basic block. LLVM_ABI static BlockAddress *get(Function *F, BasicBlock *BB); @@ -970,7 +970,7 @@ class DSOLocalEquivalent final : public Constant { Value *handleOperandChangeImpl(Value *From, Value *To); public: - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } /// Return a DSOLocalEquivalent for the specified global value. LLVM_ABI static DSOLocalEquivalent *get(GlobalValue *GV); diff --git a/llvm/include/llvm/IR/GlobalAlias.h b/llvm/include/llvm/IR/GlobalAlias.h index 12b9f053abb17..c0a6c3d69374c 100644 --- a/llvm/include/llvm/IR/GlobalAlias.h +++ b/llvm/include/llvm/IR/GlobalAlias.h @@ -63,7 +63,7 @@ class GlobalAlias : public GlobalValue, public ilist_node<GlobalAlias> { // allocate space for exactly one operand void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); diff --git a/llvm/include/llvm/IR/GlobalIFunc.h b/llvm/include/llvm/IR/GlobalIFunc.h index d93146aa016be..853b3fe250cc9 100644 --- a/llvm/include/llvm/IR/GlobalIFunc.h +++ b/llvm/include/llvm/IR/GlobalIFunc.h @@ -52,7 +52,7 @@ class GlobalIFunc final : public GlobalObject, public ilist_node<GlobalIFunc> { // allocate space for exactly one operand void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); diff --git a/llvm/include/llvm/IR/GlobalVariable.h b/llvm/include/llvm/IR/GlobalVariable.h index d1d42cebc1352..8e6af8ae6e203 100644 --- a/llvm/include/llvm/IR/GlobalVariable.h +++ b/llvm/include/llvm/IR/GlobalVariable.h @@ -100,7 +100,7 @@ class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> { void *operator new(size_t s) { return User::operator new(s, AllocMarker); } // delete space for exactly one operand as created in the corresponding new operator - void operator delete(void *ptr) { User::operator delete(ptr); } + void operator delete(void *ptr) { User::operator delete(ptr, AllocMarker); } /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h index 9f56779a9b935..55cc26d1e9c8f 100644 --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -68,7 +68,7 @@ class UnaryInstruction : public Instruction { public: // allocate space for exactly one operand void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -185,7 +185,7 @@ class BinaryOperator : public Instruction { public: // allocate space for exactly two operands void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -734,7 +734,7 @@ class CmpInst : public Instruction { public: // allocate space for exactly two operands void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } /// Construct a compare instruction, given the opcode, the predicate and /// the two operands. Optionally (if InstBefore is specified) insert the diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h index dbcaa6459eea9..d4ea74c05ae62 100644 --- a/llvm/include/llvm/IR/Instructions.h +++ b/llvm/include/llvm/IR/Instructions.h @@ -325,7 +325,7 @@ class StoreInst : public Instruction { // allocate space for exactly two operands void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } /// Return true if this is a store to a volatile memory location. bool isVolatile() const { return getSubclassData<VolatileField>(); } @@ -449,7 +449,7 @@ class FenceInst : public Instruction { // allocate space for exactly zero operands void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } /// Returns the ordering constraint of this fence instruction. AtomicOrdering getOrdering() const { @@ -530,7 +530,7 @@ class AtomicCmpXchgInst : public Instruction { // allocate space for exactly three operands void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } using VolatileField = BoolBitfieldElementT<0>; using WeakField = BoolBitfieldElementT<VolatileField::NextBit>; @@ -806,7 +806,7 @@ class AtomicRMWInst : public Instruction { // allocate space for exactly two operands void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } using VolatileField = BoolBitfieldElementT<0>; using AtomicOrderingField = @@ -1958,7 +1958,9 @@ class ShuffleVectorInst : public Instruction { InsertPosition InsertBefore = nullptr); void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { return User::operator delete(Ptr); } + void operator delete(void *Ptr) { + return User::operator delete(Ptr, AllocMarker); + } /// Swap the operands and adjust the mask to preserve the semantics /// of the instruction. @@ -2553,7 +2555,7 @@ class InsertValueInst : public Instruction { public: // allocate space for exactly two operands void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } static InsertValueInst *Create(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs, @@ -2906,7 +2908,7 @@ class LandingPadInst : public Instruction { LLVM_ABI LandingPadInst *cloneImpl() const; public: - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } /// Constructors - NumReservedClauses is a hint for the number of incoming /// clauses that this landingpad will have (use 0 if you really have no idea). @@ -3233,7 +3235,7 @@ class SwitchInst : public Instruction { } public: - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } // -2 static const unsigned DefaultPseudoIndex = static_cast<unsigned>(~0L-1); @@ -3623,7 +3625,7 @@ class IndirectBrInst : public Instruction { LLVM_ABI IndirectBrInst *cloneImpl() const; public: - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } /// Iterator type that casts an operand to a basic block. /// @@ -4145,7 +4147,9 @@ class CatchSwitchInst : public Instruction { LLVM_ABI CatchSwitchInst *cloneImpl() const; public: - void operator delete(void *Ptr) { return User::operator delete(Ptr); } + void operator delete(void *Ptr) { + return User::operator delete(Ptr, AllocMarker); + } static CatchSwitchInst *Create(Value *ParentPad, BasicBlock *UnwindDest, unsigned NumHandlers, @@ -4532,7 +4536,7 @@ class UnreachableInst : public Instruction { // allocate space for exactly zero operands void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } unsigned getNumSuccessors() const { return 0; } diff --git a/llvm/include/llvm/IR/User.h b/llvm/include/llvm/IR/User.h index da886a508a3e8..1d83cfef06c6a 100644 --- a/llvm/include/llvm/IR/User.h +++ b/llvm/include/llvm/IR/User.h @@ -128,6 +128,10 @@ class User : public Value { // null. assert((!AllocInfo.HasHungOffUses || !getOperandList()) && "Error in initializing hung off uses for User"); + + Use *Operands = reinterpret_cast<Use *>(this) - NumUserOperands; + for (unsigned I = 0; I < NumUserOperands; ++I) + new (&Operands[I]) Use(this); } /// Allocate the array of Uses, followed by a pointer @@ -150,42 +154,12 @@ class User : public Value { /// Free memory allocated for User and Use objects. LLVM_ABI void operator delete(void *Usr); /// Placement delete - required by std, called if the ctor throws. - void operator delete(void *Usr, HungOffOperandsAllocMarker) { - // Note: If a subclass manipulates the information which is required to - // calculate the Usr memory pointer, e.g. NumUserOperands, the operator - // delete of that subclass has to restore the changed information to the - // original value, since the dtor of that class is not called if the ctor - // fails. - User::operator delete(Usr); - -#ifndef LLVM_ENABLE_EXCEPTIONS - llvm_unreachable("Constructor throws?"); -#endif - } + LLVM_ABI void operator delete(void *Usr, HungOffOperandsAllocMarker); /// Placement delete - required by std, called if the ctor throws. - void operator delete(void *Usr, IntrusiveOperandsAllocMarker) { - // Note: If a subclass manipulates the information which is required to calculate the - // Usr memory pointer, e.g. NumUserOperands, the operator delete of that subclass has - // to restore the changed information to the original value, since the dtor of that class - // is not called if the ctor fails. - User::operator delete(Usr); - -#ifndef LLVM_ENABLE_EXCEPTIONS - llvm_unreachable("Constructor throws?"); -#endif - } + LLVM_ABI void operator delete(void *Usr, + IntrusiveOperandsAndDescriptorAllocMarker); /// Placement delete - required by std, called if the ctor throws. - void operator delete(void *Usr, IntrusiveOperandsAndDescriptorAllocMarker) { - // Note: If a subclass manipulates the information which is required to calculate the - // Usr memory pointer, e.g. NumUserOperands, the operator delete of that subclass has - // to restore the changed information to the original value, since the dtor of that class - // is not called if the ctor fails. - User::operator delete(Usr); - -#ifndef LLVM_ENABLE_EXCEPTIONS - llvm_unreachable("Constructor throws?"); -#endif - } + LLVM_ABI void operator delete(void *Usr, IntrusiveOperandsAllocMarker Marker); protected: template <int Idx, typename U> static Use &OpFrom(const U *that) { diff --git a/llvm/lib/IR/ConstantsContext.h b/llvm/lib/IR/ConstantsContext.h index 2073e0d42d8e3..cc9bad431787c 100644 --- a/llvm/lib/IR/ConstantsContext.h +++ b/llvm/lib/IR/ConstantsContext.h @@ -54,7 +54,7 @@ class CastConstantExpr final : public ConstantExpr { // allocate space for exactly one operand void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -82,7 +82,7 @@ class BinaryConstantExpr final : public ConstantExpr { // allocate space for exactly two operands void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -111,7 +111,7 @@ class ExtractElementConstantExpr final : public ConstantExpr { // allocate space for exactly two operands void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -140,7 +140,7 @@ class InsertElementConstantExpr final : public ConstantExpr { // allocate space for exactly three operands void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { User::operator delete(Ptr); } + void operator delete(void *Ptr) { User::operator delete(Ptr, AllocMarker); } /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -178,7 +178,9 @@ class ShuffleVectorConstantExpr final : public ConstantExpr { Constant *ShuffleMaskForBitcode; void *operator new(size_t S) { return User::operator new(S, AllocMarker); } - void operator delete(void *Ptr) { return User::operator delete(Ptr); } + void operator delete(void *Ptr) { + return User::operator delete(Ptr, AllocMarker); + } /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); diff --git a/llvm/lib/IR/User.cpp b/llvm/lib/IR/User.cpp index e97a07fe5e7a2..4acfba6766a5d 100644 --- a/llvm/lib/IR/User.cpp +++ b/llvm/lib/IR/User.cpp @@ -158,8 +158,6 @@ void *User::allocateFixedOperandUser(size_t Size, unsigned Us, Obj->NumUserOperands = Us; Obj->HasHungOffUses = false; Obj->HasDescriptor = DescBytes != 0; - for (unsigned I = 0; I < Us; ++I) - new (&Operands[I]) Use(Obj); if (DescBytes != 0) { auto *DescInfo = reinterpret_cast<DescriptorInfo *>(Operands) - 1; @@ -234,3 +232,26 @@ User::~User() { } void User::operator delete(void *Usr) { ::operator delete(((void **)Usr)[-1]); } + +void User::operator delete(void *Usr, HungOffOperandsAllocMarker) { + Use **HungOffOperandList = static_cast<Use **>(Usr) - 1; + ::operator delete(HungOffOperandList); +} + +void User::operator delete(void *Usr, + IntrusiveOperandsAndDescriptorAllocMarker Marker) { + unsigned NumOps = Marker.NumOps; + Use *UseBegin = static_cast<Use *>(Usr) - NumOps; + auto *DI = reinterpret_cast<DescriptorInfo *>(UseBegin) - 1; + uint8_t *Storage = reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes; + ::operator delete(Storage); +} + +void User::operator delete(void *Usr, IntrusiveOperandsAllocMarker Marker) { + unsigned NumOps = Marker.NumOps; + size_t LeadingSize = sizeof(Use) * NumOps; + // Handle the edge case where there are no operands and no descriptor. + LeadingSize = std::max(LeadingSize, sizeof(void *)); + uint8_t *Storage = static_cast<uint8_t *>(Usr) - LeadingSize; + ::operator delete(Storage); +} _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
