Jay Foad | 59809c7 | 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 | 9fb823b | 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" |
| 13 | #include "llvm/IR/Operator.h" |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 14 | |
| 15 | namespace llvm { |
Pete Cooper | 87b925b | 2015-06-10 22:38:30 +0000 | [diff] [blame] | 16 | class BasicBlock; |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 17 | |
| 18 | //===----------------------------------------------------------------------===// |
| 19 | // User Class |
| 20 | //===----------------------------------------------------------------------===// |
| 21 | |
David Blaikie | 3a15e14 | 2011-12-01 08:00:17 +0000 | [diff] [blame] | 22 | void User::anchor() {} |
| 23 | |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 24 | void User::replaceUsesOfWith(Value *From, Value *To) { |
| 25 | if (From == To) return; // Duh what? |
| 26 | |
| 27 | assert((!isa<Constant>(this) || isa<GlobalValue>(this)) && |
| 28 | "Cannot call User::replaceUsesOfWith on a constant!"); |
| 29 | |
| 30 | for (unsigned i = 0, E = getNumOperands(); i != E; ++i) |
| 31 | if (getOperand(i) == From) { // Is This operand is pointing to oldval? |
| 32 | // The side effects of this setOperand call include linking to |
| 33 | // "To", adding "this" to the uses list of To, and |
| 34 | // most importantly, removing "this" from the use list of "From". |
| 35 | setOperand(i, To); // Fix it now... |
| 36 | } |
| 37 | } |
| 38 | |
| 39 | //===----------------------------------------------------------------------===// |
| 40 | // User allocHungoffUses Implementation |
| 41 | //===----------------------------------------------------------------------===// |
| 42 | |
Pete Cooper | 3fc3040 | 2015-06-10 22:38:46 +0000 | [diff] [blame] | 43 | void User::allocHungoffUses(unsigned N, bool IsPhi) { |
Pete Cooper | c91fda3 | 2015-06-12 17:48:14 +0000 | [diff] [blame] | 44 | assert(HasHungOffUses && "alloc must have hung off uses"); |
James Y Knight | 8096d34 | 2015-06-17 01:21:20 +0000 | [diff] [blame] | 45 | |
| 46 | static_assert(AlignOf<Use>::Alignment >= AlignOf<Use::UserRef>::Alignment, |
James Y Knight | f27e441 | 2015-06-17 13:53:12 +0000 | [diff] [blame] | 47 | "Alignment is insufficient for 'hung-off-uses' pieces"); |
| 48 | static_assert(AlignOf<Use::UserRef>::Alignment >= |
| 49 | AlignOf<BasicBlock *>::Alignment, |
| 50 | "Alignment is insufficient for 'hung-off-uses' pieces"); |
James Y Knight | 8096d34 | 2015-06-17 01:21:20 +0000 | [diff] [blame] | 51 | |
Jay Foad | 61ea0e4 | 2011-06-23 09:09:15 +0000 | [diff] [blame] | 52 | // Allocate the array of Uses, followed by a pointer (with bottom bit set) to |
| 53 | // the User. |
| 54 | size_t size = N * sizeof(Use) + sizeof(Use::UserRef); |
Pete Cooper | 87b925b | 2015-06-10 22:38:30 +0000 | [diff] [blame] | 55 | if (IsPhi) |
| 56 | size += N * sizeof(BasicBlock *); |
Jay Foad | 61ea0e4 | 2011-06-23 09:09:15 +0000 | [diff] [blame] | 57 | Use *Begin = static_cast<Use*>(::operator new(size)); |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 58 | Use *End = Begin + N; |
Jay Foad | 5c54d75 | 2011-06-20 14:12:33 +0000 | [diff] [blame] | 59 | (void) new(End) Use::UserRef(const_cast<User*>(this), 1); |
Pete Cooper | 74510a4 | 2015-06-12 17:48:05 +0000 | [diff] [blame] | 60 | setOperandList(Use::initTags(Begin, End)); |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 61 | } |
| 62 | |
Pete Cooper | 93f9ff5 | 2015-06-10 22:38:41 +0000 | [diff] [blame] | 63 | void User::growHungoffUses(unsigned NewNumUses, bool IsPhi) { |
| 64 | assert(HasHungOffUses && "realloc must have hung off uses"); |
| 65 | |
| 66 | unsigned OldNumUses = getNumOperands(); |
| 67 | |
| 68 | // We don't support shrinking the number of uses. We wouldn't have enough |
| 69 | // space to copy the old uses in to the new space. |
| 70 | assert(NewNumUses > OldNumUses && "realloc must grow num uses"); |
| 71 | |
Pete Cooper | 74510a4 | 2015-06-12 17:48:05 +0000 | [diff] [blame] | 72 | Use *OldOps = getOperandList(); |
Pete Cooper | 93f9ff5 | 2015-06-10 22:38:41 +0000 | [diff] [blame] | 73 | allocHungoffUses(NewNumUses, IsPhi); |
Pete Cooper | 74510a4 | 2015-06-12 17:48:05 +0000 | [diff] [blame] | 74 | Use *NewOps = getOperandList(); |
Pete Cooper | 93f9ff5 | 2015-06-10 22:38:41 +0000 | [diff] [blame] | 75 | |
| 76 | // Now copy from the old operands list to the new one. |
| 77 | std::copy(OldOps, OldOps + OldNumUses, NewOps); |
| 78 | |
| 79 | // If this is a Phi, then we need to copy the BB pointers too. |
| 80 | if (IsPhi) { |
| 81 | auto *OldPtr = |
| 82 | reinterpret_cast<char *>(OldOps + OldNumUses) + sizeof(Use::UserRef); |
| 83 | auto *NewPtr = |
| 84 | reinterpret_cast<char *>(NewOps + NewNumUses) + sizeof(Use::UserRef); |
| 85 | std::copy(OldPtr, OldPtr + (OldNumUses * sizeof(BasicBlock *)), NewPtr); |
| 86 | } |
| 87 | Use::zap(OldOps, OldOps + OldNumUses, true); |
| 88 | } |
| 89 | |
Sanjoy Das | b07fc57 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 90 | |
| 91 | // This is a private struct used by `User` to track the co-allocated descriptor |
| 92 | // section. |
| 93 | struct DescriptorInfo { |
| 94 | intptr_t SizeInBytes; |
| 95 | }; |
| 96 | |
| 97 | ArrayRef<const uint8_t> User::getDescriptor() const { |
| 98 | auto MutableARef = const_cast<User *>(this)->getDescriptor(); |
| 99 | return {MutableARef.begin(), MutableARef.end()}; |
| 100 | } |
| 101 | |
| 102 | MutableArrayRef<uint8_t> User::getDescriptor() { |
| 103 | assert(HasDescriptor && "Don't call otherwise!"); |
| 104 | assert(!HasHungOffUses && "Invariant!"); |
| 105 | |
| 106 | auto *DI = reinterpret_cast<DescriptorInfo *>(getIntrusiveOperands()) - 1; |
| 107 | assert(DI->SizeInBytes != 0 && "Should not have had a descriptor otherwise!"); |
| 108 | |
| 109 | return MutableArrayRef<uint8_t>( |
| 110 | reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes, DI->SizeInBytes); |
| 111 | } |
| 112 | |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 113 | //===----------------------------------------------------------------------===// |
| 114 | // User operator new Implementations |
| 115 | //===----------------------------------------------------------------------===// |
| 116 | |
Sanjoy Das | b07fc57 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 117 | void *User::allocateFixedOperandUser(size_t Size, unsigned Us, |
| 118 | unsigned DescBytes) { |
Pete Cooper | b4eede2 | 2015-06-12 17:48:10 +0000 | [diff] [blame] | 119 | assert(Us < (1u << NumUserOperandsBits) && "Too many operands"); |
Sanjoy Das | b07fc57 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 120 | |
| 121 | static_assert(sizeof(DescriptorInfo) % sizeof(void *) == 0, "Required below"); |
| 122 | |
| 123 | unsigned DescBytesToAllocate = |
| 124 | DescBytes == 0 ? 0 : (DescBytes + sizeof(DescriptorInfo)); |
| 125 | assert(DescBytesToAllocate % sizeof(void *) == 0 && |
| 126 | "We need this to satisfy alignment constraints for Uses"); |
| 127 | |
| 128 | uint8_t *Storage = static_cast<uint8_t *>( |
| 129 | ::operator new(Size + sizeof(Use) * Us + DescBytesToAllocate)); |
| 130 | Use *Start = reinterpret_cast<Use *>(Storage + DescBytesToAllocate); |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 131 | Use *End = Start + Us; |
| 132 | User *Obj = reinterpret_cast<User*>(End); |
Pete Cooper | b4eede2 | 2015-06-12 17:48:10 +0000 | [diff] [blame] | 133 | Obj->NumUserOperands = Us; |
Pete Cooper | b676b01 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 134 | Obj->HasHungOffUses = false; |
Sanjoy Das | b07fc57 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 135 | Obj->HasDescriptor = DescBytes != 0; |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 136 | Use::initTags(Start, End); |
Sanjoy Das | b07fc57 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 137 | |
| 138 | if (DescBytes != 0) { |
| 139 | auto *DescInfo = reinterpret_cast<DescriptorInfo *>(Storage + DescBytes); |
| 140 | DescInfo->SizeInBytes = DescBytes; |
| 141 | } |
| 142 | |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 143 | return Obj; |
| 144 | } |
| 145 | |
Sanjoy Das | b07fc57 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 146 | void *User::operator new(size_t Size, unsigned Us) { |
| 147 | return allocateFixedOperandUser(Size, Us, 0); |
| 148 | } |
| 149 | |
| 150 | void *User::operator new(size_t Size, unsigned Us, unsigned DescBytes) { |
| 151 | return allocateFixedOperandUser(Size, Us, DescBytes); |
| 152 | } |
| 153 | |
Pete Cooper | c91fda3 | 2015-06-12 17:48:14 +0000 | [diff] [blame] | 154 | void *User::operator new(size_t Size) { |
Pete Cooper | b676b01 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 155 | // Allocate space for a single Use* |
| 156 | void *Storage = ::operator new(Size + sizeof(Use *)); |
| 157 | Use **HungOffOperandList = static_cast<Use **>(Storage); |
| 158 | User *Obj = reinterpret_cast<User *>(HungOffOperandList + 1); |
Pete Cooper | c91fda3 | 2015-06-12 17:48:14 +0000 | [diff] [blame] | 159 | Obj->NumUserOperands = 0; |
Pete Cooper | b676b01 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 160 | Obj->HasHungOffUses = true; |
Sanjoy Das | b07fc57 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 161 | Obj->HasDescriptor = false; |
Pete Cooper | b676b01 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 162 | *HungOffOperandList = nullptr; |
Pete Cooper | c91fda3 | 2015-06-12 17:48:14 +0000 | [diff] [blame] | 163 | return Obj; |
| 164 | } |
| 165 | |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 166 | //===----------------------------------------------------------------------===// |
| 167 | // User operator delete Implementation |
| 168 | //===----------------------------------------------------------------------===// |
| 169 | |
Naomi Musgrave | 21c1bc4 | 2015-08-31 21:06:08 +0000 | [diff] [blame] | 170 | void User::operator delete(void *Usr) { |
Pete Cooper | b676b01 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 171 | // Hung off uses use a single Use* before the User, while other subclasses |
| 172 | // use a Use[] allocated prior to the user. |
| 173 | User *Obj = static_cast<User *>(Usr); |
| 174 | if (Obj->HasHungOffUses) { |
Sanjoy Das | b07fc57 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 175 | assert(!Obj->HasDescriptor && "not supported!"); |
| 176 | |
Pete Cooper | b676b01 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 177 | Use **HungOffOperandList = static_cast<Use **>(Usr) - 1; |
| 178 | // drop the hung off uses. |
| 179 | Use::zap(*HungOffOperandList, *HungOffOperandList + Obj->NumUserOperands, |
| 180 | /* Delete */ true); |
| 181 | ::operator delete(HungOffOperandList); |
Sanjoy Das | b07fc57 | 2015-09-24 01:00:49 +0000 | [diff] [blame] | 182 | } else if (Obj->HasDescriptor) { |
| 183 | Use *UseBegin = static_cast<Use *>(Usr) - Obj->NumUserOperands; |
| 184 | Use::zap(UseBegin, UseBegin + Obj->NumUserOperands, /* Delete */ false); |
| 185 | |
| 186 | auto *DI = reinterpret_cast<DescriptorInfo *>(UseBegin) - 1; |
| 187 | uint8_t *Storage = reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes; |
| 188 | ::operator delete(Storage); |
Pete Cooper | b676b01 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 189 | } else { |
| 190 | Use *Storage = static_cast<Use *>(Usr) - Obj->NumUserOperands; |
| 191 | Use::zap(Storage, Storage + Obj->NumUserOperands, |
| 192 | /* Delete */ false); |
| 193 | ::operator delete(Storage); |
| 194 | } |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 195 | } |
| 196 | |
Richard Smith | 1f6f455 | 2012-10-24 00:30:41 +0000 | [diff] [blame] | 197 | //===----------------------------------------------------------------------===// |
| 198 | // Operator Class |
| 199 | //===----------------------------------------------------------------------===// |
| 200 | |
| 201 | Operator::~Operator() { |
| 202 | llvm_unreachable("should never destroy an Operator"); |
| 203 | } |
| 204 | |
Alexander Kornienko | f00654e | 2015-06-23 09:49:53 +0000 | [diff] [blame] | 205 | } // End llvm namespace |