xref: /freebsd/contrib/llvm-project/llvm/lib/IR/User.cpp (revision e3f4a63af63bea70bc86b6c790b14aa5ee99fcd0)
1 //===-- User.cpp - Implement the User class -------------------------------===//
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 #include "llvm/IR/User.h"
10 #include "llvm/IR/Constant.h"
11 #include "llvm/IR/GlobalValue.h"
12 #include "llvm/IR/IntrinsicInst.h"
13 
14 namespace llvm {
15 class BasicBlock;
16 
17 //===----------------------------------------------------------------------===//
18 //                                 User Class
19 //===----------------------------------------------------------------------===//
20 
21 bool User::replaceUsesOfWith(Value *From, Value *To) {
22   bool Changed = false;
23   if (From == To) return Changed;   // Duh what?
24 
25   assert((!isa<Constant>(this) || isa<GlobalValue>(this)) &&
26          "Cannot call User::replaceUsesOfWith on a constant!");
27 
28   for (unsigned i = 0, E = getNumOperands(); i != E; ++i)
29     if (getOperand(i) == From) {  // Is This operand is pointing to oldval?
30       // The side effects of this setOperand call include linking to
31       // "To", adding "this" to the uses list of To, and
32       // most importantly, removing "this" from the use list of "From".
33       setOperand(i, To);
34       Changed = true;
35     }
36   if (auto DVI = dyn_cast_or_null<DbgVariableIntrinsic>(this)) {
37     if (is_contained(DVI->location_ops(), From)) {
38       DVI->replaceVariableLocationOp(From, To);
39       Changed = true;
40     }
41   }
42 
43   return Changed;
44 }
45 
46 //===----------------------------------------------------------------------===//
47 //                         User allocHungoffUses Implementation
48 //===----------------------------------------------------------------------===//
49 
50 void User::allocHungoffUses(unsigned N, bool IsPhi) {
51   assert(HasHungOffUses && "alloc must have hung off uses");
52 
53   static_assert(alignof(Use) >= alignof(BasicBlock *),
54                 "Alignment is insufficient for 'hung-off-uses' pieces");
55 
56   // Allocate the array of Uses
57   size_t size = N * sizeof(Use);
58   if (IsPhi)
59     size += N * sizeof(BasicBlock *);
60   Use *Begin = static_cast<Use*>(::operator new(size));
61   Use *End = Begin + N;
62   setOperandList(Begin);
63   for (; Begin != End; Begin++)
64     new (Begin) Use(this);
65 }
66 
67 void User::growHungoffUses(unsigned NewNumUses, bool IsPhi) {
68   assert(HasHungOffUses && "realloc must have hung off uses");
69 
70   unsigned OldNumUses = getNumOperands();
71 
72   // We don't support shrinking the number of uses.  We wouldn't have enough
73   // space to copy the old uses in to the new space.
74   assert(NewNumUses > OldNumUses && "realloc must grow num uses");
75 
76   Use *OldOps = getOperandList();
77   allocHungoffUses(NewNumUses, IsPhi);
78   Use *NewOps = getOperandList();
79 
80   // Now copy from the old operands list to the new one.
81   std::copy(OldOps, OldOps + OldNumUses, NewOps);
82 
83   // If this is a Phi, then we need to copy the BB pointers too.
84   if (IsPhi) {
85     auto *OldPtr = reinterpret_cast<char *>(OldOps + OldNumUses);
86     auto *NewPtr = reinterpret_cast<char *>(NewOps + NewNumUses);
87     std::copy(OldPtr, OldPtr + (OldNumUses * sizeof(BasicBlock *)), NewPtr);
88   }
89   Use::zap(OldOps, OldOps + OldNumUses, true);
90 }
91 
92 
93 // This is a private struct used by `User` to track the co-allocated descriptor
94 // section.
95 struct DescriptorInfo {
96   intptr_t SizeInBytes;
97 };
98 
99 ArrayRef<const uint8_t> User::getDescriptor() const {
100   auto MutableARef = const_cast<User *>(this)->getDescriptor();
101   return {MutableARef.begin(), MutableARef.end()};
102 }
103 
104 MutableArrayRef<uint8_t> User::getDescriptor() {
105   assert(HasDescriptor && "Don't call otherwise!");
106   assert(!HasHungOffUses && "Invariant!");
107 
108   auto *DI = reinterpret_cast<DescriptorInfo *>(getIntrusiveOperands()) - 1;
109   assert(DI->SizeInBytes != 0 && "Should not have had a descriptor otherwise!");
110 
111   return MutableArrayRef<uint8_t>(
112       reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes, DI->SizeInBytes);
113 }
114 
115 bool User::isDroppable() const {
116   if (auto *II = dyn_cast<IntrinsicInst>(this)) {
117     switch (II->getIntrinsicID()) {
118     default:
119       return false;
120     case Intrinsic::assume:
121     case Intrinsic::pseudoprobe:
122     case Intrinsic::experimental_noalias_scope_decl:
123       return true;
124     }
125   }
126   return false;
127 }
128 
129 //===----------------------------------------------------------------------===//
130 //                         User operator new Implementations
131 //===----------------------------------------------------------------------===//
132 
133 void *User::allocateFixedOperandUser(size_t Size, unsigned Us,
134                                      unsigned DescBytes) {
135   assert(Us < (1u << NumUserOperandsBits) && "Too many operands");
136 
137   static_assert(sizeof(DescriptorInfo) % sizeof(void *) == 0, "Required below");
138 
139   unsigned DescBytesToAllocate =
140       DescBytes == 0 ? 0 : (DescBytes + sizeof(DescriptorInfo));
141   assert(DescBytesToAllocate % sizeof(void *) == 0 &&
142          "We need this to satisfy alignment constraints for Uses");
143 
144   uint8_t *Storage = static_cast<uint8_t *>(
145       ::operator new(Size + sizeof(Use) * Us + DescBytesToAllocate));
146   Use *Start = reinterpret_cast<Use *>(Storage + DescBytesToAllocate);
147   Use *End = Start + Us;
148   User *Obj = reinterpret_cast<User *>(End);
149   Obj->NumUserOperands = Us;
150   Obj->HasHungOffUses = false;
151   Obj->HasDescriptor = DescBytes != 0;
152   for (; Start != End; Start++)
153     new (Start) Use(Obj);
154 
155   if (DescBytes != 0) {
156     auto *DescInfo = reinterpret_cast<DescriptorInfo *>(Storage + DescBytes);
157     DescInfo->SizeInBytes = DescBytes;
158   }
159 
160   return Obj;
161 }
162 
163 void *User::operator new(size_t Size, IntrusiveOperandsAllocMarker allocTrait) {
164   return allocateFixedOperandUser(Size, allocTrait.NumOps, 0);
165 }
166 
167 void *User::operator new(size_t Size,
168                          IntrusiveOperandsAndDescriptorAllocMarker allocTrait) {
169   return allocateFixedOperandUser(Size, allocTrait.NumOps,
170                                   allocTrait.DescBytes);
171 }
172 
173 void *User::operator new(size_t Size, HungOffOperandsAllocMarker) {
174   // Allocate space for a single Use*
175   void *Storage = ::operator new(Size + sizeof(Use *));
176   Use **HungOffOperandList = static_cast<Use **>(Storage);
177   User *Obj = reinterpret_cast<User *>(HungOffOperandList + 1);
178   Obj->NumUserOperands = 0;
179   Obj->HasHungOffUses = true;
180   Obj->HasDescriptor = false;
181   *HungOffOperandList = nullptr;
182   return Obj;
183 }
184 
185 //===----------------------------------------------------------------------===//
186 //                         User operator delete Implementation
187 //===----------------------------------------------------------------------===//
188 
189 // Repress memory sanitization, due to use-after-destroy by operator
190 // delete. Bug report 24578 identifies this issue.
191 LLVM_NO_SANITIZE_MEMORY_ATTRIBUTE void User::operator delete(void *Usr) {
192   // Hung off uses use a single Use* before the User, while other subclasses
193   // use a Use[] allocated prior to the user.
194   User *Obj = static_cast<User *>(Usr);
195   if (Obj->HasHungOffUses) {
196     assert(!Obj->HasDescriptor && "not supported!");
197 
198     Use **HungOffOperandList = static_cast<Use **>(Usr) - 1;
199     // drop the hung off uses.
200     Use::zap(*HungOffOperandList, *HungOffOperandList + Obj->NumUserOperands,
201              /* Delete */ true);
202     ::operator delete(HungOffOperandList);
203   } else if (Obj->HasDescriptor) {
204     Use *UseBegin = static_cast<Use *>(Usr) - Obj->NumUserOperands;
205     Use::zap(UseBegin, UseBegin + Obj->NumUserOperands, /* Delete */ false);
206 
207     auto *DI = reinterpret_cast<DescriptorInfo *>(UseBegin) - 1;
208     uint8_t *Storage = reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes;
209     ::operator delete(Storage);
210   } else {
211     Use *Storage = static_cast<Use *>(Usr) - Obj->NumUserOperands;
212     Use::zap(Storage, Storage + Obj->NumUserOperands,
213              /* Delete */ false);
214     ::operator delete(Storage);
215   }
216 }
217 
218 } // namespace llvm
219