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, |
| 47 | "Alignment sufficient for hung-off-uses pieces"); |
| 48 | static_assert(AlignOf<Use::UserRef>::Alignment >= AlignOf<BasicBlock *>::Alignment, |
| 49 | "Alignment sufficient for hung-off-uses pieces"); |
| 50 | |
Jay Foad | 61ea0e4 | 2011-06-23 09:09:15 +0000 | [diff] [blame] | 51 | // Allocate the array of Uses, followed by a pointer (with bottom bit set) to |
| 52 | // the User. |
| 53 | size_t size = N * sizeof(Use) + sizeof(Use::UserRef); |
Pete Cooper | 87b925b | 2015-06-10 22:38:30 +0000 | [diff] [blame] | 54 | if (IsPhi) |
| 55 | size += N * sizeof(BasicBlock *); |
Jay Foad | 61ea0e4 | 2011-06-23 09:09:15 +0000 | [diff] [blame] | 56 | Use *Begin = static_cast<Use*>(::operator new(size)); |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 57 | Use *End = Begin + N; |
Jay Foad | 5c54d75 | 2011-06-20 14:12:33 +0000 | [diff] [blame] | 58 | (void) new(End) Use::UserRef(const_cast<User*>(this), 1); |
Pete Cooper | 74510a4 | 2015-06-12 17:48:05 +0000 | [diff] [blame] | 59 | setOperandList(Use::initTags(Begin, End)); |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 60 | } |
| 61 | |
Pete Cooper | 93f9ff5 | 2015-06-10 22:38:41 +0000 | [diff] [blame] | 62 | void User::growHungoffUses(unsigned NewNumUses, bool IsPhi) { |
| 63 | assert(HasHungOffUses && "realloc must have hung off uses"); |
| 64 | |
| 65 | unsigned OldNumUses = getNumOperands(); |
| 66 | |
| 67 | // We don't support shrinking the number of uses. We wouldn't have enough |
| 68 | // space to copy the old uses in to the new space. |
| 69 | assert(NewNumUses > OldNumUses && "realloc must grow num uses"); |
| 70 | |
Pete Cooper | 74510a4 | 2015-06-12 17:48:05 +0000 | [diff] [blame] | 71 | Use *OldOps = getOperandList(); |
Pete Cooper | 93f9ff5 | 2015-06-10 22:38:41 +0000 | [diff] [blame] | 72 | allocHungoffUses(NewNumUses, IsPhi); |
Pete Cooper | 74510a4 | 2015-06-12 17:48:05 +0000 | [diff] [blame] | 73 | Use *NewOps = getOperandList(); |
Pete Cooper | 93f9ff5 | 2015-06-10 22:38:41 +0000 | [diff] [blame] | 74 | |
| 75 | // Now copy from the old operands list to the new one. |
| 76 | std::copy(OldOps, OldOps + OldNumUses, NewOps); |
| 77 | |
| 78 | // If this is a Phi, then we need to copy the BB pointers too. |
| 79 | if (IsPhi) { |
| 80 | auto *OldPtr = |
| 81 | reinterpret_cast<char *>(OldOps + OldNumUses) + sizeof(Use::UserRef); |
| 82 | auto *NewPtr = |
| 83 | reinterpret_cast<char *>(NewOps + NewNumUses) + sizeof(Use::UserRef); |
| 84 | std::copy(OldPtr, OldPtr + (OldNumUses * sizeof(BasicBlock *)), NewPtr); |
| 85 | } |
| 86 | Use::zap(OldOps, OldOps + OldNumUses, true); |
| 87 | } |
| 88 | |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 89 | //===----------------------------------------------------------------------===// |
| 90 | // User operator new Implementations |
| 91 | //===----------------------------------------------------------------------===// |
| 92 | |
Pete Cooper | c91fda3 | 2015-06-12 17:48:14 +0000 | [diff] [blame] | 93 | void *User::operator new(size_t Size, unsigned Us) { |
Pete Cooper | b4eede2 | 2015-06-12 17:48:10 +0000 | [diff] [blame] | 94 | assert(Us < (1u << NumUserOperandsBits) && "Too many operands"); |
Pete Cooper | c91fda3 | 2015-06-12 17:48:14 +0000 | [diff] [blame] | 95 | void *Storage = ::operator new(Size + sizeof(Use) * Us); |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 96 | Use *Start = static_cast<Use*>(Storage); |
| 97 | Use *End = Start + Us; |
| 98 | User *Obj = reinterpret_cast<User*>(End); |
Pete Cooper | b4eede2 | 2015-06-12 17:48:10 +0000 | [diff] [blame] | 99 | Obj->NumUserOperands = Us; |
Pete Cooper | b676b01 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 100 | Obj->HasHungOffUses = false; |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 101 | Use::initTags(Start, End); |
| 102 | return Obj; |
| 103 | } |
| 104 | |
Pete Cooper | c91fda3 | 2015-06-12 17:48:14 +0000 | [diff] [blame] | 105 | void *User::operator new(size_t Size) { |
Pete Cooper | b676b01 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 106 | // Allocate space for a single Use* |
| 107 | void *Storage = ::operator new(Size + sizeof(Use *)); |
| 108 | Use **HungOffOperandList = static_cast<Use **>(Storage); |
| 109 | User *Obj = reinterpret_cast<User *>(HungOffOperandList + 1); |
Pete Cooper | c91fda3 | 2015-06-12 17:48:14 +0000 | [diff] [blame] | 110 | Obj->NumUserOperands = 0; |
Pete Cooper | b676b01 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 111 | Obj->HasHungOffUses = true; |
| 112 | *HungOffOperandList = nullptr; |
Pete Cooper | c91fda3 | 2015-06-12 17:48:14 +0000 | [diff] [blame] | 113 | return Obj; |
| 114 | } |
| 115 | |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 116 | //===----------------------------------------------------------------------===// |
| 117 | // User operator delete Implementation |
| 118 | //===----------------------------------------------------------------------===// |
| 119 | |
| 120 | void User::operator delete(void *Usr) { |
Pete Cooper | b676b01 | 2015-06-12 17:48:18 +0000 | [diff] [blame] | 121 | // Hung off uses use a single Use* before the User, while other subclasses |
| 122 | // use a Use[] allocated prior to the user. |
| 123 | User *Obj = static_cast<User *>(Usr); |
| 124 | if (Obj->HasHungOffUses) { |
| 125 | Use **HungOffOperandList = static_cast<Use **>(Usr) - 1; |
| 126 | // drop the hung off uses. |
| 127 | Use::zap(*HungOffOperandList, *HungOffOperandList + Obj->NumUserOperands, |
| 128 | /* Delete */ true); |
| 129 | ::operator delete(HungOffOperandList); |
| 130 | } else { |
| 131 | Use *Storage = static_cast<Use *>(Usr) - Obj->NumUserOperands; |
| 132 | Use::zap(Storage, Storage + Obj->NumUserOperands, |
| 133 | /* Delete */ false); |
| 134 | ::operator delete(Storage); |
| 135 | } |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 136 | } |
| 137 | |
Richard Smith | 1f6f455 | 2012-10-24 00:30:41 +0000 | [diff] [blame] | 138 | //===----------------------------------------------------------------------===// |
| 139 | // Operator Class |
| 140 | //===----------------------------------------------------------------------===// |
| 141 | |
| 142 | Operator::~Operator() { |
| 143 | llvm_unreachable("should never destroy an Operator"); |
| 144 | } |
| 145 | |
Jay Foad | 59809c7 | 2011-01-16 08:10:57 +0000 | [diff] [blame] | 146 | } // End llvm namespace |