10b57cec5SDimitry Andric //===-- User.cpp - Implement the User class -------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/IR/User.h" 100b57cec5SDimitry Andric #include "llvm/IR/Constant.h" 110b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h" 125ffd83dbSDimitry Andric #include "llvm/IR/IntrinsicInst.h" 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric namespace llvm { 150b57cec5SDimitry Andric class BasicBlock; 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 180b57cec5SDimitry Andric // User Class 190b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric void User::replaceUsesOfWith(Value *From, Value *To) { 220b57cec5SDimitry Andric if (From == To) return; // Duh what? 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric assert((!isa<Constant>(this) || isa<GlobalValue>(this)) && 250b57cec5SDimitry Andric "Cannot call User::replaceUsesOfWith on a constant!"); 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric for (unsigned i = 0, E = getNumOperands(); i != E; ++i) 280b57cec5SDimitry Andric if (getOperand(i) == From) { // Is This operand is pointing to oldval? 290b57cec5SDimitry Andric // The side effects of this setOperand call include linking to 300b57cec5SDimitry Andric // "To", adding "this" to the uses list of To, and 310b57cec5SDimitry Andric // most importantly, removing "this" from the use list of "From". 32e8d8bef9SDimitry Andric setOperand(i, To); 330b57cec5SDimitry Andric } 34fe6060f1SDimitry Andric if (auto DVI = dyn_cast_or_null<DbgVariableIntrinsic>(this)) { 35fe6060f1SDimitry Andric if (is_contained(DVI->location_ops(), From)) 36fe6060f1SDimitry Andric DVI->replaceVariableLocationOp(From, To); 37fe6060f1SDimitry Andric } 380b57cec5SDimitry Andric } 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 410b57cec5SDimitry Andric // User allocHungoffUses Implementation 420b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric void User::allocHungoffUses(unsigned N, bool IsPhi) { 450b57cec5SDimitry Andric assert(HasHungOffUses && "alloc must have hung off uses"); 460b57cec5SDimitry Andric 475ffd83dbSDimitry Andric static_assert(alignof(Use) >= alignof(BasicBlock *), 480b57cec5SDimitry Andric "Alignment is insufficient for 'hung-off-uses' pieces"); 490b57cec5SDimitry Andric 505ffd83dbSDimitry Andric // Allocate the array of Uses 515ffd83dbSDimitry Andric size_t size = N * sizeof(Use); 520b57cec5SDimitry Andric if (IsPhi) 530b57cec5SDimitry Andric size += N * sizeof(BasicBlock *); 540b57cec5SDimitry Andric Use *Begin = static_cast<Use*>(::operator new(size)); 550b57cec5SDimitry Andric Use *End = Begin + N; 565ffd83dbSDimitry Andric setOperandList(Begin); 575ffd83dbSDimitry Andric for (; Begin != End; Begin++) 585ffd83dbSDimitry Andric new (Begin) Use(this); 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric void User::growHungoffUses(unsigned NewNumUses, bool IsPhi) { 620b57cec5SDimitry Andric assert(HasHungOffUses && "realloc must have hung off uses"); 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric unsigned OldNumUses = getNumOperands(); 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric // We don't support shrinking the number of uses. We wouldn't have enough 670b57cec5SDimitry Andric // space to copy the old uses in to the new space. 680b57cec5SDimitry Andric assert(NewNumUses > OldNumUses && "realloc must grow num uses"); 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric Use *OldOps = getOperandList(); 710b57cec5SDimitry Andric allocHungoffUses(NewNumUses, IsPhi); 720b57cec5SDimitry Andric Use *NewOps = getOperandList(); 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric // Now copy from the old operands list to the new one. 750b57cec5SDimitry Andric std::copy(OldOps, OldOps + OldNumUses, NewOps); 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric // If this is a Phi, then we need to copy the BB pointers too. 780b57cec5SDimitry Andric if (IsPhi) { 795ffd83dbSDimitry Andric auto *OldPtr = reinterpret_cast<char *>(OldOps + OldNumUses); 805ffd83dbSDimitry Andric auto *NewPtr = reinterpret_cast<char *>(NewOps + NewNumUses); 810b57cec5SDimitry Andric std::copy(OldPtr, OldPtr + (OldNumUses * sizeof(BasicBlock *)), NewPtr); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric Use::zap(OldOps, OldOps + OldNumUses, true); 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric // This is a private struct used by `User` to track the co-allocated descriptor 880b57cec5SDimitry Andric // section. 890b57cec5SDimitry Andric struct DescriptorInfo { 900b57cec5SDimitry Andric intptr_t SizeInBytes; 910b57cec5SDimitry Andric }; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric ArrayRef<const uint8_t> User::getDescriptor() const { 940b57cec5SDimitry Andric auto MutableARef = const_cast<User *>(this)->getDescriptor(); 950b57cec5SDimitry Andric return {MutableARef.begin(), MutableARef.end()}; 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric MutableArrayRef<uint8_t> User::getDescriptor() { 990b57cec5SDimitry Andric assert(HasDescriptor && "Don't call otherwise!"); 1000b57cec5SDimitry Andric assert(!HasHungOffUses && "Invariant!"); 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric auto *DI = reinterpret_cast<DescriptorInfo *>(getIntrusiveOperands()) - 1; 1030b57cec5SDimitry Andric assert(DI->SizeInBytes != 0 && "Should not have had a descriptor otherwise!"); 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric return MutableArrayRef<uint8_t>( 1060b57cec5SDimitry Andric reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes, DI->SizeInBytes); 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric 1095ffd83dbSDimitry Andric bool User::isDroppable() const { 110*349cc55cSDimitry Andric return isa<AssumeInst>(this) || isa<PseudoProbeInst>(this); 1115ffd83dbSDimitry Andric } 1125ffd83dbSDimitry Andric 1130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1140b57cec5SDimitry Andric // User operator new Implementations 1150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric void *User::allocateFixedOperandUser(size_t Size, unsigned Us, 1180b57cec5SDimitry Andric unsigned DescBytes) { 1190b57cec5SDimitry Andric assert(Us < (1u << NumUserOperandsBits) && "Too many operands"); 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric static_assert(sizeof(DescriptorInfo) % sizeof(void *) == 0, "Required below"); 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric unsigned DescBytesToAllocate = 1240b57cec5SDimitry Andric DescBytes == 0 ? 0 : (DescBytes + sizeof(DescriptorInfo)); 1250b57cec5SDimitry Andric assert(DescBytesToAllocate % sizeof(void *) == 0 && 1260b57cec5SDimitry Andric "We need this to satisfy alignment constraints for Uses"); 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric uint8_t *Storage = static_cast<uint8_t *>( 1290b57cec5SDimitry Andric ::operator new(Size + sizeof(Use) * Us + DescBytesToAllocate)); 1300b57cec5SDimitry Andric Use *Start = reinterpret_cast<Use *>(Storage + DescBytesToAllocate); 1310b57cec5SDimitry Andric Use *End = Start + Us; 1320b57cec5SDimitry Andric User *Obj = reinterpret_cast<User*>(End); 1330b57cec5SDimitry Andric Obj->NumUserOperands = Us; 1340b57cec5SDimitry Andric Obj->HasHungOffUses = false; 1350b57cec5SDimitry Andric Obj->HasDescriptor = DescBytes != 0; 1365ffd83dbSDimitry Andric for (; Start != End; Start++) 1375ffd83dbSDimitry Andric new (Start) Use(Obj); 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric if (DescBytes != 0) { 1400b57cec5SDimitry Andric auto *DescInfo = reinterpret_cast<DescriptorInfo *>(Storage + DescBytes); 1410b57cec5SDimitry Andric DescInfo->SizeInBytes = DescBytes; 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric return Obj; 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric void *User::operator new(size_t Size, unsigned Us) { 1480b57cec5SDimitry Andric return allocateFixedOperandUser(Size, Us, 0); 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric void *User::operator new(size_t Size, unsigned Us, unsigned DescBytes) { 1520b57cec5SDimitry Andric return allocateFixedOperandUser(Size, Us, DescBytes); 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric void *User::operator new(size_t Size) { 1560b57cec5SDimitry Andric // Allocate space for a single Use* 1570b57cec5SDimitry Andric void *Storage = ::operator new(Size + sizeof(Use *)); 1580b57cec5SDimitry Andric Use **HungOffOperandList = static_cast<Use **>(Storage); 1590b57cec5SDimitry Andric User *Obj = reinterpret_cast<User *>(HungOffOperandList + 1); 1600b57cec5SDimitry Andric Obj->NumUserOperands = 0; 1610b57cec5SDimitry Andric Obj->HasHungOffUses = true; 1620b57cec5SDimitry Andric Obj->HasDescriptor = false; 1630b57cec5SDimitry Andric *HungOffOperandList = nullptr; 1640b57cec5SDimitry Andric return Obj; 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1680b57cec5SDimitry Andric // User operator delete Implementation 1690b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1700b57cec5SDimitry Andric 171480093f4SDimitry Andric // Repress memory sanitization, due to use-after-destroy by operator 172480093f4SDimitry Andric // delete. Bug report 24578 identifies this issue. 173480093f4SDimitry Andric LLVM_NO_SANITIZE_MEMORY_ATTRIBUTE void User::operator delete(void *Usr) { 1740b57cec5SDimitry Andric // Hung off uses use a single Use* before the User, while other subclasses 1750b57cec5SDimitry Andric // use a Use[] allocated prior to the user. 1760b57cec5SDimitry Andric User *Obj = static_cast<User *>(Usr); 1770b57cec5SDimitry Andric if (Obj->HasHungOffUses) { 1780b57cec5SDimitry Andric assert(!Obj->HasDescriptor && "not supported!"); 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric Use **HungOffOperandList = static_cast<Use **>(Usr) - 1; 1810b57cec5SDimitry Andric // drop the hung off uses. 1820b57cec5SDimitry Andric Use::zap(*HungOffOperandList, *HungOffOperandList + Obj->NumUserOperands, 1830b57cec5SDimitry Andric /* Delete */ true); 1840b57cec5SDimitry Andric ::operator delete(HungOffOperandList); 1850b57cec5SDimitry Andric } else if (Obj->HasDescriptor) { 1860b57cec5SDimitry Andric Use *UseBegin = static_cast<Use *>(Usr) - Obj->NumUserOperands; 1870b57cec5SDimitry Andric Use::zap(UseBegin, UseBegin + Obj->NumUserOperands, /* Delete */ false); 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric auto *DI = reinterpret_cast<DescriptorInfo *>(UseBegin) - 1; 1900b57cec5SDimitry Andric uint8_t *Storage = reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes; 1910b57cec5SDimitry Andric ::operator delete(Storage); 1920b57cec5SDimitry Andric } else { 1930b57cec5SDimitry Andric Use *Storage = static_cast<Use *>(Usr) - Obj->NumUserOperands; 1940b57cec5SDimitry Andric Use::zap(Storage, Storage + Obj->NumUserOperands, 1950b57cec5SDimitry Andric /* Delete */ false); 1960b57cec5SDimitry Andric ::operator delete(Storage); 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 2005ffd83dbSDimitry Andric } // namespace llvm 201