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, Val: To); |
34 | Changed = true; |
35 | } |
36 | if (auto DVI = dyn_cast_or_null<DbgVariableIntrinsic>(Val: this)) { |
37 | if (is_contained(Range: DVI->location_ops(), Element: From)) { |
38 | DVI->replaceVariableLocationOp(OldValue: From, NewValue: 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(N: 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(Start: OldOps, Stop: OldOps + OldNumUses, del: 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 | return isa<AssumeInst>(Val: this) || isa<PseudoProbeInst>(Val: this); |
117 | } |
118 | |
119 | //===----------------------------------------------------------------------===// |
120 | // User operator new Implementations |
121 | //===----------------------------------------------------------------------===// |
122 | |
123 | void *User::allocateFixedOperandUser(size_t Size, unsigned Us, |
124 | unsigned DescBytes) { |
125 | assert(Us < (1u << NumUserOperandsBits) && "Too many operands" ); |
126 | |
127 | static_assert(sizeof(DescriptorInfo) % sizeof(void *) == 0, "Required below" ); |
128 | |
129 | unsigned DescBytesToAllocate = |
130 | DescBytes == 0 ? 0 : (DescBytes + sizeof(DescriptorInfo)); |
131 | assert(DescBytesToAllocate % sizeof(void *) == 0 && |
132 | "We need this to satisfy alignment constraints for Uses" ); |
133 | |
134 | uint8_t *Storage = static_cast<uint8_t *>( |
135 | ::operator new(Size + sizeof(Use) * Us + DescBytesToAllocate)); |
136 | Use *Start = reinterpret_cast<Use *>(Storage + DescBytesToAllocate); |
137 | Use *End = Start + Us; |
138 | User *Obj = reinterpret_cast<User*>(End); |
139 | Obj->NumUserOperands = Us; |
140 | Obj->HasHungOffUses = false; |
141 | Obj->HasDescriptor = DescBytes != 0; |
142 | for (; Start != End; Start++) |
143 | new (Start) Use(Obj); |
144 | |
145 | if (DescBytes != 0) { |
146 | auto *DescInfo = reinterpret_cast<DescriptorInfo *>(Storage + DescBytes); |
147 | DescInfo->SizeInBytes = DescBytes; |
148 | } |
149 | |
150 | return Obj; |
151 | } |
152 | |
153 | void *User::operator new(size_t Size, unsigned Us) { |
154 | return allocateFixedOperandUser(Size, Us, DescBytes: 0); |
155 | } |
156 | |
157 | void *User::operator new(size_t Size, unsigned Us, unsigned DescBytes) { |
158 | return allocateFixedOperandUser(Size, Us, DescBytes); |
159 | } |
160 | |
161 | void *User::operator new(size_t Size) { |
162 | // Allocate space for a single Use* |
163 | void *Storage = ::operator new(Size + sizeof(Use *)); |
164 | Use **HungOffOperandList = static_cast<Use **>(Storage); |
165 | User *Obj = reinterpret_cast<User *>(HungOffOperandList + 1); |
166 | Obj->NumUserOperands = 0; |
167 | Obj->HasHungOffUses = true; |
168 | Obj->HasDescriptor = false; |
169 | *HungOffOperandList = nullptr; |
170 | return Obj; |
171 | } |
172 | |
173 | //===----------------------------------------------------------------------===// |
174 | // User operator delete Implementation |
175 | //===----------------------------------------------------------------------===// |
176 | |
177 | // Repress memory sanitization, due to use-after-destroy by operator |
178 | // delete. Bug report 24578 identifies this issue. |
179 | LLVM_NO_SANITIZE_MEMORY_ATTRIBUTE void User::operator delete(void *Usr) { |
180 | // Hung off uses use a single Use* before the User, while other subclasses |
181 | // use a Use[] allocated prior to the user. |
182 | User *Obj = static_cast<User *>(Usr); |
183 | if (Obj->HasHungOffUses) { |
184 | assert(!Obj->HasDescriptor && "not supported!" ); |
185 | |
186 | Use **HungOffOperandList = static_cast<Use **>(Usr) - 1; |
187 | // drop the hung off uses. |
188 | Use::zap(Start: *HungOffOperandList, Stop: *HungOffOperandList + Obj->NumUserOperands, |
189 | /* Delete */ del: true); |
190 | ::operator delete(HungOffOperandList); |
191 | } else if (Obj->HasDescriptor) { |
192 | Use *UseBegin = static_cast<Use *>(Usr) - Obj->NumUserOperands; |
193 | Use::zap(Start: UseBegin, Stop: UseBegin + Obj->NumUserOperands, /* Delete */ del: false); |
194 | |
195 | auto *DI = reinterpret_cast<DescriptorInfo *>(UseBegin) - 1; |
196 | uint8_t *Storage = reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes; |
197 | ::operator delete(Storage); |
198 | } else { |
199 | Use *Storage = static_cast<Use *>(Usr) - Obj->NumUserOperands; |
200 | Use::zap(Start: Storage, Stop: Storage + Obj->NumUserOperands, |
201 | /* Delete */ del: false); |
202 | ::operator delete(Storage); |
203 | } |
204 | } |
205 | |
206 | } // namespace llvm |
207 | |