1249259Sdim//===-- User.cpp - Implement the User class -------------------------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim 10249259Sdim#include "llvm/IR/User.h" 11249259Sdim#include "llvm/IR/Constant.h" 12249259Sdim#include "llvm/IR/GlobalValue.h" 13249259Sdim#include "llvm/IR/Operator.h" 14249259Sdim 15249259Sdimnamespace llvm { 16288943Sdimclass BasicBlock; 17249259Sdim 18249259Sdim//===----------------------------------------------------------------------===// 19249259Sdim// User Class 20249259Sdim//===----------------------------------------------------------------------===// 21249259Sdim 22249259Sdimvoid User::anchor() {} 23249259Sdim 24249259Sdimvoid User::replaceUsesOfWith(Value *From, Value *To) { 25249259Sdim if (From == To) return; // Duh what? 26249259Sdim 27249259Sdim assert((!isa<Constant>(this) || isa<GlobalValue>(this)) && 28249259Sdim "Cannot call User::replaceUsesOfWith on a constant!"); 29249259Sdim 30249259Sdim for (unsigned i = 0, E = getNumOperands(); i != E; ++i) 31249259Sdim if (getOperand(i) == From) { // Is This operand is pointing to oldval? 32249259Sdim // The side effects of this setOperand call include linking to 33249259Sdim // "To", adding "this" to the uses list of To, and 34249259Sdim // most importantly, removing "this" from the use list of "From". 35249259Sdim setOperand(i, To); // Fix it now... 36249259Sdim } 37249259Sdim} 38249259Sdim 39249259Sdim//===----------------------------------------------------------------------===// 40249259Sdim// User allocHungoffUses Implementation 41249259Sdim//===----------------------------------------------------------------------===// 42249259Sdim 43288943Sdimvoid User::allocHungoffUses(unsigned N, bool IsPhi) { 44288943Sdim assert(HasHungOffUses && "alloc must have hung off uses"); 45288943Sdim 46288943Sdim static_assert(AlignOf<Use>::Alignment >= AlignOf<Use::UserRef>::Alignment, 47288943Sdim "Alignment is insufficient for 'hung-off-uses' pieces"); 48288943Sdim static_assert(AlignOf<Use::UserRef>::Alignment >= 49288943Sdim AlignOf<BasicBlock *>::Alignment, 50288943Sdim "Alignment is insufficient for 'hung-off-uses' pieces"); 51288943Sdim 52249259Sdim // Allocate the array of Uses, followed by a pointer (with bottom bit set) to 53249259Sdim // the User. 54249259Sdim size_t size = N * sizeof(Use) + sizeof(Use::UserRef); 55288943Sdim if (IsPhi) 56288943Sdim size += N * sizeof(BasicBlock *); 57249259Sdim Use *Begin = static_cast<Use*>(::operator new(size)); 58249259Sdim Use *End = Begin + N; 59249259Sdim (void) new(End) Use::UserRef(const_cast<User*>(this), 1); 60288943Sdim setOperandList(Use::initTags(Begin, End)); 61249259Sdim} 62249259Sdim 63288943Sdimvoid User::growHungoffUses(unsigned NewNumUses, bool IsPhi) { 64288943Sdim assert(HasHungOffUses && "realloc must have hung off uses"); 65288943Sdim 66288943Sdim unsigned OldNumUses = getNumOperands(); 67288943Sdim 68288943Sdim // We don't support shrinking the number of uses. We wouldn't have enough 69288943Sdim // space to copy the old uses in to the new space. 70288943Sdim assert(NewNumUses > OldNumUses && "realloc must grow num uses"); 71288943Sdim 72288943Sdim Use *OldOps = getOperandList(); 73288943Sdim allocHungoffUses(NewNumUses, IsPhi); 74288943Sdim Use *NewOps = getOperandList(); 75288943Sdim 76288943Sdim // Now copy from the old operands list to the new one. 77288943Sdim std::copy(OldOps, OldOps + OldNumUses, NewOps); 78288943Sdim 79288943Sdim // If this is a Phi, then we need to copy the BB pointers too. 80288943Sdim if (IsPhi) { 81288943Sdim auto *OldPtr = 82288943Sdim reinterpret_cast<char *>(OldOps + OldNumUses) + sizeof(Use::UserRef); 83288943Sdim auto *NewPtr = 84288943Sdim reinterpret_cast<char *>(NewOps + NewNumUses) + sizeof(Use::UserRef); 85288943Sdim std::copy(OldPtr, OldPtr + (OldNumUses * sizeof(BasicBlock *)), NewPtr); 86288943Sdim } 87288943Sdim Use::zap(OldOps, OldOps + OldNumUses, true); 88288943Sdim} 89288943Sdim 90296417Sdim 91296417Sdim// This is a private struct used by `User` to track the co-allocated descriptor 92296417Sdim// section. 93296417Sdimstruct DescriptorInfo { 94296417Sdim intptr_t SizeInBytes; 95296417Sdim}; 96296417Sdim 97296417SdimArrayRef<const uint8_t> User::getDescriptor() const { 98296417Sdim auto MutableARef = const_cast<User *>(this)->getDescriptor(); 99296417Sdim return {MutableARef.begin(), MutableARef.end()}; 100296417Sdim} 101296417Sdim 102296417SdimMutableArrayRef<uint8_t> User::getDescriptor() { 103296417Sdim assert(HasDescriptor && "Don't call otherwise!"); 104296417Sdim assert(!HasHungOffUses && "Invariant!"); 105296417Sdim 106296417Sdim auto *DI = reinterpret_cast<DescriptorInfo *>(getIntrusiveOperands()) - 1; 107296417Sdim assert(DI->SizeInBytes != 0 && "Should not have had a descriptor otherwise!"); 108296417Sdim 109296417Sdim return MutableArrayRef<uint8_t>( 110296417Sdim reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes, DI->SizeInBytes); 111296417Sdim} 112296417Sdim 113249259Sdim//===----------------------------------------------------------------------===// 114249259Sdim// User operator new Implementations 115249259Sdim//===----------------------------------------------------------------------===// 116249259Sdim 117296417Sdimvoid *User::allocateFixedOperandUser(size_t Size, unsigned Us, 118296417Sdim unsigned DescBytes) { 119288943Sdim assert(Us < (1u << NumUserOperandsBits) && "Too many operands"); 120296417Sdim 121296417Sdim static_assert(sizeof(DescriptorInfo) % sizeof(void *) == 0, "Required below"); 122296417Sdim 123296417Sdim unsigned DescBytesToAllocate = 124296417Sdim DescBytes == 0 ? 0 : (DescBytes + sizeof(DescriptorInfo)); 125296417Sdim assert(DescBytesToAllocate % sizeof(void *) == 0 && 126296417Sdim "We need this to satisfy alignment constraints for Uses"); 127296417Sdim 128296417Sdim uint8_t *Storage = static_cast<uint8_t *>( 129296417Sdim ::operator new(Size + sizeof(Use) * Us + DescBytesToAllocate)); 130296417Sdim Use *Start = reinterpret_cast<Use *>(Storage + DescBytesToAllocate); 131249259Sdim Use *End = Start + Us; 132249259Sdim User *Obj = reinterpret_cast<User*>(End); 133288943Sdim Obj->NumUserOperands = Us; 134288943Sdim Obj->HasHungOffUses = false; 135296417Sdim Obj->HasDescriptor = DescBytes != 0; 136249259Sdim Use::initTags(Start, End); 137296417Sdim 138296417Sdim if (DescBytes != 0) { 139296417Sdim auto *DescInfo = reinterpret_cast<DescriptorInfo *>(Storage + DescBytes); 140296417Sdim DescInfo->SizeInBytes = DescBytes; 141296417Sdim } 142296417Sdim 143249259Sdim return Obj; 144249259Sdim} 145249259Sdim 146296417Sdimvoid *User::operator new(size_t Size, unsigned Us) { 147296417Sdim return allocateFixedOperandUser(Size, Us, 0); 148296417Sdim} 149296417Sdim 150296417Sdimvoid *User::operator new(size_t Size, unsigned Us, unsigned DescBytes) { 151296417Sdim return allocateFixedOperandUser(Size, Us, DescBytes); 152296417Sdim} 153296417Sdim 154288943Sdimvoid *User::operator new(size_t Size) { 155288943Sdim // Allocate space for a single Use* 156288943Sdim void *Storage = ::operator new(Size + sizeof(Use *)); 157288943Sdim Use **HungOffOperandList = static_cast<Use **>(Storage); 158288943Sdim User *Obj = reinterpret_cast<User *>(HungOffOperandList + 1); 159288943Sdim Obj->NumUserOperands = 0; 160288943Sdim Obj->HasHungOffUses = true; 161296417Sdim Obj->HasDescriptor = false; 162288943Sdim *HungOffOperandList = nullptr; 163288943Sdim return Obj; 164288943Sdim} 165288943Sdim 166249259Sdim//===----------------------------------------------------------------------===// 167249259Sdim// User operator delete Implementation 168249259Sdim//===----------------------------------------------------------------------===// 169249259Sdim 170249259Sdimvoid User::operator delete(void *Usr) { 171288943Sdim // Hung off uses use a single Use* before the User, while other subclasses 172288943Sdim // use a Use[] allocated prior to the user. 173288943Sdim User *Obj = static_cast<User *>(Usr); 174288943Sdim if (Obj->HasHungOffUses) { 175296417Sdim assert(!Obj->HasDescriptor && "not supported!"); 176296417Sdim 177288943Sdim Use **HungOffOperandList = static_cast<Use **>(Usr) - 1; 178288943Sdim // drop the hung off uses. 179288943Sdim Use::zap(*HungOffOperandList, *HungOffOperandList + Obj->NumUserOperands, 180288943Sdim /* Delete */ true); 181288943Sdim ::operator delete(HungOffOperandList); 182296417Sdim } else if (Obj->HasDescriptor) { 183296417Sdim Use *UseBegin = static_cast<Use *>(Usr) - Obj->NumUserOperands; 184296417Sdim Use::zap(UseBegin, UseBegin + Obj->NumUserOperands, /* Delete */ false); 185296417Sdim 186296417Sdim auto *DI = reinterpret_cast<DescriptorInfo *>(UseBegin) - 1; 187296417Sdim uint8_t *Storage = reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes; 188296417Sdim ::operator delete(Storage); 189288943Sdim } else { 190288943Sdim Use *Storage = static_cast<Use *>(Usr) - Obj->NumUserOperands; 191288943Sdim Use::zap(Storage, Storage + Obj->NumUserOperands, 192288943Sdim /* Delete */ false); 193288943Sdim ::operator delete(Storage); 194288943Sdim } 195249259Sdim} 196249259Sdim 197249259Sdim//===----------------------------------------------------------------------===// 198249259Sdim// Operator Class 199249259Sdim//===----------------------------------------------------------------------===// 200249259Sdim 201249259SdimOperator::~Operator() { 202249259Sdim llvm_unreachable("should never destroy an Operator"); 203249259Sdim} 204249259Sdim 205249259Sdim} // End llvm namespace 206