10b57cec5SDimitry Andric //===- ValueList.cpp - Internal BitcodeReader implementation --------------===//
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 "ValueList.h"
100b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
110b57cec5SDimitry Andric #include "llvm/IR/Argument.h"
120b57cec5SDimitry Andric #include "llvm/IR/Constant.h"
130b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
140b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
150b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
160b57cec5SDimitry Andric #include "llvm/IR/Type.h"
170b57cec5SDimitry Andric #include "llvm/IR/User.h"
180b57cec5SDimitry Andric #include "llvm/IR/Value.h"
190b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
200b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
210b57cec5SDimitry Andric #include <algorithm>
220b57cec5SDimitry Andric #include <cstddef>
230b57cec5SDimitry Andric #include <limits>
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric namespace llvm {
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric namespace {
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric /// A class for maintaining the slot number definition
320b57cec5SDimitry Andric /// as a placeholder for the actual definition for forward constants defs.
330b57cec5SDimitry Andric class ConstantPlaceHolder : public ConstantExpr {
340b57cec5SDimitry Andric public:
ConstantPlaceHolder(Type * Ty,LLVMContext & Context)350b57cec5SDimitry Andric explicit ConstantPlaceHolder(Type *Ty, LLVMContext &Context)
360b57cec5SDimitry Andric : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) {
370b57cec5SDimitry Andric Op<0>() = UndefValue::get(Type::getInt32Ty(Context));
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric ConstantPlaceHolder &operator=(const ConstantPlaceHolder &) = delete;
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric // allocate space for exactly one operand
operator new(size_t s)430b57cec5SDimitry Andric void *operator new(size_t s) { return User::operator new(s, 1); }
440b57cec5SDimitry Andric
450b57cec5SDimitry Andric /// Methods to support type inquiry through isa, cast, and dyn_cast.
classof(const Value * V)460b57cec5SDimitry Andric static bool classof(const Value *V) {
470b57cec5SDimitry Andric return isa<ConstantExpr>(V) &&
480b57cec5SDimitry Andric cast<ConstantExpr>(V)->getOpcode() == Instruction::UserOp1;
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric
510b57cec5SDimitry Andric /// Provide fast operand accessors
520b57cec5SDimitry Andric DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
530b57cec5SDimitry Andric };
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric } // end anonymous namespace
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric // FIXME: can we inherit this from ConstantExpr?
580b57cec5SDimitry Andric template <>
590b57cec5SDimitry Andric struct OperandTraits<ConstantPlaceHolder>
600b57cec5SDimitry Andric : public FixedNumOperandTraits<ConstantPlaceHolder, 1> {};
610b57cec5SDimitry Andric DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantPlaceHolder, Value)
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric } // end namespace llvm
640b57cec5SDimitry Andric
assignValue(Value * V,unsigned Idx)65*5f7ddb14SDimitry Andric void BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) {
660b57cec5SDimitry Andric if (Idx == size()) {
67*5f7ddb14SDimitry Andric push_back(V);
680b57cec5SDimitry Andric return;
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric if (Idx >= size())
720b57cec5SDimitry Andric resize(Idx + 1);
730b57cec5SDimitry Andric
740b57cec5SDimitry Andric WeakTrackingVH &OldV = ValuePtrs[Idx];
750b57cec5SDimitry Andric if (!OldV) {
760b57cec5SDimitry Andric OldV = V;
770b57cec5SDimitry Andric return;
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric // Handle constants and non-constants (e.g. instrs) differently for
810b57cec5SDimitry Andric // efficiency.
820b57cec5SDimitry Andric if (Constant *PHC = dyn_cast<Constant>(&*OldV)) {
830b57cec5SDimitry Andric ResolveConstants.push_back(std::make_pair(PHC, Idx));
840b57cec5SDimitry Andric OldV = V;
850b57cec5SDimitry Andric } else {
860b57cec5SDimitry Andric // If there was a forward reference to this value, replace it.
870b57cec5SDimitry Andric Value *PrevVal = OldV;
880b57cec5SDimitry Andric OldV->replaceAllUsesWith(V);
890b57cec5SDimitry Andric PrevVal->deleteValue();
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric
getConstantFwdRef(unsigned Idx,Type * Ty)930b57cec5SDimitry Andric Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx, Type *Ty) {
940b57cec5SDimitry Andric // Bail out for a clearly invalid value.
950b57cec5SDimitry Andric if (Idx >= RefsUpperBound)
960b57cec5SDimitry Andric return nullptr;
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric if (Idx >= size())
990b57cec5SDimitry Andric resize(Idx + 1);
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric if (Value *V = ValuePtrs[Idx]) {
1020b57cec5SDimitry Andric if (Ty != V->getType())
1030b57cec5SDimitry Andric report_fatal_error("Type mismatch in constant table!");
1040b57cec5SDimitry Andric return cast<Constant>(V);
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric
1070b57cec5SDimitry Andric // Create and return a placeholder, which will later be RAUW'd.
1080b57cec5SDimitry Andric Constant *C = new ConstantPlaceHolder(Ty, Context);
1090b57cec5SDimitry Andric ValuePtrs[Idx] = C;
1100b57cec5SDimitry Andric return C;
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric
getValueFwdRef(unsigned Idx,Type * Ty)113*5f7ddb14SDimitry Andric Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) {
1140b57cec5SDimitry Andric // Bail out for a clearly invalid value.
1150b57cec5SDimitry Andric if (Idx >= RefsUpperBound)
1160b57cec5SDimitry Andric return nullptr;
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andric if (Idx >= size())
1190b57cec5SDimitry Andric resize(Idx + 1);
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric if (Value *V = ValuePtrs[Idx]) {
1220b57cec5SDimitry Andric // If the types don't match, it's invalid.
1230b57cec5SDimitry Andric if (Ty && Ty != V->getType())
1240b57cec5SDimitry Andric return nullptr;
1250b57cec5SDimitry Andric return V;
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric
1280b57cec5SDimitry Andric // No type specified, must be invalid reference.
1290b57cec5SDimitry Andric if (!Ty)
1300b57cec5SDimitry Andric return nullptr;
1310b57cec5SDimitry Andric
1320b57cec5SDimitry Andric // Create and return a placeholder, which will later be RAUW'd.
1330b57cec5SDimitry Andric Value *V = new Argument(Ty);
1340b57cec5SDimitry Andric ValuePtrs[Idx] = V;
1350b57cec5SDimitry Andric return V;
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric
1380b57cec5SDimitry Andric /// Once all constants are read, this method bulk resolves any forward
1390b57cec5SDimitry Andric /// references. The idea behind this is that we sometimes get constants (such
1400b57cec5SDimitry Andric /// as large arrays) which reference *many* forward ref constants. Replacing
1410b57cec5SDimitry Andric /// each of these causes a lot of thrashing when building/reuniquing the
1420b57cec5SDimitry Andric /// constant. Instead of doing this, we look at all the uses and rewrite all
1430b57cec5SDimitry Andric /// the place holders at once for any constant that uses a placeholder.
resolveConstantForwardRefs()1440b57cec5SDimitry Andric void BitcodeReaderValueList::resolveConstantForwardRefs() {
1450b57cec5SDimitry Andric // Sort the values by-pointer so that they are efficient to look up with a
1460b57cec5SDimitry Andric // binary search.
1470b57cec5SDimitry Andric llvm::sort(ResolveConstants);
1480b57cec5SDimitry Andric
1490b57cec5SDimitry Andric SmallVector<Constant *, 64> NewOps;
1500b57cec5SDimitry Andric
1510b57cec5SDimitry Andric while (!ResolveConstants.empty()) {
1520b57cec5SDimitry Andric Value *RealVal = operator[](ResolveConstants.back().second);
1530b57cec5SDimitry Andric Constant *Placeholder = ResolveConstants.back().first;
1540b57cec5SDimitry Andric ResolveConstants.pop_back();
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andric // Loop over all users of the placeholder, updating them to reference the
1570b57cec5SDimitry Andric // new value. If they reference more than one placeholder, update them all
1580b57cec5SDimitry Andric // at once.
1590b57cec5SDimitry Andric while (!Placeholder->use_empty()) {
1600b57cec5SDimitry Andric auto UI = Placeholder->user_begin();
1610b57cec5SDimitry Andric User *U = *UI;
1620b57cec5SDimitry Andric
1630b57cec5SDimitry Andric // If the using object isn't uniqued, just update the operands. This
1640b57cec5SDimitry Andric // handles instructions and initializers for global variables.
1650b57cec5SDimitry Andric if (!isa<Constant>(U) || isa<GlobalValue>(U)) {
1660b57cec5SDimitry Andric UI.getUse().set(RealVal);
1670b57cec5SDimitry Andric continue;
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric
1700b57cec5SDimitry Andric // Otherwise, we have a constant that uses the placeholder. Replace that
1710b57cec5SDimitry Andric // constant with a new constant that has *all* placeholder uses updated.
1720b57cec5SDimitry Andric Constant *UserC = cast<Constant>(U);
1730b57cec5SDimitry Andric for (User::op_iterator I = UserC->op_begin(), E = UserC->op_end(); I != E;
1740b57cec5SDimitry Andric ++I) {
1750b57cec5SDimitry Andric Value *NewOp;
1760b57cec5SDimitry Andric if (!isa<ConstantPlaceHolder>(*I)) {
1770b57cec5SDimitry Andric // Not a placeholder reference.
1780b57cec5SDimitry Andric NewOp = *I;
1790b57cec5SDimitry Andric } else if (*I == Placeholder) {
1800b57cec5SDimitry Andric // Common case is that it just references this one placeholder.
1810b57cec5SDimitry Andric NewOp = RealVal;
1820b57cec5SDimitry Andric } else {
1830b57cec5SDimitry Andric // Otherwise, look up the placeholder in ResolveConstants.
1840b57cec5SDimitry Andric ResolveConstantsTy::iterator It = llvm::lower_bound(
1850b57cec5SDimitry Andric ResolveConstants,
1860b57cec5SDimitry Andric std::pair<Constant *, unsigned>(cast<Constant>(*I), 0));
1870b57cec5SDimitry Andric assert(It != ResolveConstants.end() && It->first == *I);
1880b57cec5SDimitry Andric NewOp = operator[](It->second);
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric
1910b57cec5SDimitry Andric NewOps.push_back(cast<Constant>(NewOp));
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric
1940b57cec5SDimitry Andric // Make the new constant.
1950b57cec5SDimitry Andric Constant *NewC;
1960b57cec5SDimitry Andric if (ConstantArray *UserCA = dyn_cast<ConstantArray>(UserC)) {
1970b57cec5SDimitry Andric NewC = ConstantArray::get(UserCA->getType(), NewOps);
1980b57cec5SDimitry Andric } else if (ConstantStruct *UserCS = dyn_cast<ConstantStruct>(UserC)) {
1990b57cec5SDimitry Andric NewC = ConstantStruct::get(UserCS->getType(), NewOps);
2000b57cec5SDimitry Andric } else if (isa<ConstantVector>(UserC)) {
2010b57cec5SDimitry Andric NewC = ConstantVector::get(NewOps);
2020b57cec5SDimitry Andric } else {
2030b57cec5SDimitry Andric assert(isa<ConstantExpr>(UserC) && "Must be a ConstantExpr.");
2040b57cec5SDimitry Andric NewC = cast<ConstantExpr>(UserC)->getWithOperands(NewOps);
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric
2070b57cec5SDimitry Andric UserC->replaceAllUsesWith(NewC);
2080b57cec5SDimitry Andric UserC->destroyConstant();
2090b57cec5SDimitry Andric NewOps.clear();
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric
2120b57cec5SDimitry Andric // Update all ValueHandles, they should be the only users at this point.
2130b57cec5SDimitry Andric Placeholder->replaceAllUsesWith(RealVal);
2145ffd83dbSDimitry Andric delete cast<ConstantPlaceHolder>(Placeholder);
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric }
217