diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Bitcode/Reader/ValueList.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Bitcode/Reader/ValueList.cpp | 195 |
1 files changed, 33 insertions, 162 deletions
diff --git a/contrib/llvm-project/llvm/lib/Bitcode/Reader/ValueList.cpp b/contrib/llvm-project/llvm/lib/Bitcode/Reader/ValueList.cpp index 86ed664070f6..b9dbf904c89e 100644 --- a/contrib/llvm-project/llvm/lib/Bitcode/Reader/ValueList.cpp +++ b/contrib/llvm-project/llvm/lib/Bitcode/Reader/ValueList.cpp @@ -17,80 +17,44 @@ #include "llvm/IR/User.h" #include "llvm/IR/Value.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" -#include <algorithm> #include <cstddef> -#include <limits> using namespace llvm; -namespace llvm { - -namespace { - -/// A class for maintaining the slot number definition -/// as a placeholder for the actual definition for forward constants defs. -class ConstantPlaceHolder : public ConstantExpr { -public: - explicit ConstantPlaceHolder(Type *Ty, LLVMContext &Context) - : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) { - Op<0>() = UndefValue::get(Type::getInt32Ty(Context)); - } - - ConstantPlaceHolder &operator=(const ConstantPlaceHolder &) = delete; - - // allocate space for exactly one operand - void *operator new(size_t s) { return User::operator new(s, 1); } - - /// Methods to support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Value *V) { - return isa<ConstantExpr>(V) && - cast<ConstantExpr>(V)->getOpcode() == Instruction::UserOp1; - } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); -}; - -} // end anonymous namespace - -// FIXME: can we inherit this from ConstantExpr? -template <> -struct OperandTraits<ConstantPlaceHolder> - : public FixedNumOperandTraits<ConstantPlaceHolder, 1> {}; -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantPlaceHolder, Value) - -} // end namespace llvm - -void BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) { +Error BitcodeReaderValueList::assignValue(unsigned Idx, Value *V, + unsigned TypeID) { if (Idx == size()) { - push_back(V); - return; + push_back(V, TypeID); + return Error::success(); } if (Idx >= size()) resize(Idx + 1); - WeakTrackingVH &OldV = ValuePtrs[Idx]; - if (!OldV) { - OldV = V; - return; + auto &Old = ValuePtrs[Idx]; + if (!Old.first) { + Old.first = V; + Old.second = TypeID; + return Error::success(); } - // Handle constants and non-constants (e.g. instrs) differently for - // efficiency. - if (Constant *PHC = dyn_cast<Constant>(&*OldV)) { - ResolveConstants.push_back(std::make_pair(PHC, Idx)); - OldV = V; - } else { - // If there was a forward reference to this value, replace it. - Value *PrevVal = OldV; - OldV->replaceAllUsesWith(V); - PrevVal->deleteValue(); - } + assert(!isa<Constant>(&*Old.first) && "Shouldn't update constant"); + // If there was a forward reference to this value, replace it. + Value *PrevVal = Old.first; + if (PrevVal->getType() != V->getType()) + return createStringError( + std::errc::illegal_byte_sequence, + "Assigned value does not match type of forward declaration"); + Old.first->replaceAllUsesWith(V); + PrevVal->deleteValue(); + return Error::success(); } -Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx, Type *Ty) { +Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty, + unsigned TyID, + BasicBlock *ConstExprInsertBB) { // Bail out for a clearly invalid value. if (Idx >= RefsUpperBound) return nullptr; @@ -98,31 +62,18 @@ Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx, Type *Ty) { if (Idx >= size()) resize(Idx + 1); - if (Value *V = ValuePtrs[Idx]) { - if (Ty != V->getType()) - report_fatal_error("Type mismatch in constant table!"); - return cast<Constant>(V); - } - - // Create and return a placeholder, which will later be RAUW'd. - Constant *C = new ConstantPlaceHolder(Ty, Context); - ValuePtrs[Idx] = C; - return C; -} - -Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) { - // Bail out for a clearly invalid value. - if (Idx >= RefsUpperBound) - return nullptr; - - if (Idx >= size()) - resize(Idx + 1); - - if (Value *V = ValuePtrs[Idx]) { + if (Value *V = ValuePtrs[Idx].first) { // If the types don't match, it's invalid. if (Ty && Ty != V->getType()) return nullptr; - return V; + + Expected<Value *> MaybeV = MaterializeValueFn(Idx, ConstExprInsertBB); + if (!MaybeV) { + // TODO: We might want to propagate the precise error message here. + consumeError(MaybeV.takeError()); + return nullptr; + } + return MaybeV.get(); } // No type specified, must be invalid reference. @@ -131,86 +82,6 @@ Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) { // Create and return a placeholder, which will later be RAUW'd. Value *V = new Argument(Ty); - ValuePtrs[Idx] = V; + ValuePtrs[Idx] = {V, TyID}; return V; } - -/// Once all constants are read, this method bulk resolves any forward -/// references. The idea behind this is that we sometimes get constants (such -/// as large arrays) which reference *many* forward ref constants. Replacing -/// each of these causes a lot of thrashing when building/reuniquing the -/// constant. Instead of doing this, we look at all the uses and rewrite all -/// the place holders at once for any constant that uses a placeholder. -void BitcodeReaderValueList::resolveConstantForwardRefs() { - // Sort the values by-pointer so that they are efficient to look up with a - // binary search. - llvm::sort(ResolveConstants); - - SmallVector<Constant *, 64> NewOps; - - while (!ResolveConstants.empty()) { - Value *RealVal = operator[](ResolveConstants.back().second); - Constant *Placeholder = ResolveConstants.back().first; - ResolveConstants.pop_back(); - - // Loop over all users of the placeholder, updating them to reference the - // new value. If they reference more than one placeholder, update them all - // at once. - while (!Placeholder->use_empty()) { - auto UI = Placeholder->user_begin(); - User *U = *UI; - - // If the using object isn't uniqued, just update the operands. This - // handles instructions and initializers for global variables. - if (!isa<Constant>(U) || isa<GlobalValue>(U)) { - UI.getUse().set(RealVal); - continue; - } - - // Otherwise, we have a constant that uses the placeholder. Replace that - // constant with a new constant that has *all* placeholder uses updated. - Constant *UserC = cast<Constant>(U); - for (User::op_iterator I = UserC->op_begin(), E = UserC->op_end(); I != E; - ++I) { - Value *NewOp; - if (!isa<ConstantPlaceHolder>(*I)) { - // Not a placeholder reference. - NewOp = *I; - } else if (*I == Placeholder) { - // Common case is that it just references this one placeholder. - NewOp = RealVal; - } else { - // Otherwise, look up the placeholder in ResolveConstants. - ResolveConstantsTy::iterator It = llvm::lower_bound( - ResolveConstants, - std::pair<Constant *, unsigned>(cast<Constant>(*I), 0)); - assert(It != ResolveConstants.end() && It->first == *I); - NewOp = operator[](It->second); - } - - NewOps.push_back(cast<Constant>(NewOp)); - } - - // Make the new constant. - Constant *NewC; - if (ConstantArray *UserCA = dyn_cast<ConstantArray>(UserC)) { - NewC = ConstantArray::get(UserCA->getType(), NewOps); - } else if (ConstantStruct *UserCS = dyn_cast<ConstantStruct>(UserC)) { - NewC = ConstantStruct::get(UserCS->getType(), NewOps); - } else if (isa<ConstantVector>(UserC)) { - NewC = ConstantVector::get(NewOps); - } else { - assert(isa<ConstantExpr>(UserC) && "Must be a ConstantExpr."); - NewC = cast<ConstantExpr>(UserC)->getWithOperands(NewOps); - } - - UserC->replaceAllUsesWith(NewC); - UserC->destroyConstant(); - NewOps.clear(); - } - - // Update all ValueHandles, they should be the only users at this point. - Placeholder->replaceAllUsesWith(RealVal); - delete cast<ConstantPlaceHolder>(Placeholder); - } -} |