Jay Foad | bdbe342 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 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 | |
Chandler Carruth | 0b8c9a8 | 2013-01-02 11:36:10 +0000 | [diff] [blame] | 10 | #include "llvm/IR/User.h" |
| 11 | #include "llvm/IR/Constant.h" |
| 12 | #include "llvm/IR/GlobalValue.h" |
Jay Foad | bdbe342 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 13 | |
| 14 | namespace llvm { |
Pete Cooper | e0e42bb | 2015-06-10 22:38:30 +0000 | [diff] [blame] | 15 | class BasicBlock; |
Jay Foad | bdbe342 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 16 | |
| 17 | //===----------------------------------------------------------------------===// |
| 18 | // User Class |
| 19 | //===----------------------------------------------------------------------===// |
| 20 | |
Jay Foad | bdbe342 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 21 | void User::replaceUsesOfWith(Value *From, Value *To) { |
| 22 | if (From == To) return; // Duh what? |
| 23 | |
| 24 | assert((!isa<Constant>(this) || isa<GlobalValue>(this)) && |
| 25 | "Cannot call User::replaceUsesOfWith on a constant!"); |
| 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 | |
Pete Cooper | ea42367 | 2015-06-10 22:38:46 +0000 | [diff] [blame] | 40 | void User::allocHungoffUses(unsigned N, bool IsPhi) { |
Pete Cooper | 8b351e4 | 2015-06-12 17:48:14 +0000 | [diff] [blame] | 41 | assert(HasHungOffUses && "alloc must have hung off uses"); |
James Y Knight | 4a80b4b | 2015-06-17 01:21:20 +0000 | [diff] [blame] | 42 | |
Benjamin Kramer | cb58e1e | 2016-10-20 15:02:18 +0000 | [diff] [blame] | 43 | static_assert(alignof(Use) >= alignof(Use::UserRef), |
James Y Knight | 4dd3b87 | 2015-06-17 13:53:12 +0000 | [diff] [blame] | 44 | "Alignment is insufficient for 'hung-off-uses' pieces"); |
Benjamin Kramer | cb58e1e | 2016-10-20 15:02:18 +0000 | [diff] [blame] | 45 | static_assert(alignof(Use::UserRef) >= alignof(BasicBlock *), |
James Y Knight | 4dd3b87 | 2015-06-17 13:53:12 +0000 | [diff] [blame] | 46 | "Alignment is insufficient for 'hung-off-uses' pieces"); |
James Y Knight | 4a80b4b | 2015-06-17 01:21:20 +0000 | [diff] [blame] | 47 | |
Jay Foad | 95c3e48 | 2011-06-23 09:09:15 +0000 | [diff] [blame] | 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); |
Pete Cooper | e0e42bb | 2015-06-10 22:38:30 +0000 | [diff] [blame] | 51 | if (IsPhi) |
| 52 | size += N * sizeof(BasicBlock *); |
Jay Foad | 95c3e48 | 2011-06-23 09:09:15 +0000 | [diff] [blame] | 53 | Use *Begin = static_cast<Use*>(::operator new(size)); |
Jay Foad | bdbe342 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 54 | Use *End = Begin + N; |
Jay Foad | 691c05b | 2011-06-20 14:12:33 +0000 | [diff] [blame] | 55 | (void) new(End) Use::UserRef(const_cast<User*>(this), 1); |
Pete Cooper | cff40fc | 2015-06-12 17:48:05 +0000 | [diff] [blame] | 56 | setOperandList(Use::initTags(Begin, End)); |
Jay Foad | bdbe342 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 57 | } |
| 58 | |
Pete Cooper | 33102d2 | 2015-06-10 22:38:41 +0000 | [diff] [blame] | 59 | void User::growHungoffUses(unsigned NewNumUses, bool IsPhi) { |
| 60 | assert(HasHungOffUses && "realloc must have hung off uses"); |
| 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"); |
| 67 | |
Pete Cooper | cff40fc | 2015-06-12 17:48:05 +0000 | [diff] [blame] | 68 | Use *OldOps = getOperandList(); |
Pete Cooper | 33102d2 | 2015-06-10 22:38:41 +0000 | [diff] [blame] | 69 | allocHungoffUses(NewNumUses, IsPhi); |
Pete Cooper | cff40fc | 2015-06-12 17:48:05 +0000 | [diff] [blame] | 70 | Use *NewOps = getOperandList(); |
Pete Cooper | 33102d2 | 2015-06-10 22:38:41 +0000 | [diff] [blame] | 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 | |
Sanjoy Das | 4769a74 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 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!"); |
| 100 | assert(!HasHungOffUses && "Invariant!"); |
| 101 | |
| 102 | auto *DI = reinterpret_cast<DescriptorInfo *>(getIntrusiveOperands()) - 1; |
| 103 | assert(DI->SizeInBytes != 0 && "Should not have had a descriptor otherwise!"); |
| 104 | |
| 105 | return MutableArrayRef<uint8_t>( |
| 106 | reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes, DI->SizeInBytes); |
| 107 | } |
| 108 | |
Jay Foad | bdbe342 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 109 | //===----------------------------------------------------------------------===// |
| 110 | // User operator new Implementations |
| 111 | //===----------------------------------------------------------------------===// |
| 112 | |
Sanjoy Das | 4769a74 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 113 | void *User::allocateFixedOperandUser(size_t Size, unsigned Us, |
| 114 | unsigned DescBytes) { |
Pete Cooper | aaa3fa6 | 2015-06-12 17:48:10 +0000 | [diff] [blame] | 115 | assert(Us < (1u << NumUserOperandsBits) && "Too many operands"); |
Sanjoy Das | 4769a74 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 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 && |
| 122 | "We need this to satisfy alignment constraints for Uses"); |
| 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); |
Jay Foad | bdbe342 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 127 | Use *End = Start + Us; |
| 128 | User *Obj = reinterpret_cast<User*>(End); |
Pete Cooper | aaa3fa6 | 2015-06-12 17:48:10 +0000 | [diff] [blame] | 129 | Obj->NumUserOperands = Us; |
Pete Cooper | a6ff221 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 130 | Obj->HasHungOffUses = false; |
Sanjoy Das | 4769a74 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 131 | Obj->HasDescriptor = DescBytes != 0; |
Jay Foad | bdbe342 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 132 | Use::initTags(Start, End); |
Sanjoy Das | 4769a74 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 133 | |
| 134 | if (DescBytes != 0) { |
| 135 | auto *DescInfo = reinterpret_cast<DescriptorInfo *>(Storage + DescBytes); |
| 136 | DescInfo->SizeInBytes = DescBytes; |
| 137 | } |
| 138 | |
Jay Foad | bdbe342 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 139 | return Obj; |
| 140 | } |
| 141 | |
Sanjoy Das | 4769a74 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 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 | |
Pete Cooper | 8b351e4 | 2015-06-12 17:48:14 +0000 | [diff] [blame] | 150 | void *User::operator new(size_t Size) { |
Pete Cooper | a6ff221 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 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); |
Pete Cooper | 8b351e4 | 2015-06-12 17:48:14 +0000 | [diff] [blame] | 155 | Obj->NumUserOperands = 0; |
Pete Cooper | a6ff221 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 156 | Obj->HasHungOffUses = true; |
Sanjoy Das | 4769a74 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 157 | Obj->HasDescriptor = false; |
Pete Cooper | a6ff221 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 158 | *HungOffOperandList = nullptr; |
Pete Cooper | 8b351e4 | 2015-06-12 17:48:14 +0000 | [diff] [blame] | 159 | return Obj; |
| 160 | } |
| 161 | |
Jay Foad | bdbe342 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 162 | //===----------------------------------------------------------------------===// |
| 163 | // User operator delete Implementation |
| 164 | //===----------------------------------------------------------------------===// |
| 165 | |
Naomi Musgrave | 950c009 | 2015-08-31 21:06:08 +0000 | [diff] [blame] | 166 | void User::operator delete(void *Usr) { |
Pete Cooper | a6ff221 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 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) { |
Sanjoy Das | 4769a74 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 171 | assert(!Obj->HasDescriptor && "not supported!"); |
| 172 | |
Pete Cooper | a6ff221 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 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); |
Sanjoy Das | 4769a74 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 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); |
Pete Cooper | a6ff221 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 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 | } |
Jay Foad | bdbe342 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 191 | } |
| 192 | |
Alexander Kornienko | cd52a7a | 2015-06-23 09:49:53 +0000 | [diff] [blame] | 193 | } // End llvm namespace |