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