File: | lib/IR/User.cpp |
Warning: | line 135, column 5 Potential leak of memory pointed to by 'Storage' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- User.cpp - Implement the User class -------------------------------===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | ||||
10 | #include "llvm/IR/User.h" | |||
11 | #include "llvm/IR/Constant.h" | |||
12 | #include "llvm/IR/GlobalValue.h" | |||
13 | ||||
14 | namespace llvm { | |||
15 | class BasicBlock; | |||
16 | ||||
17 | //===----------------------------------------------------------------------===// | |||
18 | // User Class | |||
19 | //===----------------------------------------------------------------------===// | |||
20 | ||||
21 | void User::replaceUsesOfWith(Value *From, Value *To) { | |||
22 | if (From == To) return; // Duh what? | |||
23 | ||||
24 | assert((!isa<Constant>(this) || isa<GlobalValue>(this)) &&(static_cast <bool> ((!isa<Constant>(this) || isa <GlobalValue>(this)) && "Cannot call User::replaceUsesOfWith on a constant!" ) ? void (0) : __assert_fail ("(!isa<Constant>(this) || isa<GlobalValue>(this)) && \"Cannot call User::replaceUsesOfWith on a constant!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/IR/User.cpp" , 25, __extension__ __PRETTY_FUNCTION__)) | |||
25 | "Cannot call User::replaceUsesOfWith on a constant!")(static_cast <bool> ((!isa<Constant>(this) || isa <GlobalValue>(this)) && "Cannot call User::replaceUsesOfWith on a constant!" ) ? void (0) : __assert_fail ("(!isa<Constant>(this) || isa<GlobalValue>(this)) && \"Cannot call User::replaceUsesOfWith on a constant!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/IR/User.cpp" , 25, __extension__ __PRETTY_FUNCTION__)); | |||
26 | ||||
27 | for (unsigned i = 0, E = getNumOperands(); i != E; ++i) | |||
28 | if (getOperand(i) == From) { // Is This operand is pointing to oldval? | |||
29 | // The side effects of this setOperand call include linking to | |||
30 | // "To", adding "this" to the uses list of To, and | |||
31 | // most importantly, removing "this" from the use list of "From". | |||
32 | setOperand(i, To); // Fix it now... | |||
33 | } | |||
34 | } | |||
35 | ||||
36 | //===----------------------------------------------------------------------===// | |||
37 | // User allocHungoffUses Implementation | |||
38 | //===----------------------------------------------------------------------===// | |||
39 | ||||
40 | void User::allocHungoffUses(unsigned N, bool IsPhi) { | |||
41 | assert(HasHungOffUses && "alloc must have hung off uses")(static_cast <bool> (HasHungOffUses && "alloc must have hung off uses" ) ? void (0) : __assert_fail ("HasHungOffUses && \"alloc must have hung off uses\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/IR/User.cpp" , 41, __extension__ __PRETTY_FUNCTION__)); | |||
42 | ||||
43 | static_assert(alignof(Use) >= alignof(Use::UserRef), | |||
44 | "Alignment is insufficient for 'hung-off-uses' pieces"); | |||
45 | static_assert(alignof(Use::UserRef) >= alignof(BasicBlock *), | |||
46 | "Alignment is insufficient for 'hung-off-uses' pieces"); | |||
47 | ||||
48 | // Allocate the array of Uses, followed by a pointer (with bottom bit set) to | |||
49 | // the User. | |||
50 | size_t size = N * sizeof(Use) + sizeof(Use::UserRef); | |||
51 | if (IsPhi) | |||
52 | size += N * sizeof(BasicBlock *); | |||
53 | Use *Begin = static_cast<Use*>(::operator new(size)); | |||
54 | Use *End = Begin + N; | |||
55 | (void) new(End) Use::UserRef(const_cast<User*>(this), 1); | |||
56 | setOperandList(Use::initTags(Begin, End)); | |||
57 | } | |||
58 | ||||
59 | void User::growHungoffUses(unsigned NewNumUses, bool IsPhi) { | |||
60 | assert(HasHungOffUses && "realloc must have hung off uses")(static_cast <bool> (HasHungOffUses && "realloc must have hung off uses" ) ? void (0) : __assert_fail ("HasHungOffUses && \"realloc must have hung off uses\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/IR/User.cpp" , 60, __extension__ __PRETTY_FUNCTION__)); | |||
61 | ||||
62 | unsigned OldNumUses = getNumOperands(); | |||
63 | ||||
64 | // We don't support shrinking the number of uses. We wouldn't have enough | |||
65 | // space to copy the old uses in to the new space. | |||
66 | assert(NewNumUses > OldNumUses && "realloc must grow num uses")(static_cast <bool> (NewNumUses > OldNumUses && "realloc must grow num uses") ? void (0) : __assert_fail ("NewNumUses > OldNumUses && \"realloc must grow num uses\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/IR/User.cpp" , 66, __extension__ __PRETTY_FUNCTION__)); | |||
67 | ||||
68 | Use *OldOps = getOperandList(); | |||
69 | allocHungoffUses(NewNumUses, IsPhi); | |||
70 | Use *NewOps = getOperandList(); | |||
71 | ||||
72 | // Now copy from the old operands list to the new one. | |||
73 | std::copy(OldOps, OldOps + OldNumUses, NewOps); | |||
74 | ||||
75 | // If this is a Phi, then we need to copy the BB pointers too. | |||
76 | if (IsPhi) { | |||
77 | auto *OldPtr = | |||
78 | reinterpret_cast<char *>(OldOps + OldNumUses) + sizeof(Use::UserRef); | |||
79 | auto *NewPtr = | |||
80 | reinterpret_cast<char *>(NewOps + NewNumUses) + sizeof(Use::UserRef); | |||
81 | std::copy(OldPtr, OldPtr + (OldNumUses * sizeof(BasicBlock *)), NewPtr); | |||
82 | } | |||
83 | Use::zap(OldOps, OldOps + OldNumUses, true); | |||
84 | } | |||
85 | ||||
86 | ||||
87 | // This is a private struct used by `User` to track the co-allocated descriptor | |||
88 | // section. | |||
89 | struct DescriptorInfo { | |||
90 | intptr_t SizeInBytes; | |||
91 | }; | |||
92 | ||||
93 | ArrayRef<const uint8_t> User::getDescriptor() const { | |||
94 | auto MutableARef = const_cast<User *>(this)->getDescriptor(); | |||
95 | return {MutableARef.begin(), MutableARef.end()}; | |||
96 | } | |||
97 | ||||
98 | MutableArrayRef<uint8_t> User::getDescriptor() { | |||
99 | assert(HasDescriptor && "Don't call otherwise!")(static_cast <bool> (HasDescriptor && "Don't call otherwise!" ) ? void (0) : __assert_fail ("HasDescriptor && \"Don't call otherwise!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/IR/User.cpp" , 99, __extension__ __PRETTY_FUNCTION__)); | |||
100 | assert(!HasHungOffUses && "Invariant!")(static_cast <bool> (!HasHungOffUses && "Invariant!" ) ? void (0) : __assert_fail ("!HasHungOffUses && \"Invariant!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/IR/User.cpp" , 100, __extension__ __PRETTY_FUNCTION__)); | |||
101 | ||||
102 | auto *DI = reinterpret_cast<DescriptorInfo *>(getIntrusiveOperands()) - 1; | |||
103 | assert(DI->SizeInBytes != 0 && "Should not have had a descriptor otherwise!")(static_cast <bool> (DI->SizeInBytes != 0 && "Should not have had a descriptor otherwise!") ? void (0) : __assert_fail ("DI->SizeInBytes != 0 && \"Should not have had a descriptor otherwise!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/IR/User.cpp" , 103, __extension__ __PRETTY_FUNCTION__)); | |||
104 | ||||
105 | return MutableArrayRef<uint8_t>( | |||
106 | reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes, DI->SizeInBytes); | |||
107 | } | |||
108 | ||||
109 | //===----------------------------------------------------------------------===// | |||
110 | // User operator new Implementations | |||
111 | //===----------------------------------------------------------------------===// | |||
112 | ||||
113 | void *User::allocateFixedOperandUser(size_t Size, unsigned Us, | |||
114 | unsigned DescBytes) { | |||
115 | assert(Us < (1u << NumUserOperandsBits) && "Too many operands")(static_cast <bool> (Us < (1u << NumUserOperandsBits ) && "Too many operands") ? void (0) : __assert_fail ( "Us < (1u << NumUserOperandsBits) && \"Too many operands\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/IR/User.cpp" , 115, __extension__ __PRETTY_FUNCTION__)); | |||
116 | ||||
117 | static_assert(sizeof(DescriptorInfo) % sizeof(void *) == 0, "Required below"); | |||
118 | ||||
119 | unsigned DescBytesToAllocate = | |||
120 | DescBytes == 0 ? 0 : (DescBytes + sizeof(DescriptorInfo)); | |||
121 | assert(DescBytesToAllocate % sizeof(void *) == 0 &&(static_cast <bool> (DescBytesToAllocate % sizeof(void * ) == 0 && "We need this to satisfy alignment constraints for Uses" ) ? void (0) : __assert_fail ("DescBytesToAllocate % sizeof(void *) == 0 && \"We need this to satisfy alignment constraints for Uses\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/IR/User.cpp" , 122, __extension__ __PRETTY_FUNCTION__)) | |||
122 | "We need this to satisfy alignment constraints for Uses")(static_cast <bool> (DescBytesToAllocate % sizeof(void * ) == 0 && "We need this to satisfy alignment constraints for Uses" ) ? void (0) : __assert_fail ("DescBytesToAllocate % sizeof(void *) == 0 && \"We need this to satisfy alignment constraints for Uses\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/IR/User.cpp" , 122, __extension__ __PRETTY_FUNCTION__)); | |||
123 | ||||
124 | uint8_t *Storage = static_cast<uint8_t *>( | |||
125 | ::operator new(Size + sizeof(Use) * Us + DescBytesToAllocate)); | |||
126 | Use *Start = reinterpret_cast<Use *>(Storage + DescBytesToAllocate); | |||
127 | Use *End = Start + Us; | |||
128 | User *Obj = reinterpret_cast<User*>(End); | |||
129 | Obj->NumUserOperands = Us; | |||
130 | Obj->HasHungOffUses = false; | |||
131 | Obj->HasDescriptor = DescBytes != 0; | |||
132 | Use::initTags(Start, End); | |||
133 | ||||
134 | if (DescBytes != 0) { | |||
135 | auto *DescInfo = reinterpret_cast<DescriptorInfo *>(Storage + DescBytes); | |||
| ||||
136 | DescInfo->SizeInBytes = DescBytes; | |||
137 | } | |||
138 | ||||
139 | return Obj; | |||
140 | } | |||
141 | ||||
142 | void *User::operator new(size_t Size, unsigned Us) { | |||
143 | return allocateFixedOperandUser(Size, Us, 0); | |||
144 | } | |||
145 | ||||
146 | void *User::operator new(size_t Size, unsigned Us, unsigned DescBytes) { | |||
147 | return allocateFixedOperandUser(Size, Us, DescBytes); | |||
| ||||
148 | } | |||
149 | ||||
150 | void *User::operator new(size_t Size) { | |||
151 | // Allocate space for a single Use* | |||
152 | void *Storage = ::operator new(Size + sizeof(Use *)); | |||
153 | Use **HungOffOperandList = static_cast<Use **>(Storage); | |||
154 | User *Obj = reinterpret_cast<User *>(HungOffOperandList + 1); | |||
155 | Obj->NumUserOperands = 0; | |||
156 | Obj->HasHungOffUses = true; | |||
157 | Obj->HasDescriptor = false; | |||
158 | *HungOffOperandList = nullptr; | |||
159 | return Obj; | |||
160 | } | |||
161 | ||||
162 | //===----------------------------------------------------------------------===// | |||
163 | // User operator delete Implementation | |||
164 | //===----------------------------------------------------------------------===// | |||
165 | ||||
166 | void User::operator delete(void *Usr) { | |||
167 | // Hung off uses use a single Use* before the User, while other subclasses | |||
168 | // use a Use[] allocated prior to the user. | |||
169 | User *Obj = static_cast<User *>(Usr); | |||
170 | if (Obj->HasHungOffUses) { | |||
171 | assert(!Obj->HasDescriptor && "not supported!")(static_cast <bool> (!Obj->HasDescriptor && "not supported!" ) ? void (0) : __assert_fail ("!Obj->HasDescriptor && \"not supported!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/lib/IR/User.cpp" , 171, __extension__ __PRETTY_FUNCTION__)); | |||
172 | ||||
173 | Use **HungOffOperandList = static_cast<Use **>(Usr) - 1; | |||
174 | // drop the hung off uses. | |||
175 | Use::zap(*HungOffOperandList, *HungOffOperandList + Obj->NumUserOperands, | |||
176 | /* Delete */ true); | |||
177 | ::operator delete(HungOffOperandList); | |||
178 | } else if (Obj->HasDescriptor) { | |||
179 | Use *UseBegin = static_cast<Use *>(Usr) - Obj->NumUserOperands; | |||
180 | Use::zap(UseBegin, UseBegin + Obj->NumUserOperands, /* Delete */ false); | |||
181 | ||||
182 | auto *DI = reinterpret_cast<DescriptorInfo *>(UseBegin) - 1; | |||
183 | uint8_t *Storage = reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes; | |||
184 | ::operator delete(Storage); | |||
185 | } else { | |||
186 | Use *Storage = static_cast<Use *>(Usr) - Obj->NumUserOperands; | |||
187 | Use::zap(Storage, Storage + Obj->NumUserOperands, | |||
188 | /* Delete */ false); | |||
189 | ::operator delete(Storage); | |||
190 | } | |||
191 | } | |||
192 | ||||
193 | } // End llvm namespace |