-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[IR] Use alloc markers for operator delete variants #138261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
marcauberer
wants to merge
2
commits into
llvm:main
Choose a base branch
from
marcauberer:llvm/user-delete-follow-up
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
+58
−64
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@llvm/pr-subscribers-llvm-ir Author: Marc Auberer (marcauberer) ChangesFollow-up to #129914 PS: Sorry for the long delay ;) Full diff: https://github.com/llvm/llvm-project/pull/138261.diff 2 Files Affected:
diff --git a/llvm/include/llvm/IR/User.h b/llvm/include/llvm/IR/User.h
index 39e1314bd8130..634b14341d243 100644
--- a/llvm/include/llvm/IR/User.h
+++ b/llvm/include/llvm/IR/User.h
@@ -54,7 +54,10 @@ class User : public Value {
void *operator new(size_t Size) = delete;
/// Indicates this User has operands "hung off" in another allocation.
- struct HungOffOperandsAllocMarker {};
+ struct HungOffOperandsAllocMarker {
+ /// The number of operands for this User.
+ const unsigned NumOps;
+ };
/// Indicates this User has operands co-allocated.
struct IntrusiveOperandsAllocMarker {
@@ -145,42 +148,11 @@ class User : public Value {
/// Free memory allocated for User and Use objects.
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
- }
+ 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
- }
+ void operator delete(void *Usr, IntrusiveOperandsAllocMarker Marker);
/// 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
- }
+ void operator delete(void *Usr, IntrusiveOperandsAndDescriptorAllocMarker);
protected:
template <int Idx, typename U> static Use &OpFrom(const U *that) {
diff --git a/llvm/lib/IR/User.cpp b/llvm/lib/IR/User.cpp
index ab44cb4b8a3f7..fea8aa6a02338 100644
--- a/llvm/lib/IR/User.cpp
+++ b/llvm/lib/IR/User.cpp
@@ -20,13 +20,14 @@ class BasicBlock;
bool User::replaceUsesOfWith(Value *From, Value *To) {
bool Changed = false;
- if (From == To) return Changed; // Duh what?
+ if (From == To)
+ return Changed; // Duh what?
assert((!isa<Constant>(this) || isa<GlobalValue>(this)) &&
"Cannot call User::replaceUsesOfWith on a constant!");
for (unsigned i = 0, E = getNumOperands(); i != E; ++i)
- if (getOperand(i) == From) { // Is This operand is pointing to oldval?
+ if (getOperand(i) == From) { // Is This operand is pointing to oldval?
// The side effects of this setOperand call include linking to
// "To", adding "this" to the uses list of To, and
// most importantly, removing "this" from the use list of "From".
@@ -57,7 +58,7 @@ void User::allocHungoffUses(unsigned N, bool IsPhi) {
size_t size = N * sizeof(Use);
if (IsPhi)
size += N * sizeof(BasicBlock *);
- Use *Begin = static_cast<Use*>(::operator new(size));
+ Use *Begin = static_cast<Use *>(::operator new(size));
Use *End = Begin + N;
setOperandList(Begin);
for (; Begin != End; Begin++)
@@ -89,7 +90,6 @@ void User::growHungoffUses(unsigned NewNumUses, bool IsPhi) {
Use::zap(OldOps, OldOps + OldNumUses, true);
}
-
// This is a private struct used by `User` to track the co-allocated descriptor
// section.
struct DescriptorInfo {
@@ -191,28 +191,70 @@ void *User::operator new(size_t Size, HungOffOperandsAllocMarker) {
LLVM_NO_SANITIZE_MEMORY_ATTRIBUTE void User::operator delete(void *Usr) {
// Hung off uses use a single Use* before the User, while other subclasses
// use a Use[] allocated prior to the user.
- User *Obj = static_cast<User *>(Usr);
+ const auto *Obj = static_cast<User *>(Usr);
if (Obj->HasHungOffUses) {
- assert(!Obj->HasDescriptor && "not supported!");
-
- Use **HungOffOperandList = static_cast<Use **>(Usr) - 1;
- // drop the hung off uses.
- Use::zap(*HungOffOperandList, *HungOffOperandList + Obj->NumUserOperands,
- /* Delete */ true);
- ::operator delete(HungOffOperandList);
+ const HungOffOperandsAllocMarker Marker{
+ Obj->NumUserOperands,
+ };
+ operator delete(Usr, Marker);
} else if (Obj->HasDescriptor) {
- Use *UseBegin = static_cast<Use *>(Usr) - Obj->NumUserOperands;
- Use::zap(UseBegin, UseBegin + Obj->NumUserOperands, /* Delete */ false);
-
- auto *DI = reinterpret_cast<DescriptorInfo *>(UseBegin) - 1;
- uint8_t *Storage = reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes;
- ::operator delete(Storage);
+ const IntrusiveOperandsAndDescriptorAllocMarker Marker{
+ Obj->NumUserOperands,
+ Obj->HasDescriptor,
+ };
+ operator delete(Usr, Marker);
} else {
- Use *Storage = static_cast<Use *>(Usr) - Obj->NumUserOperands;
- Use::zap(Storage, Storage + Obj->NumUserOperands,
- /* Delete */ false);
- ::operator delete(Storage);
+ const IntrusiveOperandsAllocMarker Marker{
+ Obj->NumUserOperands,
+ };
+ operator delete(Usr, Marker);
}
}
+// Repress memory sanitization, due to use-after-destroy by operator
+// delete. Bug report 24578 identifies this issue.
+LLVM_NO_SANITIZE_MEMORY_ATTRIBUTE void
+User::operator delete(void *Usr, const HungOffOperandsAllocMarker Marker) {
+ // 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.
+ Use **HungOffOperandList = static_cast<Use **>(Usr) - 1;
+ // drop the hung off uses.
+ Use::zap(*HungOffOperandList, *HungOffOperandList + Marker.NumOps,
+ /* Delete */ true);
+ ::operator delete(HungOffOperandList);
+}
+
+// Repress memory sanitization, due to use-after-destroy by operator
+// delete. Bug report 24578 identifies this issue.
+LLVM_NO_SANITIZE_MEMORY_ATTRIBUTE void
+User::operator delete(void *Usr, const IntrusiveOperandsAllocMarker Marker) {
+ // 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.
+ Use *Storage = static_cast<Use *>(Usr) - Marker.NumOps;
+ Use::zap(Storage, Storage + Marker.NumOps, /* Delete */ false);
+ ::operator delete(Storage);
+}
+
+// Repress memory sanitization, due to use-after-destroy by operator
+// delete. Bug report 24578 identifies this issue.
+LLVM_NO_SANITIZE_MEMORY_ATTRIBUTE void
+User::operator delete(void *Usr,
+ const IntrusiveOperandsAndDescriptorAllocMarker Marker) {
+ // 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.
+ Use *UseBegin = static_cast<Use *>(Usr) - Marker.NumOps;
+ Use::zap(UseBegin, UseBegin + Marker.NumOps, /* Delete */ false);
+
+ auto *DI = reinterpret_cast<DescriptorInfo *>(UseBegin) - 1;
+ uint8_t *Storage = reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes;
+ ::operator delete(Storage);
+}
+
} // namespace llvm
|
nikic
reviewed
May 2, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Follow-up to #129914
This fixes the problem properly by using the data via the allocation markers.
PS: Sorry for the long delay ;)