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
replaceUsesOfWith(Value * From,Value * To)21*81ad6265SDimitry Andric bool User::replaceUsesOfWith(Value *From, Value *To) {
22*81ad6265SDimitry Andric bool Changed = false;
23*81ad6265SDimitry Andric if (From == To) return Changed; // Duh what?
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric assert((!isa<Constant>(this) || isa<GlobalValue>(this)) &&
260b57cec5SDimitry Andric "Cannot call User::replaceUsesOfWith on a constant!");
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric for (unsigned i = 0, E = getNumOperands(); i != E; ++i)
290b57cec5SDimitry Andric if (getOperand(i) == From) { // Is This operand is pointing to oldval?
300b57cec5SDimitry Andric // The side effects of this setOperand call include linking to
310b57cec5SDimitry Andric // "To", adding "this" to the uses list of To, and
320b57cec5SDimitry Andric // most importantly, removing "this" from the use list of "From".
33e8d8bef9SDimitry Andric setOperand(i, To);
34*81ad6265SDimitry Andric Changed = true;
350b57cec5SDimitry Andric }
36fe6060f1SDimitry Andric if (auto DVI = dyn_cast_or_null<DbgVariableIntrinsic>(this)) {
37*81ad6265SDimitry Andric if (is_contained(DVI->location_ops(), From)) {
38fe6060f1SDimitry Andric DVI->replaceVariableLocationOp(From, To);
39*81ad6265SDimitry Andric Changed = true;
40fe6060f1SDimitry Andric }
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric
43*81ad6265SDimitry Andric return Changed;
44*81ad6265SDimitry Andric }
45*81ad6265SDimitry Andric
460b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
470b57cec5SDimitry Andric // User allocHungoffUses Implementation
480b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
490b57cec5SDimitry Andric
allocHungoffUses(unsigned N,bool IsPhi)500b57cec5SDimitry Andric void User::allocHungoffUses(unsigned N, bool IsPhi) {
510b57cec5SDimitry Andric assert(HasHungOffUses && "alloc must have hung off uses");
520b57cec5SDimitry Andric
535ffd83dbSDimitry Andric static_assert(alignof(Use) >= alignof(BasicBlock *),
540b57cec5SDimitry Andric "Alignment is insufficient for 'hung-off-uses' pieces");
550b57cec5SDimitry Andric
565ffd83dbSDimitry Andric // Allocate the array of Uses
575ffd83dbSDimitry Andric size_t size = N * sizeof(Use);
580b57cec5SDimitry Andric if (IsPhi)
590b57cec5SDimitry Andric size += N * sizeof(BasicBlock *);
600b57cec5SDimitry Andric Use *Begin = static_cast<Use*>(::operator new(size));
610b57cec5SDimitry Andric Use *End = Begin + N;
625ffd83dbSDimitry Andric setOperandList(Begin);
635ffd83dbSDimitry Andric for (; Begin != End; Begin++)
645ffd83dbSDimitry Andric new (Begin) Use(this);
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric
growHungoffUses(unsigned NewNumUses,bool IsPhi)670b57cec5SDimitry Andric void User::growHungoffUses(unsigned NewNumUses, bool IsPhi) {
680b57cec5SDimitry Andric assert(HasHungOffUses && "realloc must have hung off uses");
690b57cec5SDimitry Andric
700b57cec5SDimitry Andric unsigned OldNumUses = getNumOperands();
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric // We don't support shrinking the number of uses. We wouldn't have enough
730b57cec5SDimitry Andric // space to copy the old uses in to the new space.
740b57cec5SDimitry Andric assert(NewNumUses > OldNumUses && "realloc must grow num uses");
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric Use *OldOps = getOperandList();
770b57cec5SDimitry Andric allocHungoffUses(NewNumUses, IsPhi);
780b57cec5SDimitry Andric Use *NewOps = getOperandList();
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric // Now copy from the old operands list to the new one.
810b57cec5SDimitry Andric std::copy(OldOps, OldOps + OldNumUses, NewOps);
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric // If this is a Phi, then we need to copy the BB pointers too.
840b57cec5SDimitry Andric if (IsPhi) {
855ffd83dbSDimitry Andric auto *OldPtr = reinterpret_cast<char *>(OldOps + OldNumUses);
865ffd83dbSDimitry Andric auto *NewPtr = reinterpret_cast<char *>(NewOps + NewNumUses);
870b57cec5SDimitry Andric std::copy(OldPtr, OldPtr + (OldNumUses * sizeof(BasicBlock *)), NewPtr);
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric Use::zap(OldOps, OldOps + OldNumUses, true);
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric // This is a private struct used by `User` to track the co-allocated descriptor
940b57cec5SDimitry Andric // section.
950b57cec5SDimitry Andric struct DescriptorInfo {
960b57cec5SDimitry Andric intptr_t SizeInBytes;
970b57cec5SDimitry Andric };
980b57cec5SDimitry Andric
getDescriptor() const990b57cec5SDimitry Andric ArrayRef<const uint8_t> User::getDescriptor() const {
1000b57cec5SDimitry Andric auto MutableARef = const_cast<User *>(this)->getDescriptor();
1010b57cec5SDimitry Andric return {MutableARef.begin(), MutableARef.end()};
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric
getDescriptor()1040b57cec5SDimitry Andric MutableArrayRef<uint8_t> User::getDescriptor() {
1050b57cec5SDimitry Andric assert(HasDescriptor && "Don't call otherwise!");
1060b57cec5SDimitry Andric assert(!HasHungOffUses && "Invariant!");
1070b57cec5SDimitry Andric
1080b57cec5SDimitry Andric auto *DI = reinterpret_cast<DescriptorInfo *>(getIntrusiveOperands()) - 1;
1090b57cec5SDimitry Andric assert(DI->SizeInBytes != 0 && "Should not have had a descriptor otherwise!");
1100b57cec5SDimitry Andric
1110b57cec5SDimitry Andric return MutableArrayRef<uint8_t>(
1120b57cec5SDimitry Andric reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes, DI->SizeInBytes);
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric
isDroppable() const1155ffd83dbSDimitry Andric bool User::isDroppable() const {
116349cc55cSDimitry Andric return isa<AssumeInst>(this) || isa<PseudoProbeInst>(this);
1175ffd83dbSDimitry Andric }
1185ffd83dbSDimitry Andric
1190b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1200b57cec5SDimitry Andric // User operator new Implementations
1210b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1220b57cec5SDimitry Andric
allocateFixedOperandUser(size_t Size,unsigned Us,unsigned DescBytes)1230b57cec5SDimitry Andric void *User::allocateFixedOperandUser(size_t Size, unsigned Us,
1240b57cec5SDimitry Andric unsigned DescBytes) {
1250b57cec5SDimitry Andric assert(Us < (1u << NumUserOperandsBits) && "Too many operands");
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric static_assert(sizeof(DescriptorInfo) % sizeof(void *) == 0, "Required below");
1280b57cec5SDimitry Andric
1290b57cec5SDimitry Andric unsigned DescBytesToAllocate =
1300b57cec5SDimitry Andric DescBytes == 0 ? 0 : (DescBytes + sizeof(DescriptorInfo));
1310b57cec5SDimitry Andric assert(DescBytesToAllocate % sizeof(void *) == 0 &&
1320b57cec5SDimitry Andric "We need this to satisfy alignment constraints for Uses");
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric uint8_t *Storage = static_cast<uint8_t *>(
1350b57cec5SDimitry Andric ::operator new(Size + sizeof(Use) * Us + DescBytesToAllocate));
1360b57cec5SDimitry Andric Use *Start = reinterpret_cast<Use *>(Storage + DescBytesToAllocate);
1370b57cec5SDimitry Andric Use *End = Start + Us;
1380b57cec5SDimitry Andric User *Obj = reinterpret_cast<User*>(End);
1390b57cec5SDimitry Andric Obj->NumUserOperands = Us;
1400b57cec5SDimitry Andric Obj->HasHungOffUses = false;
1410b57cec5SDimitry Andric Obj->HasDescriptor = DescBytes != 0;
1425ffd83dbSDimitry Andric for (; Start != End; Start++)
1435ffd83dbSDimitry Andric new (Start) Use(Obj);
1440b57cec5SDimitry Andric
1450b57cec5SDimitry Andric if (DescBytes != 0) {
1460b57cec5SDimitry Andric auto *DescInfo = reinterpret_cast<DescriptorInfo *>(Storage + DescBytes);
1470b57cec5SDimitry Andric DescInfo->SizeInBytes = DescBytes;
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric
1500b57cec5SDimitry Andric return Obj;
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric
operator new(size_t Size,unsigned Us)1530b57cec5SDimitry Andric void *User::operator new(size_t Size, unsigned Us) {
1540b57cec5SDimitry Andric return allocateFixedOperandUser(Size, Us, 0);
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric
operator new(size_t Size,unsigned Us,unsigned DescBytes)1570b57cec5SDimitry Andric void *User::operator new(size_t Size, unsigned Us, unsigned DescBytes) {
1580b57cec5SDimitry Andric return allocateFixedOperandUser(Size, Us, DescBytes);
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric
operator new(size_t Size)1610b57cec5SDimitry Andric void *User::operator new(size_t Size) {
1620b57cec5SDimitry Andric // Allocate space for a single Use*
1630b57cec5SDimitry Andric void *Storage = ::operator new(Size + sizeof(Use *));
1640b57cec5SDimitry Andric Use **HungOffOperandList = static_cast<Use **>(Storage);
1650b57cec5SDimitry Andric User *Obj = reinterpret_cast<User *>(HungOffOperandList + 1);
1660b57cec5SDimitry Andric Obj->NumUserOperands = 0;
1670b57cec5SDimitry Andric Obj->HasHungOffUses = true;
1680b57cec5SDimitry Andric Obj->HasDescriptor = false;
1690b57cec5SDimitry Andric *HungOffOperandList = nullptr;
1700b57cec5SDimitry Andric return Obj;
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric
1730b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1740b57cec5SDimitry Andric // User operator delete Implementation
1750b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1760b57cec5SDimitry Andric
177480093f4SDimitry Andric // Repress memory sanitization, due to use-after-destroy by operator
178480093f4SDimitry Andric // delete. Bug report 24578 identifies this issue.
operator delete(void * Usr)179480093f4SDimitry Andric LLVM_NO_SANITIZE_MEMORY_ATTRIBUTE void User::operator delete(void *Usr) {
1800b57cec5SDimitry Andric // Hung off uses use a single Use* before the User, while other subclasses
1810b57cec5SDimitry Andric // use a Use[] allocated prior to the user.
1820b57cec5SDimitry Andric User *Obj = static_cast<User *>(Usr);
1830b57cec5SDimitry Andric if (Obj->HasHungOffUses) {
1840b57cec5SDimitry Andric assert(!Obj->HasDescriptor && "not supported!");
1850b57cec5SDimitry Andric
1860b57cec5SDimitry Andric Use **HungOffOperandList = static_cast<Use **>(Usr) - 1;
1870b57cec5SDimitry Andric // drop the hung off uses.
1880b57cec5SDimitry Andric Use::zap(*HungOffOperandList, *HungOffOperandList + Obj->NumUserOperands,
1890b57cec5SDimitry Andric /* Delete */ true);
1900b57cec5SDimitry Andric ::operator delete(HungOffOperandList);
1910b57cec5SDimitry Andric } else if (Obj->HasDescriptor) {
1920b57cec5SDimitry Andric Use *UseBegin = static_cast<Use *>(Usr) - Obj->NumUserOperands;
1930b57cec5SDimitry Andric Use::zap(UseBegin, UseBegin + Obj->NumUserOperands, /* Delete */ false);
1940b57cec5SDimitry Andric
1950b57cec5SDimitry Andric auto *DI = reinterpret_cast<DescriptorInfo *>(UseBegin) - 1;
1960b57cec5SDimitry Andric uint8_t *Storage = reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes;
1970b57cec5SDimitry Andric ::operator delete(Storage);
1980b57cec5SDimitry Andric } else {
1990b57cec5SDimitry Andric Use *Storage = static_cast<Use *>(Usr) - Obj->NumUserOperands;
2000b57cec5SDimitry Andric Use::zap(Storage, Storage + Obj->NumUserOperands,
2010b57cec5SDimitry Andric /* Delete */ false);
2020b57cec5SDimitry Andric ::operator delete(Storage);
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric
2065ffd83dbSDimitry Andric } // namespace llvm
207