12cab237bSDimitry Andric //===- ValueList.cpp - Internal BitcodeReader implementation --------------===//
2d88c1a5aSDimitry Andric //
3d88c1a5aSDimitry Andric // The LLVM Compiler Infrastructure
4d88c1a5aSDimitry Andric //
5d88c1a5aSDimitry Andric // This file is distributed under the University of Illinois Open Source
6d88c1a5aSDimitry Andric // License. See LICENSE.TXT for details.
7d88c1a5aSDimitry Andric //
8d88c1a5aSDimitry Andric //===----------------------------------------------------------------------===//
9d88c1a5aSDimitry Andric
10d88c1a5aSDimitry Andric #include "ValueList.h"
112cab237bSDimitry Andric #include "llvm/ADT/SmallVector.h"
122cab237bSDimitry Andric #include "llvm/IR/Argument.h"
132cab237bSDimitry Andric #include "llvm/IR/Constant.h"
14d88c1a5aSDimitry Andric #include "llvm/IR/Constants.h"
152cab237bSDimitry Andric #include "llvm/IR/GlobalValue.h"
162cab237bSDimitry Andric #include "llvm/IR/Instruction.h"
172cab237bSDimitry Andric #include "llvm/IR/Type.h"
182cab237bSDimitry Andric #include "llvm/IR/User.h"
192cab237bSDimitry Andric #include "llvm/IR/Value.h"
202cab237bSDimitry Andric #include "llvm/IR/ValueHandle.h"
212cab237bSDimitry Andric #include "llvm/Support/Casting.h"
222cab237bSDimitry Andric #include "llvm/Support/ErrorHandling.h"
232cab237bSDimitry Andric #include <algorithm>
242cab237bSDimitry Andric #include <cassert>
252cab237bSDimitry Andric #include <cstddef>
262cab237bSDimitry Andric #include <limits>
272cab237bSDimitry Andric #include <utility>
28d88c1a5aSDimitry Andric
29d88c1a5aSDimitry Andric using namespace llvm;
30d88c1a5aSDimitry Andric
31d88c1a5aSDimitry Andric namespace llvm {
322cab237bSDimitry Andric
33d88c1a5aSDimitry Andric namespace {
34d88c1a5aSDimitry Andric
354ba319b5SDimitry Andric /// A class for maintaining the slot number definition
36d88c1a5aSDimitry Andric /// as a placeholder for the actual definition for forward constants defs.
37d88c1a5aSDimitry Andric class ConstantPlaceHolder : public ConstantExpr {
38d88c1a5aSDimitry Andric public:
ConstantPlaceHolder(Type * Ty,LLVMContext & Context)39d88c1a5aSDimitry Andric explicit ConstantPlaceHolder(Type *Ty, LLVMContext &Context)
40d88c1a5aSDimitry Andric : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) {
41d88c1a5aSDimitry Andric Op<0>() = UndefValue::get(Type::getInt32Ty(Context));
42d88c1a5aSDimitry Andric }
43d88c1a5aSDimitry Andric
442cab237bSDimitry Andric ConstantPlaceHolder &operator=(const ConstantPlaceHolder &) = delete;
452cab237bSDimitry Andric
462cab237bSDimitry Andric // allocate space for exactly one operand
operator new(size_t s)472cab237bSDimitry Andric void *operator new(size_t s) { return User::operator new(s, 1); }
482cab237bSDimitry Andric
494ba319b5SDimitry Andric /// Methods to support type inquiry through isa, cast, and dyn_cast.
classof(const Value * V)50d88c1a5aSDimitry Andric static bool classof(const Value *V) {
51d88c1a5aSDimitry Andric return isa<ConstantExpr>(V) &&
52d88c1a5aSDimitry Andric cast<ConstantExpr>(V)->getOpcode() == Instruction::UserOp1;
53d88c1a5aSDimitry Andric }
54d88c1a5aSDimitry Andric
55d88c1a5aSDimitry Andric /// Provide fast operand accessors
56d88c1a5aSDimitry Andric DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
57d88c1a5aSDimitry Andric };
58d88c1a5aSDimitry Andric
59d88c1a5aSDimitry Andric } // end anonymous namespace
60d88c1a5aSDimitry Andric
61d88c1a5aSDimitry Andric // FIXME: can we inherit this from ConstantExpr?
62d88c1a5aSDimitry Andric template <>
63d88c1a5aSDimitry Andric struct OperandTraits<ConstantPlaceHolder>
64d88c1a5aSDimitry Andric : public FixedNumOperandTraits<ConstantPlaceHolder, 1> {};
65d88c1a5aSDimitry Andric DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantPlaceHolder, Value)
66d88c1a5aSDimitry Andric
67d88c1a5aSDimitry Andric } // end namespace llvm
68d88c1a5aSDimitry Andric
assignValue(Value * V,unsigned Idx)69d88c1a5aSDimitry Andric void BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) {
70d88c1a5aSDimitry Andric if (Idx == size()) {
71d88c1a5aSDimitry Andric push_back(V);
72d88c1a5aSDimitry Andric return;
73d88c1a5aSDimitry Andric }
74d88c1a5aSDimitry Andric
75d88c1a5aSDimitry Andric if (Idx >= size())
76d88c1a5aSDimitry Andric resize(Idx + 1);
77d88c1a5aSDimitry Andric
78f37b6182SDimitry Andric WeakTrackingVH &OldV = ValuePtrs[Idx];
79d88c1a5aSDimitry Andric if (!OldV) {
80d88c1a5aSDimitry Andric OldV = V;
81d88c1a5aSDimitry Andric return;
82d88c1a5aSDimitry Andric }
83d88c1a5aSDimitry Andric
84d88c1a5aSDimitry Andric // Handle constants and non-constants (e.g. instrs) differently for
85d88c1a5aSDimitry Andric // efficiency.
86d88c1a5aSDimitry Andric if (Constant *PHC = dyn_cast<Constant>(&*OldV)) {
87d88c1a5aSDimitry Andric ResolveConstants.push_back(std::make_pair(PHC, Idx));
88d88c1a5aSDimitry Andric OldV = V;
89d88c1a5aSDimitry Andric } else {
90d88c1a5aSDimitry Andric // If there was a forward reference to this value, replace it.
91d88c1a5aSDimitry Andric Value *PrevVal = OldV;
92d88c1a5aSDimitry Andric OldV->replaceAllUsesWith(V);
93d8866befSDimitry Andric PrevVal->deleteValue();
94d88c1a5aSDimitry Andric }
95d88c1a5aSDimitry Andric }
96d88c1a5aSDimitry Andric
getConstantFwdRef(unsigned Idx,Type * Ty)97d88c1a5aSDimitry Andric Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx, Type *Ty) {
98d88c1a5aSDimitry Andric if (Idx >= size())
99d88c1a5aSDimitry Andric resize(Idx + 1);
100d88c1a5aSDimitry Andric
101d88c1a5aSDimitry Andric if (Value *V = ValuePtrs[Idx]) {
102d88c1a5aSDimitry Andric if (Ty != V->getType())
103d88c1a5aSDimitry Andric report_fatal_error("Type mismatch in constant table!");
104d88c1a5aSDimitry Andric return cast<Constant>(V);
105d88c1a5aSDimitry Andric }
106d88c1a5aSDimitry Andric
107d88c1a5aSDimitry Andric // Create and return a placeholder, which will later be RAUW'd.
108d88c1a5aSDimitry Andric Constant *C = new ConstantPlaceHolder(Ty, Context);
109d88c1a5aSDimitry Andric ValuePtrs[Idx] = C;
110d88c1a5aSDimitry Andric return C;
111d88c1a5aSDimitry Andric }
112d88c1a5aSDimitry Andric
getValueFwdRef(unsigned Idx,Type * Ty)113d88c1a5aSDimitry Andric Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) {
114d88c1a5aSDimitry Andric // Bail out for a clearly invalid value. This would make us call resize(0)
115d88c1a5aSDimitry Andric if (Idx == std::numeric_limits<unsigned>::max())
116d88c1a5aSDimitry Andric return nullptr;
117d88c1a5aSDimitry Andric
118d88c1a5aSDimitry Andric if (Idx >= size())
119d88c1a5aSDimitry Andric resize(Idx + 1);
120d88c1a5aSDimitry Andric
121d88c1a5aSDimitry Andric if (Value *V = ValuePtrs[Idx]) {
122d88c1a5aSDimitry Andric // If the types don't match, it's invalid.
123d88c1a5aSDimitry Andric if (Ty && Ty != V->getType())
124d88c1a5aSDimitry Andric return nullptr;
125d88c1a5aSDimitry Andric return V;
126d88c1a5aSDimitry Andric }
127d88c1a5aSDimitry Andric
128d88c1a5aSDimitry Andric // No type specified, must be invalid reference.
129d88c1a5aSDimitry Andric if (!Ty)
130d88c1a5aSDimitry Andric return nullptr;
131d88c1a5aSDimitry Andric
132d88c1a5aSDimitry Andric // Create and return a placeholder, which will later be RAUW'd.
133d88c1a5aSDimitry Andric Value *V = new Argument(Ty);
134d88c1a5aSDimitry Andric ValuePtrs[Idx] = V;
135d88c1a5aSDimitry Andric return V;
136d88c1a5aSDimitry Andric }
137d88c1a5aSDimitry Andric
138d88c1a5aSDimitry Andric /// Once all constants are read, this method bulk resolves any forward
139d88c1a5aSDimitry Andric /// references. The idea behind this is that we sometimes get constants (such
140d88c1a5aSDimitry Andric /// as large arrays) which reference *many* forward ref constants. Replacing
141d88c1a5aSDimitry Andric /// each of these causes a lot of thrashing when building/reuniquing the
142d88c1a5aSDimitry Andric /// constant. Instead of doing this, we look at all the uses and rewrite all
143d88c1a5aSDimitry Andric /// the place holders at once for any constant that uses a placeholder.
resolveConstantForwardRefs()144d88c1a5aSDimitry Andric void BitcodeReaderValueList::resolveConstantForwardRefs() {
145d88c1a5aSDimitry Andric // Sort the values by-pointer so that they are efficient to look up with a
146d88c1a5aSDimitry Andric // binary search.
147*b5893f02SDimitry Andric llvm::sort(ResolveConstants);
148d88c1a5aSDimitry Andric
149d88c1a5aSDimitry Andric SmallVector<Constant *, 64> NewOps;
150d88c1a5aSDimitry Andric
151d88c1a5aSDimitry Andric while (!ResolveConstants.empty()) {
152d88c1a5aSDimitry Andric Value *RealVal = operator[](ResolveConstants.back().second);
153d88c1a5aSDimitry Andric Constant *Placeholder = ResolveConstants.back().first;
154d88c1a5aSDimitry Andric ResolveConstants.pop_back();
155d88c1a5aSDimitry Andric
156d88c1a5aSDimitry Andric // Loop over all users of the placeholder, updating them to reference the
157d88c1a5aSDimitry Andric // new value. If they reference more than one placeholder, update them all
158d88c1a5aSDimitry Andric // at once.
159d88c1a5aSDimitry Andric while (!Placeholder->use_empty()) {
160d88c1a5aSDimitry Andric auto UI = Placeholder->user_begin();
161d88c1a5aSDimitry Andric User *U = *UI;
162d88c1a5aSDimitry Andric
163d88c1a5aSDimitry Andric // If the using object isn't uniqued, just update the operands. This
164d88c1a5aSDimitry Andric // handles instructions and initializers for global variables.
165d88c1a5aSDimitry Andric if (!isa<Constant>(U) || isa<GlobalValue>(U)) {
166d88c1a5aSDimitry Andric UI.getUse().set(RealVal);
167d88c1a5aSDimitry Andric continue;
168d88c1a5aSDimitry Andric }
169d88c1a5aSDimitry Andric
170d88c1a5aSDimitry Andric // Otherwise, we have a constant that uses the placeholder. Replace that
171d88c1a5aSDimitry Andric // constant with a new constant that has *all* placeholder uses updated.
172d88c1a5aSDimitry Andric Constant *UserC = cast<Constant>(U);
173d88c1a5aSDimitry Andric for (User::op_iterator I = UserC->op_begin(), E = UserC->op_end(); I != E;
174d88c1a5aSDimitry Andric ++I) {
175d88c1a5aSDimitry Andric Value *NewOp;
176d88c1a5aSDimitry Andric if (!isa<ConstantPlaceHolder>(*I)) {
177d88c1a5aSDimitry Andric // Not a placeholder reference.
178d88c1a5aSDimitry Andric NewOp = *I;
179d88c1a5aSDimitry Andric } else if (*I == Placeholder) {
180d88c1a5aSDimitry Andric // Common case is that it just references this one placeholder.
181d88c1a5aSDimitry Andric NewOp = RealVal;
182d88c1a5aSDimitry Andric } else {
183d88c1a5aSDimitry Andric // Otherwise, look up the placeholder in ResolveConstants.
184d88c1a5aSDimitry Andric ResolveConstantsTy::iterator It = std::lower_bound(
185d88c1a5aSDimitry Andric ResolveConstants.begin(), ResolveConstants.end(),
186d88c1a5aSDimitry Andric std::pair<Constant *, unsigned>(cast<Constant>(*I), 0));
187d88c1a5aSDimitry Andric assert(It != ResolveConstants.end() && It->first == *I);
188d88c1a5aSDimitry Andric NewOp = operator[](It->second);
189d88c1a5aSDimitry Andric }
190d88c1a5aSDimitry Andric
191d88c1a5aSDimitry Andric NewOps.push_back(cast<Constant>(NewOp));
192d88c1a5aSDimitry Andric }
193d88c1a5aSDimitry Andric
194d88c1a5aSDimitry Andric // Make the new constant.
195d88c1a5aSDimitry Andric Constant *NewC;
196d88c1a5aSDimitry Andric if (ConstantArray *UserCA = dyn_cast<ConstantArray>(UserC)) {
197d88c1a5aSDimitry Andric NewC = ConstantArray::get(UserCA->getType(), NewOps);
198d88c1a5aSDimitry Andric } else if (ConstantStruct *UserCS = dyn_cast<ConstantStruct>(UserC)) {
199d88c1a5aSDimitry Andric NewC = ConstantStruct::get(UserCS->getType(), NewOps);
200d88c1a5aSDimitry Andric } else if (isa<ConstantVector>(UserC)) {
201d88c1a5aSDimitry Andric NewC = ConstantVector::get(NewOps);
202d88c1a5aSDimitry Andric } else {
203d88c1a5aSDimitry Andric assert(isa<ConstantExpr>(UserC) && "Must be a ConstantExpr.");
204d88c1a5aSDimitry Andric NewC = cast<ConstantExpr>(UserC)->getWithOperands(NewOps);
205d88c1a5aSDimitry Andric }
206d88c1a5aSDimitry Andric
207d88c1a5aSDimitry Andric UserC->replaceAllUsesWith(NewC);
208d88c1a5aSDimitry Andric UserC->destroyConstant();
209d88c1a5aSDimitry Andric NewOps.clear();
210d88c1a5aSDimitry Andric }
211d88c1a5aSDimitry Andric
212d88c1a5aSDimitry Andric // Update all ValueHandles, they should be the only users at this point.
213d88c1a5aSDimitry Andric Placeholder->replaceAllUsesWith(RealVal);
214d8866befSDimitry Andric Placeholder->deleteValue();
215d88c1a5aSDimitry Andric }
216d88c1a5aSDimitry Andric }
217