https://github.com/bwendling updated https://github.com/llvm/llvm-project/pull/76882
>From ca7a96a40952fe94b916dacc52f07aa90bbdb1e7 Mon Sep 17 00:00:00 2001 From: Bill Wendling <mo...@google.com> Date: Wed, 3 Jan 2024 13:22:37 -0800 Subject: [PATCH 1/6] [builtin_object_size] Use classes instead of std::pair (NFC) The use of std::pair makes the values it holds opaque. Using classes improves this while keeping the POD aspect of a std::pair. As a nice addition, the "known" functions held inappropriately in the Visitor classes can now properly reside in the value classes. :-) --- llvm/include/llvm/Analysis/MemoryBuiltins.h | 192 +++++++---- llvm/lib/Analysis/MemoryBuiltins.cpp | 314 +++++++++--------- .../Transforms/IPO/AttributorAttributes.cpp | 8 +- .../Instrumentation/AddressSanitizer.cpp | 12 +- .../Instrumentation/BoundsChecking.cpp | 8 +- 5 files changed, 299 insertions(+), 235 deletions(-) diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h index 827b5081b2ce75..56faa32fb0b226 100644 --- a/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -187,80 +187,146 @@ Value *lowerObjectSizeCall( const TargetLibraryInfo *TLI, AAResults *AA, bool MustSucceed, SmallVectorImpl<Instruction *> *InsertedInstructions = nullptr); -using SizeOffsetType = std::pair<APInt, APInt>; +/// SizeOffsetType - A base template class for the object size visitors. Used +/// here as a self-documenting way to handle the values rather than using a +/// \p std::pair. +template <typename T> struct SizeOffsetType { + T Size; + T Offset; + + bool knownSize() const; + bool knownOffset() const; + bool anyKnown() const; + bool bothKnown() const; +}; + +/// SizeOffsetType<APInt> - Used by \p ObjectSizeOffsetVisitor, which works +/// with \p APInts. +template <> struct SizeOffsetType<APInt> { + APInt Size; + APInt Offset; + + SizeOffsetType() = default; + SizeOffsetType(APInt Size, APInt Offset) : Size(Size), Offset(Offset) {} + + bool knownSize() const { return Size.getBitWidth() > 1; } + bool knownOffset() const { return Offset.getBitWidth() > 1; } + bool anyKnown() const { return knownSize() || knownOffset(); } + bool bothKnown() const { return knownSize() && knownOffset(); } + + bool operator==(const SizeOffsetType<APInt> &RHS) { + return Size == RHS.Size && Offset == RHS.Offset; + } + bool operator!=(const SizeOffsetType<APInt> &RHS) { return !(*this == RHS); } +}; +using SizeOffsetAPInt = SizeOffsetType<APInt>; /// Evaluate the size and offset of an object pointed to by a Value* /// statically. Fails if size or offset are not known at compile time. class ObjectSizeOffsetVisitor - : public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> { + : public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetAPInt> { const DataLayout &DL; const TargetLibraryInfo *TLI; ObjectSizeOpts Options; unsigned IntTyBits; APInt Zero; - SmallDenseMap<Instruction *, SizeOffsetType, 8> SeenInsts; + SmallDenseMap<Instruction *, SizeOffsetAPInt, 8> SeenInsts; unsigned InstructionsVisited; APInt align(APInt Size, MaybeAlign Align); - SizeOffsetType unknown() { - return std::make_pair(APInt(), APInt()); - } + static SizeOffsetAPInt unknown; public: ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, ObjectSizeOpts Options = {}); - SizeOffsetType compute(Value *V); - - static bool knownSize(const SizeOffsetType &SizeOffset) { - return SizeOffset.first.getBitWidth() > 1; - } - - static bool knownOffset(const SizeOffsetType &SizeOffset) { - return SizeOffset.second.getBitWidth() > 1; - } - - static bool bothKnown(const SizeOffsetType &SizeOffset) { - return knownSize(SizeOffset) && knownOffset(SizeOffset); - } + SizeOffsetAPInt compute(Value *V); // These are "private", except they can't actually be made private. Only // compute() should be used by external users. - SizeOffsetType visitAllocaInst(AllocaInst &I); - SizeOffsetType visitArgument(Argument &A); - SizeOffsetType visitCallBase(CallBase &CB); - SizeOffsetType visitConstantPointerNull(ConstantPointerNull&); - SizeOffsetType visitExtractElementInst(ExtractElementInst &I); - SizeOffsetType visitExtractValueInst(ExtractValueInst &I); - SizeOffsetType visitGlobalAlias(GlobalAlias &GA); - SizeOffsetType visitGlobalVariable(GlobalVariable &GV); - SizeOffsetType visitIntToPtrInst(IntToPtrInst&); - SizeOffsetType visitLoadInst(LoadInst &I); - SizeOffsetType visitPHINode(PHINode&); - SizeOffsetType visitSelectInst(SelectInst &I); - SizeOffsetType visitUndefValue(UndefValue&); - SizeOffsetType visitInstruction(Instruction &I); + SizeOffsetAPInt visitAllocaInst(AllocaInst &I); + SizeOffsetAPInt visitArgument(Argument &A); + SizeOffsetAPInt visitCallBase(CallBase &CB); + SizeOffsetAPInt visitConstantPointerNull(ConstantPointerNull &); + SizeOffsetAPInt visitExtractElementInst(ExtractElementInst &I); + SizeOffsetAPInt visitExtractValueInst(ExtractValueInst &I); + SizeOffsetAPInt visitGlobalAlias(GlobalAlias &GA); + SizeOffsetAPInt visitGlobalVariable(GlobalVariable &GV); + SizeOffsetAPInt visitIntToPtrInst(IntToPtrInst &); + SizeOffsetAPInt visitLoadInst(LoadInst &I); + SizeOffsetAPInt visitPHINode(PHINode &); + SizeOffsetAPInt visitSelectInst(SelectInst &I); + SizeOffsetAPInt visitUndefValue(UndefValue &); + SizeOffsetAPInt visitInstruction(Instruction &I); private: - SizeOffsetType findLoadSizeOffset( + SizeOffsetAPInt findLoadSizeOffset( LoadInst &LoadFrom, BasicBlock &BB, BasicBlock::iterator From, - SmallDenseMap<BasicBlock *, SizeOffsetType, 8> &VisitedBlocks, + SmallDenseMap<BasicBlock *, SizeOffsetAPInt, 8> &VisitedBlocks, unsigned &ScannedInstCount); - SizeOffsetType combineSizeOffset(SizeOffsetType LHS, SizeOffsetType RHS); - SizeOffsetType computeImpl(Value *V); - SizeOffsetType computeValue(Value *V); + SizeOffsetAPInt combineSizeOffset(SizeOffsetAPInt LHS, SizeOffsetAPInt RHS); + SizeOffsetAPInt computeImpl(Value *V); + SizeOffsetAPInt computeValue(Value *V); bool CheckedZextOrTrunc(APInt &I); }; -using SizeOffsetEvalType = std::pair<Value *, Value *>; +template <> struct SizeOffsetType<WeakTrackingVH>; + +/// SizeOffsetType<Value *> - Used by \p ObjectSizeOffsetEvaluator, which works +/// with \p Values. +template <> struct SizeOffsetType<Value *> { + Value *Size; + Value *Offset; + + SizeOffsetType() = default; + SizeOffsetType(Value *Size, Value *Offset) : Size(Size), Offset(Offset) {} + SizeOffsetType(SizeOffsetType<WeakTrackingVH> &SOT); + + bool knownSize() const { return Size != nullptr; } + bool knownOffset() const { return Offset != nullptr; } + bool anyKnown() const { return knownSize() || knownOffset(); } + bool bothKnown() const { return knownSize() && knownOffset(); } + + bool operator==(const SizeOffsetType<Value *> &RHS) { + return Size == RHS.Size && Offset == RHS.Offset; + } + bool operator!=(const SizeOffsetType<Value *> &RHS) { + return !(*this == RHS); + } +}; +using SizeOffsetValue = SizeOffsetType<Value *>; + +/// SizeOffsetType<WeakTrackingVH> - Used by \p ObjectSizeOffsetEvaluator in a +/// \p DenseMap. +template <> struct SizeOffsetType<WeakTrackingVH> { + WeakTrackingVH Size; + WeakTrackingVH Offset; + + SizeOffsetType() = default; + SizeOffsetType(Value *Size, Value *Offset) : Size(Size), Offset(Offset) {} + + bool knownSize() const { return Size.pointsToAliveValue(); } + bool knownOffset() const { return Offset.pointsToAliveValue(); } + bool anyKnown() const { return knownSize() || knownOffset(); } + bool bothKnown() const { return knownSize() && knownOffset(); } + + bool operator==(const SizeOffsetType<Value *> &RHS) { + return (Value *)Size == (Value *)RHS.Size && + (Value *)Offset == (Value *)RHS.Offset; + } + bool operator!=(const SizeOffsetType<Value *> &RHS) { + return !(*this == RHS); + } +}; +using SizeOffsetWeakTrackingVH = SizeOffsetType<WeakTrackingVH>; /// Evaluate the size and offset of an object pointed to by a Value*. /// May create code to compute the result at run-time. class ObjectSizeOffsetEvaluator - : public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetEvalType> { + : public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetValue> { using BuilderTy = IRBuilder<TargetFolder, IRBuilderCallbackInserter>; - using WeakEvalType = std::pair<WeakTrackingVH, WeakTrackingVH>; + using WeakEvalType = SizeOffsetType<WeakTrackingVH>; using CacheMapTy = DenseMap<const Value *, WeakEvalType>; using PtrSetTy = SmallPtrSet<const Value *, 8>; @@ -275,45 +341,27 @@ class ObjectSizeOffsetEvaluator ObjectSizeOpts EvalOpts; SmallPtrSet<Instruction *, 8> InsertedInstructions; - SizeOffsetEvalType compute_(Value *V); + SizeOffsetValue compute_(Value *V); public: - static SizeOffsetEvalType unknown() { - return std::make_pair(nullptr, nullptr); - } - ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, ObjectSizeOpts EvalOpts = {}); - SizeOffsetEvalType compute(Value *V); + static SizeOffsetValue unknown; - bool knownSize(SizeOffsetEvalType SizeOffset) { - return SizeOffset.first; - } - - bool knownOffset(SizeOffsetEvalType SizeOffset) { - return SizeOffset.second; - } - - bool anyKnown(SizeOffsetEvalType SizeOffset) { - return knownSize(SizeOffset) || knownOffset(SizeOffset); - } - - bool bothKnown(SizeOffsetEvalType SizeOffset) { - return knownSize(SizeOffset) && knownOffset(SizeOffset); - } + SizeOffsetValue compute(Value *V); // The individual instruction visitors should be treated as private. - SizeOffsetEvalType visitAllocaInst(AllocaInst &I); - SizeOffsetEvalType visitCallBase(CallBase &CB); - SizeOffsetEvalType visitExtractElementInst(ExtractElementInst &I); - SizeOffsetEvalType visitExtractValueInst(ExtractValueInst &I); - SizeOffsetEvalType visitGEPOperator(GEPOperator &GEP); - SizeOffsetEvalType visitIntToPtrInst(IntToPtrInst&); - SizeOffsetEvalType visitLoadInst(LoadInst &I); - SizeOffsetEvalType visitPHINode(PHINode &PHI); - SizeOffsetEvalType visitSelectInst(SelectInst &I); - SizeOffsetEvalType visitInstruction(Instruction &I); + SizeOffsetValue visitAllocaInst(AllocaInst &I); + SizeOffsetValue visitCallBase(CallBase &CB); + SizeOffsetValue visitExtractElementInst(ExtractElementInst &I); + SizeOffsetValue visitExtractValueInst(ExtractValueInst &I); + SizeOffsetValue visitGEPOperator(GEPOperator &GEP); + SizeOffsetValue visitIntToPtrInst(IntToPtrInst &); + SizeOffsetValue visitLoadInst(LoadInst &I); + SizeOffsetValue visitPHINode(PHINode &PHI); + SizeOffsetValue visitSelectInst(SelectInst &I); + SizeOffsetValue visitInstruction(Instruction &I); }; } // end namespace llvm diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp index 9e6811f3bf8815..8cc2d070d1d8e7 100644 --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -577,10 +577,12 @@ Value *llvm::getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI) { //===----------------------------------------------------------------------===// // Utility functions to compute size of objects. // -static APInt getSizeWithOverflow(const SizeOffsetType &Data) { - if (Data.second.isNegative() || Data.first.ult(Data.second)) - return APInt(Data.first.getBitWidth(), 0); - return Data.first - Data.second; +static APInt getSizeWithOverflow(const SizeOffsetAPInt &Data) { + APInt Size = Data.Size; + APInt Offset = Data.Offset; + if (Offset.isNegative() || Size.ult(Size)) + return APInt(Size.getBitWidth(), 0); + return Size - Offset; } /// Compute the size of the object pointed by Ptr. Returns true and the @@ -590,8 +592,8 @@ static APInt getSizeWithOverflow(const SizeOffsetType &Data) { bool llvm::getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts) { ObjectSizeOffsetVisitor Visitor(DL, TLI, Ptr->getContext(), Opts); - SizeOffsetType Data = Visitor.compute(const_cast<Value*>(Ptr)); - if (!Visitor.bothKnown(Data)) + SizeOffsetAPInt Data = Visitor.compute(const_cast<Value *>(Ptr)); + if (!Data.bothKnown()) return false; Size = getSizeWithOverflow(Data).getZExtValue(); @@ -640,10 +642,9 @@ Value *llvm::lowerObjectSizeCall( } else { LLVMContext &Ctx = ObjectSize->getFunction()->getContext(); ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, EvalOptions); - SizeOffsetEvalType SizeOffsetPair = - Eval.compute(ObjectSize->getArgOperand(0)); + SizeOffsetValue SizeOffsetPair = Eval.compute(ObjectSize->getArgOperand(0)); - if (SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown()) { + if (SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown) { IRBuilder<TargetFolder, IRBuilderCallbackInserter> Builder( Ctx, TargetFolder(DL), IRBuilderCallbackInserter([&](Instruction *I) { if (InsertedInstructions) @@ -651,19 +652,19 @@ Value *llvm::lowerObjectSizeCall( })); Builder.SetInsertPoint(ObjectSize); + Value *Size = SizeOffsetPair.Size; + Value *Offset = SizeOffsetPair.Offset; + // If we've outside the end of the object, then we can always access // exactly 0 bytes. - Value *ResultSize = - Builder.CreateSub(SizeOffsetPair.first, SizeOffsetPair.second); - Value *UseZero = - Builder.CreateICmpULT(SizeOffsetPair.first, SizeOffsetPair.second); + Value *ResultSize = Builder.CreateSub(Size, Offset); + Value *UseZero = Builder.CreateICmpULT(Size, Offset); ResultSize = Builder.CreateZExtOrTrunc(ResultSize, ResultType); Value *Ret = Builder.CreateSelect( UseZero, ConstantInt::get(ResultType, 0), ResultSize); // The non-constant size expression cannot evaluate to -1. - if (!isa<Constant>(SizeOffsetPair.first) || - !isa<Constant>(SizeOffsetPair.second)) + if (!isa<Constant>(Size) || !isa<Constant>(Offset)) Builder.CreateAssumption( Builder.CreateICmpNE(Ret, ConstantInt::get(ResultType, -1))); @@ -682,6 +683,8 @@ STATISTIC(ObjectVisitorArgument, STATISTIC(ObjectVisitorLoad, "Number of load instructions with unsolved size and offset"); +SizeOffsetAPInt ObjectSizeOffsetVisitor::unknown; + APInt ObjectSizeOffsetVisitor::align(APInt Size, MaybeAlign Alignment) { if (Options.RoundToAlign && Alignment) return APInt(IntTyBits, alignTo(Size.getZExtValue(), *Alignment)); @@ -697,12 +700,12 @@ ObjectSizeOffsetVisitor::ObjectSizeOffsetVisitor(const DataLayout &DL, // a different address space. } -SizeOffsetType ObjectSizeOffsetVisitor::compute(Value *V) { +SizeOffsetAPInt ObjectSizeOffsetVisitor::compute(Value *V) { InstructionsVisited = 0; return computeImpl(V); } -SizeOffsetType ObjectSizeOffsetVisitor::computeImpl(Value *V) { +SizeOffsetAPInt ObjectSizeOffsetVisitor::computeImpl(Value *V) { unsigned InitialIntTyBits = DL.getIndexTypeSizeInBits(V->getType()); // Stripping pointer casts can strip address space casts which can change the @@ -719,7 +722,7 @@ SizeOffsetType ObjectSizeOffsetVisitor::computeImpl(Value *V) { IntTyBits = DL.getIndexTypeSizeInBits(V->getType()); Zero = APInt::getZero(IntTyBits); - SizeOffsetType SOT = computeValue(V); + SizeOffsetAPInt SOT = computeValue(V); bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits; if (!IndexTypeSizeChanged && Offset.isZero()) @@ -729,27 +732,28 @@ SizeOffsetType ObjectSizeOffsetVisitor::computeImpl(Value *V) { // accumulated some constant offset (or both). Readjust the bit width to match // the argument index type size and apply the offset, as required. if (IndexTypeSizeChanged) { - if (knownSize(SOT) && !::CheckedZextOrTrunc(SOT.first, InitialIntTyBits)) - SOT.first = APInt(); - if (knownOffset(SOT) && !::CheckedZextOrTrunc(SOT.second, InitialIntTyBits)) - SOT.second = APInt(); + if (SOT.knownSize() && !::CheckedZextOrTrunc(SOT.Size, InitialIntTyBits)) + SOT.Size = APInt(); + if (SOT.knownOffset() && + !::CheckedZextOrTrunc(SOT.Offset, InitialIntTyBits)) + SOT.Offset = APInt(); } // If the computed offset is "unknown" we cannot add the stripped offset. - return {SOT.first, - SOT.second.getBitWidth() > 1 ? SOT.second + Offset : SOT.second}; + return {SOT.Size, + SOT.Offset.getBitWidth() > 1 ? SOT.Offset + Offset : SOT.Offset}; } -SizeOffsetType ObjectSizeOffsetVisitor::computeValue(Value *V) { +SizeOffsetAPInt ObjectSizeOffsetVisitor::computeValue(Value *V) { if (Instruction *I = dyn_cast<Instruction>(V)) { // If we have already seen this instruction, bail out. Cycles can happen in // unreachable code after constant propagation. - auto P = SeenInsts.try_emplace(I, unknown()); + auto P = SeenInsts.try_emplace(I, ObjectSizeOffsetVisitor::unknown); if (!P.second) return P.first->second; ++InstructionsVisited; if (InstructionsVisited > ObjectSizeOffsetVisitorMaxVisitInstructions) - return unknown(); - SizeOffsetType Res = visit(*I); + return ObjectSizeOffsetVisitor::unknown; + SizeOffsetAPInt Res = visit(*I); // Cache the result for later visits. If we happened to visit this during // the above recursion, we would consider it unknown until now. SeenInsts[I] = Res; @@ -768,55 +772,55 @@ SizeOffsetType ObjectSizeOffsetVisitor::computeValue(Value *V) { LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: " << *V << '\n'); - return unknown(); + return ObjectSizeOffsetVisitor::unknown; } bool ObjectSizeOffsetVisitor::CheckedZextOrTrunc(APInt &I) { return ::CheckedZextOrTrunc(I, IntTyBits); } -SizeOffsetType ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) { +SizeOffsetAPInt ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) { TypeSize ElemSize = DL.getTypeAllocSize(I.getAllocatedType()); if (ElemSize.isScalable() && Options.EvalMode != ObjectSizeOpts::Mode::Min) - return unknown(); + return ObjectSizeOffsetVisitor::unknown; APInt Size(IntTyBits, ElemSize.getKnownMinValue()); if (!I.isArrayAllocation()) - return std::make_pair(align(Size, I.getAlign()), Zero); + return SizeOffsetAPInt(align(Size, I.getAlign()), Zero); Value *ArraySize = I.getArraySize(); if (const ConstantInt *C = dyn_cast<ConstantInt>(ArraySize)) { APInt NumElems = C->getValue(); if (!CheckedZextOrTrunc(NumElems)) - return unknown(); + return ObjectSizeOffsetVisitor::unknown; bool Overflow; Size = Size.umul_ov(NumElems, Overflow); - return Overflow ? unknown() - : std::make_pair(align(Size, I.getAlign()), Zero); + return Overflow ? ObjectSizeOffsetVisitor::unknown + : SizeOffsetAPInt(align(Size, I.getAlign()), Zero); } - return unknown(); + return ObjectSizeOffsetVisitor::unknown; } -SizeOffsetType ObjectSizeOffsetVisitor::visitArgument(Argument &A) { +SizeOffsetAPInt ObjectSizeOffsetVisitor::visitArgument(Argument &A) { Type *MemoryTy = A.getPointeeInMemoryValueType(); // No interprocedural analysis is done at the moment. if (!MemoryTy|| !MemoryTy->isSized()) { ++ObjectVisitorArgument; - return unknown(); + return ObjectSizeOffsetVisitor::unknown; } APInt Size(IntTyBits, DL.getTypeAllocSize(MemoryTy)); - return std::make_pair(align(Size, A.getParamAlign()), Zero); + return SizeOffsetAPInt(align(Size, A.getParamAlign()), Zero); } -SizeOffsetType ObjectSizeOffsetVisitor::visitCallBase(CallBase &CB) { +SizeOffsetAPInt ObjectSizeOffsetVisitor::visitCallBase(CallBase &CB) { if (std::optional<APInt> Size = getAllocSize(&CB, TLI)) - return std::make_pair(*Size, Zero); - return unknown(); + return SizeOffsetAPInt(*Size, Zero); + return ObjectSizeOffsetVisitor::unknown; } -SizeOffsetType -ObjectSizeOffsetVisitor::visitConstantPointerNull(ConstantPointerNull& CPN) { +SizeOffsetAPInt +ObjectSizeOffsetVisitor::visitConstantPointerNull(ConstantPointerNull &CPN) { // If null is unknown, there's nothing we can do. Additionally, non-zero // address spaces can make use of null, so we don't presume to know anything // about that. @@ -825,45 +829,46 @@ ObjectSizeOffsetVisitor::visitConstantPointerNull(ConstantPointerNull& CPN) { // them on the floor, but it's unclear what we should do when a NULL from // addrspace(1) gets casted to addrspace(0) (or vice-versa). if (Options.NullIsUnknownSize || CPN.getType()->getAddressSpace()) - return unknown(); - return std::make_pair(Zero, Zero); + return ObjectSizeOffsetVisitor::unknown; + return SizeOffsetAPInt(Zero, Zero); } -SizeOffsetType -ObjectSizeOffsetVisitor::visitExtractElementInst(ExtractElementInst&) { - return unknown(); +SizeOffsetAPInt +ObjectSizeOffsetVisitor::visitExtractElementInst(ExtractElementInst &) { + return ObjectSizeOffsetVisitor::unknown; } -SizeOffsetType -ObjectSizeOffsetVisitor::visitExtractValueInst(ExtractValueInst&) { +SizeOffsetAPInt +ObjectSizeOffsetVisitor::visitExtractValueInst(ExtractValueInst &) { // Easy cases were already folded by previous passes. - return unknown(); + return ObjectSizeOffsetVisitor::unknown; } -SizeOffsetType ObjectSizeOffsetVisitor::visitGlobalAlias(GlobalAlias &GA) { +SizeOffsetAPInt ObjectSizeOffsetVisitor::visitGlobalAlias(GlobalAlias &GA) { if (GA.isInterposable()) - return unknown(); + return ObjectSizeOffsetVisitor::unknown; return computeImpl(GA.getAliasee()); } -SizeOffsetType ObjectSizeOffsetVisitor::visitGlobalVariable(GlobalVariable &GV){ +SizeOffsetAPInt +ObjectSizeOffsetVisitor::visitGlobalVariable(GlobalVariable &GV) { if (!GV.getValueType()->isSized() || GV.hasExternalWeakLinkage() || ((!GV.hasInitializer() || GV.isInterposable()) && Options.EvalMode != ObjectSizeOpts::Mode::Min)) - return unknown(); + return ObjectSizeOffsetVisitor::unknown; APInt Size(IntTyBits, DL.getTypeAllocSize(GV.getValueType())); - return std::make_pair(align(Size, GV.getAlign()), Zero); + return SizeOffsetAPInt(align(Size, GV.getAlign()), Zero); } -SizeOffsetType ObjectSizeOffsetVisitor::visitIntToPtrInst(IntToPtrInst&) { +SizeOffsetAPInt ObjectSizeOffsetVisitor::visitIntToPtrInst(IntToPtrInst &) { // clueless - return unknown(); + return ObjectSizeOffsetVisitor::unknown; } -SizeOffsetType ObjectSizeOffsetVisitor::findLoadSizeOffset( +SizeOffsetAPInt ObjectSizeOffsetVisitor::findLoadSizeOffset( LoadInst &Load, BasicBlock &BB, BasicBlock::iterator From, - SmallDenseMap<BasicBlock *, SizeOffsetType, 8> &VisitedBlocks, + SmallDenseMap<BasicBlock *, SizeOffsetAPInt, 8> &VisitedBlocks, unsigned &ScannedInstCount) { constexpr unsigned MaxInstsToScan = 128; @@ -871,10 +876,10 @@ SizeOffsetType ObjectSizeOffsetVisitor::findLoadSizeOffset( if (Where != VisitedBlocks.end()) return Where->second; - auto Unknown = [this, &BB, &VisitedBlocks]() { - return VisitedBlocks[&BB] = unknown(); + auto Unknown = [&BB, &VisitedBlocks]() { + return VisitedBlocks[&BB] = ObjectSizeOffsetVisitor::unknown; }; - auto Known = [&BB, &VisitedBlocks](SizeOffsetType SO) { + auto Known = [&BB, &VisitedBlocks](SizeOffsetAPInt SO) { return VisitedBlocks[&BB] = SO; }; @@ -951,46 +956,47 @@ SizeOffsetType ObjectSizeOffsetVisitor::findLoadSizeOffset( return Unknown(); } while (From-- != BB.begin()); - SmallVector<SizeOffsetType> PredecessorSizeOffsets; + SmallVector<SizeOffsetAPInt> PredecessorSizeOffsets; for (auto *PredBB : predecessors(&BB)) { PredecessorSizeOffsets.push_back(findLoadSizeOffset( Load, *PredBB, BasicBlock::iterator(PredBB->getTerminator()), VisitedBlocks, ScannedInstCount)); - if (!bothKnown(PredecessorSizeOffsets.back())) + if (!PredecessorSizeOffsets.back().bothKnown()) return Unknown(); } if (PredecessorSizeOffsets.empty()) return Unknown(); - return Known(std::accumulate(PredecessorSizeOffsets.begin() + 1, - PredecessorSizeOffsets.end(), - PredecessorSizeOffsets.front(), - [this](SizeOffsetType LHS, SizeOffsetType RHS) { - return combineSizeOffset(LHS, RHS); - })); + return Known(std::accumulate( + PredecessorSizeOffsets.begin() + 1, PredecessorSizeOffsets.end(), + PredecessorSizeOffsets.front(), + [this](SizeOffsetAPInt LHS, SizeOffsetAPInt RHS) { + return combineSizeOffset(LHS, RHS); + })); } -SizeOffsetType ObjectSizeOffsetVisitor::visitLoadInst(LoadInst &LI) { +SizeOffsetAPInt ObjectSizeOffsetVisitor::visitLoadInst(LoadInst &LI) { if (!Options.AA) { ++ObjectVisitorLoad; - return unknown(); + return ObjectSizeOffsetVisitor::unknown; } - SmallDenseMap<BasicBlock *, SizeOffsetType, 8> VisitedBlocks; + SmallDenseMap<BasicBlock *, SizeOffsetAPInt, 8> VisitedBlocks; unsigned ScannedInstCount = 0; - SizeOffsetType SO = + SizeOffsetAPInt SO = findLoadSizeOffset(LI, *LI.getParent(), BasicBlock::iterator(LI), VisitedBlocks, ScannedInstCount); - if (!bothKnown(SO)) + if (!SO.bothKnown()) ++ObjectVisitorLoad; return SO; } -SizeOffsetType ObjectSizeOffsetVisitor::combineSizeOffset(SizeOffsetType LHS, - SizeOffsetType RHS) { - if (!bothKnown(LHS) || !bothKnown(RHS)) - return unknown(); +SizeOffsetAPInt +ObjectSizeOffsetVisitor::combineSizeOffset(SizeOffsetAPInt LHS, + SizeOffsetAPInt RHS) { + if (!LHS.bothKnown() || !RHS.bothKnown()) + return ObjectSizeOffsetVisitor::unknown; switch (Options.EvalMode) { case ObjectSizeOpts::Mode::Min: @@ -998,40 +1004,47 @@ SizeOffsetType ObjectSizeOffsetVisitor::combineSizeOffset(SizeOffsetType LHS, case ObjectSizeOpts::Mode::Max: return (getSizeWithOverflow(LHS).sgt(getSizeWithOverflow(RHS))) ? LHS : RHS; case ObjectSizeOpts::Mode::ExactSizeFromOffset: - return (getSizeWithOverflow(LHS).eq(getSizeWithOverflow(RHS))) ? LHS - : unknown(); + return (getSizeWithOverflow(LHS).eq(getSizeWithOverflow(RHS))) + ? LHS + : ObjectSizeOffsetVisitor::unknown; case ObjectSizeOpts::Mode::ExactUnderlyingSizeAndOffset: - return LHS == RHS ? LHS : unknown(); + return LHS == RHS ? LHS : ObjectSizeOffsetVisitor::unknown; } llvm_unreachable("missing an eval mode"); } -SizeOffsetType ObjectSizeOffsetVisitor::visitPHINode(PHINode &PN) { +SizeOffsetAPInt ObjectSizeOffsetVisitor::visitPHINode(PHINode &PN) { if (PN.getNumIncomingValues() == 0) - return unknown(); + return ObjectSizeOffsetVisitor::unknown; auto IncomingValues = PN.incoming_values(); return std::accumulate(IncomingValues.begin() + 1, IncomingValues.end(), computeImpl(*IncomingValues.begin()), - [this](SizeOffsetType LHS, Value *VRHS) { + [this](SizeOffsetAPInt LHS, Value *VRHS) { return combineSizeOffset(LHS, computeImpl(VRHS)); }); } -SizeOffsetType ObjectSizeOffsetVisitor::visitSelectInst(SelectInst &I) { +SizeOffsetAPInt ObjectSizeOffsetVisitor::visitSelectInst(SelectInst &I) { return combineSizeOffset(computeImpl(I.getTrueValue()), computeImpl(I.getFalseValue())); } -SizeOffsetType ObjectSizeOffsetVisitor::visitUndefValue(UndefValue&) { - return std::make_pair(Zero, Zero); +SizeOffsetAPInt ObjectSizeOffsetVisitor::visitUndefValue(UndefValue &) { + return SizeOffsetAPInt(Zero, Zero); } -SizeOffsetType ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) { +SizeOffsetAPInt ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) { LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor unknown instruction:" << I << '\n'); - return unknown(); + return ObjectSizeOffsetVisitor::unknown; } +// Just set these right here... +SizeOffsetValue::SizeOffsetType(SizeOffsetWeakTrackingVH &SOT) + : Size((Value *)SOT.Size), Offset((Value *)SOT.Offset) {} + +SizeOffsetValue ObjectSizeOffsetEvaluator::unknown; + ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator( const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, ObjectSizeOpts EvalOpts) @@ -1044,21 +1057,21 @@ ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator( // be different for later objects. } -SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute(Value *V) { +SizeOffsetValue ObjectSizeOffsetEvaluator::compute(Value *V) { // XXX - Are vectors of pointers possible here? IntTy = cast<IntegerType>(DL.getIndexType(V->getType())); Zero = ConstantInt::get(IntTy, 0); - SizeOffsetEvalType Result = compute_(V); + SizeOffsetValue Result = compute_(V); - if (!bothKnown(Result)) { + if (!Result.bothKnown()) { // Erase everything that was computed in this iteration from the cache, so // that no dangling references are left behind. We could be a bit smarter if // we kept a dependency graph. It's probably not worth the complexity. for (const Value *SeenVal : SeenVals) { CacheMapTy::iterator CacheIt = CacheMap.find(SeenVal); // non-computable results can be safely cached - if (CacheIt != CacheMap.end() && anyKnown(CacheIt->second)) + if (CacheIt != CacheMap.end() && CacheIt->second.anyKnown()) CacheMap.erase(CacheIt); } @@ -1074,12 +1087,12 @@ SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute(Value *V) { return Result; } -SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) { +SizeOffsetValue ObjectSizeOffsetEvaluator::compute_(Value *V) { ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, EvalOpts); - SizeOffsetType Const = Visitor.compute(V); - if (Visitor.bothKnown(Const)) - return std::make_pair(ConstantInt::get(Context, Const.first), - ConstantInt::get(Context, Const.second)); + SizeOffsetAPInt Const = Visitor.compute(V); + if (Const.bothKnown()) + return SizeOffsetValue(ConstantInt::get(Context, Const.Size), + ConstantInt::get(Context, Const.Offset)); V = V->stripPointerCasts(); @@ -1095,13 +1108,13 @@ SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) { Builder.SetInsertPoint(I); // Now compute the size and offset. - SizeOffsetEvalType Result; + SizeOffsetValue Result; // Record the pointers that were handled in this run, so that they can be // cleaned later if something fails. We also use this set to break cycles that // can occur in dead code. if (!SeenVals.insert(V).second) { - Result = unknown(); + Result = ObjectSizeOffsetEvaluator::unknown; } else if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) { Result = visitGEPOperator(*GEP); } else if (Instruction *I = dyn_cast<Instruction>(V)) { @@ -1112,22 +1125,22 @@ SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) { isa<GlobalAlias>(V) || isa<GlobalVariable>(V)) { // Ignore values where we cannot do more than ObjectSizeVisitor. - Result = unknown(); + Result = ObjectSizeOffsetEvaluator::unknown; } else { LLVM_DEBUG( dbgs() << "ObjectSizeOffsetEvaluator::compute() unhandled value: " << *V << '\n'); - Result = unknown(); + Result = ObjectSizeOffsetEvaluator::unknown; } // Don't reuse CacheIt since it may be invalid at this point. - CacheMap[V] = Result; + CacheMap[V] = SizeOffsetWeakTrackingVH(Result.Size, Result.Offset); return Result; } -SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitAllocaInst(AllocaInst &I) { +SizeOffsetValue ObjectSizeOffsetEvaluator::visitAllocaInst(AllocaInst &I) { if (!I.getAllocatedType()->isSized()) - return unknown(); + return ObjectSizeOffsetEvaluator::unknown; // must be a VLA assert(I.isArrayAllocation()); @@ -1143,86 +1156,85 @@ SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitAllocaInst(AllocaInst &I) { Value *Size = ConstantInt::get(ArraySize->getType(), DL.getTypeAllocSize(I.getAllocatedType())); Size = Builder.CreateMul(Size, ArraySize); - return std::make_pair(Size, Zero); + return SizeOffsetValue(Size, Zero); } -SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitCallBase(CallBase &CB) { +SizeOffsetValue ObjectSizeOffsetEvaluator::visitCallBase(CallBase &CB) { std::optional<AllocFnsTy> FnData = getAllocationSize(&CB, TLI); if (!FnData) - return unknown(); + return ObjectSizeOffsetEvaluator::unknown; // Handle strdup-like functions separately. if (FnData->AllocTy == StrDupLike) { // TODO: implement evaluation of strdup/strndup - return unknown(); + return ObjectSizeOffsetEvaluator::unknown; } Value *FirstArg = CB.getArgOperand(FnData->FstParam); FirstArg = Builder.CreateZExtOrTrunc(FirstArg, IntTy); if (FnData->SndParam < 0) - return std::make_pair(FirstArg, Zero); + return SizeOffsetValue(FirstArg, Zero); Value *SecondArg = CB.getArgOperand(FnData->SndParam); SecondArg = Builder.CreateZExtOrTrunc(SecondArg, IntTy); Value *Size = Builder.CreateMul(FirstArg, SecondArg); - return std::make_pair(Size, Zero); + return SizeOffsetValue(Size, Zero); } -SizeOffsetEvalType -ObjectSizeOffsetEvaluator::visitExtractElementInst(ExtractElementInst&) { - return unknown(); +SizeOffsetValue +ObjectSizeOffsetEvaluator::visitExtractElementInst(ExtractElementInst &) { + return ObjectSizeOffsetEvaluator::unknown; } -SizeOffsetEvalType -ObjectSizeOffsetEvaluator::visitExtractValueInst(ExtractValueInst&) { - return unknown(); +SizeOffsetValue +ObjectSizeOffsetEvaluator::visitExtractValueInst(ExtractValueInst &) { + return ObjectSizeOffsetEvaluator::unknown; } -SizeOffsetEvalType -ObjectSizeOffsetEvaluator::visitGEPOperator(GEPOperator &GEP) { - SizeOffsetEvalType PtrData = compute_(GEP.getPointerOperand()); - if (!bothKnown(PtrData)) - return unknown(); +SizeOffsetValue ObjectSizeOffsetEvaluator::visitGEPOperator(GEPOperator &GEP) { + SizeOffsetValue PtrData = compute_(GEP.getPointerOperand()); + if (!PtrData.bothKnown()) + return ObjectSizeOffsetEvaluator::unknown; Value *Offset = emitGEPOffset(&Builder, DL, &GEP, /*NoAssumptions=*/true); - Offset = Builder.CreateAdd(PtrData.second, Offset); - return std::make_pair(PtrData.first, Offset); + Offset = Builder.CreateAdd(PtrData.Offset, Offset); + return SizeOffsetValue(PtrData.Size, Offset); } -SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitIntToPtrInst(IntToPtrInst&) { +SizeOffsetValue ObjectSizeOffsetEvaluator::visitIntToPtrInst(IntToPtrInst &) { // clueless - return unknown(); + return ObjectSizeOffsetEvaluator::unknown; } -SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitLoadInst(LoadInst &LI) { - return unknown(); +SizeOffsetValue ObjectSizeOffsetEvaluator::visitLoadInst(LoadInst &LI) { + return ObjectSizeOffsetEvaluator::unknown; } -SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitPHINode(PHINode &PHI) { +SizeOffsetValue ObjectSizeOffsetEvaluator::visitPHINode(PHINode &PHI) { // Create 2 PHIs: one for size and another for offset. PHINode *SizePHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues()); PHINode *OffsetPHI = Builder.CreatePHI(IntTy, PHI.getNumIncomingValues()); // Insert right away in the cache to handle recursive PHIs. - CacheMap[&PHI] = std::make_pair(SizePHI, OffsetPHI); + CacheMap[&PHI] = SizeOffsetWeakTrackingVH(SizePHI, OffsetPHI); // Compute offset/size for each PHI incoming pointer. for (unsigned i = 0, e = PHI.getNumIncomingValues(); i != e; ++i) { BasicBlock *IncomingBlock = PHI.getIncomingBlock(i); Builder.SetInsertPoint(IncomingBlock, IncomingBlock->getFirstInsertionPt()); - SizeOffsetEvalType EdgeData = compute_(PHI.getIncomingValue(i)); + SizeOffsetValue EdgeData = compute_(PHI.getIncomingValue(i)); - if (!bothKnown(EdgeData)) { + if (!EdgeData.bothKnown()) { OffsetPHI->replaceAllUsesWith(PoisonValue::get(IntTy)); OffsetPHI->eraseFromParent(); InsertedInstructions.erase(OffsetPHI); SizePHI->replaceAllUsesWith(PoisonValue::get(IntTy)); SizePHI->eraseFromParent(); InsertedInstructions.erase(SizePHI); - return unknown(); + return ObjectSizeOffsetEvaluator::unknown; } - SizePHI->addIncoming(EdgeData.first, IncomingBlock); - OffsetPHI->addIncoming(EdgeData.second, IncomingBlock); + SizePHI->addIncoming(EdgeData.Size, IncomingBlock); + OffsetPHI->addIncoming(EdgeData.Offset, IncomingBlock); } Value *Size = SizePHI, *Offset = OffsetPHI; @@ -1238,27 +1250,27 @@ SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitPHINode(PHINode &PHI) { OffsetPHI->eraseFromParent(); InsertedInstructions.erase(OffsetPHI); } - return std::make_pair(Size, Offset); + return SizeOffsetValue(Size, Offset); } -SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitSelectInst(SelectInst &I) { - SizeOffsetEvalType TrueSide = compute_(I.getTrueValue()); - SizeOffsetEvalType FalseSide = compute_(I.getFalseValue()); +SizeOffsetValue ObjectSizeOffsetEvaluator::visitSelectInst(SelectInst &I) { + SizeOffsetValue TrueSide = compute_(I.getTrueValue()); + SizeOffsetValue FalseSide = compute_(I.getFalseValue()); - if (!bothKnown(TrueSide) || !bothKnown(FalseSide)) - return unknown(); + if (!TrueSide.bothKnown() || !FalseSide.bothKnown()) + return ObjectSizeOffsetEvaluator::unknown; if (TrueSide == FalseSide) return TrueSide; - Value *Size = Builder.CreateSelect(I.getCondition(), TrueSide.first, - FalseSide.first); - Value *Offset = Builder.CreateSelect(I.getCondition(), TrueSide.second, - FalseSide.second); - return std::make_pair(Size, Offset); + Value *Size = + Builder.CreateSelect(I.getCondition(), TrueSide.Size, FalseSide.Size); + Value *Offset = + Builder.CreateSelect(I.getCondition(), TrueSide.Offset, FalseSide.Offset); + return SizeOffsetValue(Size, Offset); } -SizeOffsetEvalType ObjectSizeOffsetEvaluator::visitInstruction(Instruction &I) { +SizeOffsetValue ObjectSizeOffsetEvaluator::visitInstruction(Instruction &I) { LLVM_DEBUG(dbgs() << "ObjectSizeOffsetEvaluator unknown instruction:" << I << '\n'); - return unknown(); + return ObjectSizeOffsetEvaluator::unknown; } diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp index b2618e35b08552..b4d83ef728bd12 100644 --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -6725,10 +6725,10 @@ struct AAHeapToStackFunction final : public AAHeapToStack { LLVMContext &Ctx = AI.CB->getContext(); ObjectSizeOpts Opts; ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, Opts); - SizeOffsetEvalType SizeOffsetPair = Eval.compute(AI.CB); - assert(SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown() && - cast<ConstantInt>(SizeOffsetPair.second)->isZero()); - Size = SizeOffsetPair.first; + SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB); + assert(SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown && + cast<ConstantInt>(SizeOffsetPair.Offset)->isZero()); + Size = SizeOffsetPair.Size; } Instruction *IP = diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index afb0e6cd1548b0..5e1d8f0e51008d 100644 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -3629,10 +3629,14 @@ bool AddressSanitizer::isSafeAccess(ObjectSizeOffsetVisitor &ObjSizeVis, // TODO: We can use vscale_range to convert a scalable value to an // upper bound on the access size. return false; - SizeOffsetType SizeOffset = ObjSizeVis.compute(Addr); - if (!ObjSizeVis.bothKnown(SizeOffset)) return false; - uint64_t Size = SizeOffset.first.getZExtValue(); - int64_t Offset = SizeOffset.second.getSExtValue(); + + SizeOffsetAPInt SizeOffset = ObjSizeVis.compute(Addr); + if (!SizeOffset.bothKnown()) + return false; + + uint64_t Size = SizeOffset.Size.getZExtValue(); + int64_t Offset = SizeOffset.Offset.getSExtValue(); + // Three checks are required to ensure safety: // . Offset >= 0 (since the offset is given from the base ptr) // . Size >= Offset (unsigned) diff --git a/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp b/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp index ee5b819604170e..cfa8ae26c62572 100644 --- a/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp +++ b/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp @@ -61,15 +61,15 @@ static Value *getBoundsCheckCond(Value *Ptr, Value *InstVal, LLVM_DEBUG(dbgs() << "Instrument " << *Ptr << " for " << Twine(NeededSize) << " bytes\n"); - SizeOffsetEvalType SizeOffset = ObjSizeEval.compute(Ptr); + SizeOffsetValue SizeOffset = ObjSizeEval.compute(Ptr); - if (!ObjSizeEval.bothKnown(SizeOffset)) { + if (!SizeOffset.bothKnown()) { ++ChecksUnable; return nullptr; } - Value *Size = SizeOffset.first; - Value *Offset = SizeOffset.second; + Value *Size = SizeOffset.Size; + Value *Offset = SizeOffset.Offset; ConstantInt *SizeCI = dyn_cast<ConstantInt>(Size); Type *IndexTy = DL.getIndexType(Ptr->getType()); >From 68900ef913c47991ed4761b2917a5d4f08d81dd7 Mon Sep 17 00:00:00 2001 From: Bill Wendling <mo...@google.com> Date: Wed, 3 Jan 2024 16:19:16 -0800 Subject: [PATCH 2/6] Use correct value. --- llvm/lib/Analysis/MemoryBuiltins.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp index 8cc2d070d1d8e7..47ac5446c3142b 100644 --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -580,7 +580,7 @@ Value *llvm::getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI) { static APInt getSizeWithOverflow(const SizeOffsetAPInt &Data) { APInt Size = Data.Size; APInt Offset = Data.Offset; - if (Offset.isNegative() || Size.ult(Size)) + if (Offset.isNegative() || Size.ult(Offset)) return APInt(Size.getBitWidth(), 0); return Size - Offset; } >From 2a235d3a6254f5c880b35c77159d547881fc1e92 Mon Sep 17 00:00:00 2001 From: Bill Wendling <mo...@google.com> Date: Wed, 3 Jan 2024 16:22:03 -0800 Subject: [PATCH 3/6] Add helpful c'tor. --- llvm/include/llvm/Analysis/MemoryBuiltins.h | 1 + llvm/lib/Analysis/MemoryBuiltins.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h index 56faa32fb0b226..aff5a29445ef70 100644 --- a/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -305,6 +305,7 @@ template <> struct SizeOffsetType<WeakTrackingVH> { SizeOffsetType() = default; SizeOffsetType(Value *Size, Value *Offset) : Size(Size), Offset(Offset) {} + SizeOffsetType(SizeOffsetValue &SOT) : Size(SOT.Size), Offset(SOT.Offset) {} bool knownSize() const { return Size.pointsToAliveValue(); } bool knownOffset() const { return Offset.pointsToAliveValue(); } diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp index 47ac5446c3142b..ac8005df29d14e 100644 --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -1134,7 +1134,7 @@ SizeOffsetValue ObjectSizeOffsetEvaluator::compute_(Value *V) { } // Don't reuse CacheIt since it may be invalid at this point. - CacheMap[V] = SizeOffsetWeakTrackingVH(Result.Size, Result.Offset); + CacheMap[V] = SizeOffsetWeakTrackingVH(Result); return Result; } >From 278faa86119ed25214534951a9ccd078e4b69f1f Mon Sep 17 00:00:00 2001 From: Bill Wendling <mo...@google.com> Date: Wed, 3 Jan 2024 17:45:48 -0800 Subject: [PATCH 4/6] Move common functions and items into the base class. Use inheritance instead of specialization. --- llvm/include/llvm/Analysis/MemoryBuiltins.h | 96 ++++++++------------- llvm/lib/Analysis/MemoryBuiltins.cpp | 4 +- 2 files changed, 37 insertions(+), 63 deletions(-) diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h index aff5a29445ef70..10a98739377d24 100644 --- a/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -190,36 +190,36 @@ Value *lowerObjectSizeCall( /// SizeOffsetType - A base template class for the object size visitors. Used /// here as a self-documenting way to handle the values rather than using a /// \p std::pair. -template <typename T> struct SizeOffsetType { +template <typename T> +struct SizeOffsetType { T Size; T Offset; - bool knownSize() const; - bool knownOffset() const; - bool anyKnown() const; - bool bothKnown() const; -}; - -/// SizeOffsetType<APInt> - Used by \p ObjectSizeOffsetVisitor, which works -/// with \p APInts. -template <> struct SizeOffsetType<APInt> { - APInt Size; - APInt Offset; - SizeOffsetType() = default; - SizeOffsetType(APInt Size, APInt Offset) : Size(Size), Offset(Offset) {} + SizeOffsetType(T Size, T Offset) : Size(Size), Offset(Offset) {} - bool knownSize() const { return Size.getBitWidth() > 1; } - bool knownOffset() const { return Offset.getBitWidth() > 1; } + bool knownSize() const { return false; } + bool knownOffset() const { return false; } bool anyKnown() const { return knownSize() || knownOffset(); } bool bothKnown() const { return knownSize() && knownOffset(); } - bool operator==(const SizeOffsetType<APInt> &RHS) { - return Size == RHS.Size && Offset == RHS.Offset; + bool operator==(const SizeOffsetType<T> &RHS) const { + return (T)Size == (T)RHS.Size && (T)Offset == (T)RHS.Offset; + } + bool operator!=(const SizeOffsetType<T> &RHS) const { + return !(*this == RHS); } - bool operator!=(const SizeOffsetType<APInt> &RHS) { return !(*this == RHS); } }; -using SizeOffsetAPInt = SizeOffsetType<APInt>; + +/// SizeOffsetAPInt - Used by \p ObjectSizeOffsetVisitor, which works with +/// \p APInts. +struct SizeOffsetAPInt : public SizeOffsetType<APInt> { + SizeOffsetAPInt() = default; + SizeOffsetAPInt(APInt Size, APInt Offset) : SizeOffsetType(Size, Offset) {} + + bool knownSize() const { return Size.getBitWidth() > 1; } + bool knownOffset() const { return Offset.getBitWidth() > 1; } +}; /// Evaluate the size and offset of an object pointed to by a Value* /// statically. Fails if size or offset are not known at compile time. @@ -271,63 +271,37 @@ class ObjectSizeOffsetVisitor bool CheckedZextOrTrunc(APInt &I); }; -template <> struct SizeOffsetType<WeakTrackingVH>; - -/// SizeOffsetType<Value *> - Used by \p ObjectSizeOffsetEvaluator, which works -/// with \p Values. -template <> struct SizeOffsetType<Value *> { - Value *Size; - Value *Offset; - - SizeOffsetType() = default; - SizeOffsetType(Value *Size, Value *Offset) : Size(Size), Offset(Offset) {} - SizeOffsetType(SizeOffsetType<WeakTrackingVH> &SOT); +/// SizeOffsetValue - Used by \p ObjectSizeOffsetEvaluator, which works with +/// \p Values. +struct SizeOffsetWeakTrackingVH; +struct SizeOffsetValue : public SizeOffsetType<Value *> { + SizeOffsetValue() = default; + SizeOffsetValue(Value *Size, Value *Offset) : SizeOffsetType(Size, Offset) {} + SizeOffsetValue(const SizeOffsetWeakTrackingVH &SOT); bool knownSize() const { return Size != nullptr; } bool knownOffset() const { return Offset != nullptr; } - bool anyKnown() const { return knownSize() || knownOffset(); } - bool bothKnown() const { return knownSize() && knownOffset(); } - - bool operator==(const SizeOffsetType<Value *> &RHS) { - return Size == RHS.Size && Offset == RHS.Offset; - } - bool operator!=(const SizeOffsetType<Value *> &RHS) { - return !(*this == RHS); - } }; -using SizeOffsetValue = SizeOffsetType<Value *>; -/// SizeOffsetType<WeakTrackingVH> - Used by \p ObjectSizeOffsetEvaluator in a +/// SizeOffsetWeakTrackingVH - Used by \p ObjectSizeOffsetEvaluator in a /// \p DenseMap. -template <> struct SizeOffsetType<WeakTrackingVH> { - WeakTrackingVH Size; - WeakTrackingVH Offset; - - SizeOffsetType() = default; - SizeOffsetType(Value *Size, Value *Offset) : Size(Size), Offset(Offset) {} - SizeOffsetType(SizeOffsetValue &SOT) : Size(SOT.Size), Offset(SOT.Offset) {} +struct SizeOffsetWeakTrackingVH : public SizeOffsetType<WeakTrackingVH> { + SizeOffsetWeakTrackingVH() = default; + SizeOffsetWeakTrackingVH(Value *Size, Value *Offset) + : SizeOffsetType(Size, Offset) {} + SizeOffsetWeakTrackingVH(const SizeOffsetValue &SOV) + : SizeOffsetType(SOV.Size, SOV.Offset) {} bool knownSize() const { return Size.pointsToAliveValue(); } bool knownOffset() const { return Offset.pointsToAliveValue(); } - bool anyKnown() const { return knownSize() || knownOffset(); } - bool bothKnown() const { return knownSize() && knownOffset(); } - - bool operator==(const SizeOffsetType<Value *> &RHS) { - return (Value *)Size == (Value *)RHS.Size && - (Value *)Offset == (Value *)RHS.Offset; - } - bool operator!=(const SizeOffsetType<Value *> &RHS) { - return !(*this == RHS); - } }; -using SizeOffsetWeakTrackingVH = SizeOffsetType<WeakTrackingVH>; /// Evaluate the size and offset of an object pointed to by a Value*. /// May create code to compute the result at run-time. class ObjectSizeOffsetEvaluator : public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetValue> { using BuilderTy = IRBuilder<TargetFolder, IRBuilderCallbackInserter>; - using WeakEvalType = SizeOffsetType<WeakTrackingVH>; + using WeakEvalType = SizeOffsetWeakTrackingVH; using CacheMapTy = DenseMap<const Value *, WeakEvalType>; using PtrSetTy = SmallPtrSet<const Value *, 8>; diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp index ac8005df29d14e..e03f5c0977127f 100644 --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -1040,8 +1040,8 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) { } // Just set these right here... -SizeOffsetValue::SizeOffsetType(SizeOffsetWeakTrackingVH &SOT) - : Size((Value *)SOT.Size), Offset((Value *)SOT.Offset) {} +SizeOffsetValue::SizeOffsetValue(const SizeOffsetWeakTrackingVH &SOT) + : SizeOffsetType((Value *)SOT.Size, (Value *)SOT.Offset) {} SizeOffsetValue ObjectSizeOffsetEvaluator::unknown; >From c9b2154fdc12379621e1d3aedfc1e41df9fb88c9 Mon Sep 17 00:00:00 2001 From: Bill Wendling <mo...@google.com> Date: Thu, 4 Jan 2024 00:08:47 -0800 Subject: [PATCH 5/6] Format --- llvm/include/llvm/Analysis/MemoryBuiltins.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h index 10a98739377d24..10c5505c5b598c 100644 --- a/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -190,8 +190,7 @@ Value *lowerObjectSizeCall( /// SizeOffsetType - A base template class for the object size visitors. Used /// here as a self-documenting way to handle the values rather than using a /// \p std::pair. -template <typename T> -struct SizeOffsetType { +template <typename T> struct SizeOffsetType { T Size; T Offset; >From 2bcd640815bb39819b2d096f6e1483d950462fc0 Mon Sep 17 00:00:00 2001 From: Bill Wendling <mo...@google.com> Date: Thu, 4 Jan 2024 04:37:59 -0800 Subject: [PATCH 6/6] Don't use a static data member for 'unknown' as it might be changed. Also make the base class abstract. --- llvm/include/llvm/Analysis/MemoryBuiltins.h | 30 +++---- llvm/lib/Analysis/MemoryBuiltins.cpp | 78 +++++++++---------- .../Transforms/IPO/AttributorAttributes.cpp | 2 +- 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h index 10c5505c5b598c..2849e2da545a68 100644 --- a/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -196,14 +196,18 @@ template <typename T> struct SizeOffsetType { SizeOffsetType() = default; SizeOffsetType(T Size, T Offset) : Size(Size), Offset(Offset) {} + virtual ~SizeOffsetType() = default; + + virtual bool knownSize() const = 0; + virtual bool knownOffset() const = 0; - bool knownSize() const { return false; } - bool knownOffset() const { return false; } bool anyKnown() const { return knownSize() || knownOffset(); } bool bothKnown() const { return knownSize() && knownOffset(); } bool operator==(const SizeOffsetType<T> &RHS) const { - return (T)Size == (T)RHS.Size && (T)Offset == (T)RHS.Offset; + // Cast here to get the 'Value*' from the 'WeakTrackingVH' object. + return static_cast<T>(Size) == static_cast<T>(RHS.Size) && + static_cast<T>(Offset) == static_cast<T>(RHS.Offset); } bool operator!=(const SizeOffsetType<T> &RHS) const { return !(*this == RHS); @@ -216,8 +220,8 @@ struct SizeOffsetAPInt : public SizeOffsetType<APInt> { SizeOffsetAPInt() = default; SizeOffsetAPInt(APInt Size, APInt Offset) : SizeOffsetType(Size, Offset) {} - bool knownSize() const { return Size.getBitWidth() > 1; } - bool knownOffset() const { return Offset.getBitWidth() > 1; } + bool knownSize() const override { return Size.getBitWidth() > 1; } + bool knownOffset() const override { return Offset.getBitWidth() > 1; } }; /// Evaluate the size and offset of an object pointed to by a Value* @@ -234,7 +238,7 @@ class ObjectSizeOffsetVisitor APInt align(APInt Size, MaybeAlign Align); - static SizeOffsetAPInt unknown; + static SizeOffsetAPInt unknown() { return SizeOffsetAPInt(); } public: ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI, @@ -274,25 +278,25 @@ class ObjectSizeOffsetVisitor /// \p Values. struct SizeOffsetWeakTrackingVH; struct SizeOffsetValue : public SizeOffsetType<Value *> { - SizeOffsetValue() = default; + SizeOffsetValue() : SizeOffsetType(nullptr, nullptr) {} SizeOffsetValue(Value *Size, Value *Offset) : SizeOffsetType(Size, Offset) {} SizeOffsetValue(const SizeOffsetWeakTrackingVH &SOT); - bool knownSize() const { return Size != nullptr; } - bool knownOffset() const { return Offset != nullptr; } + bool knownSize() const override { return Size != nullptr; } + bool knownOffset() const override { return Offset != nullptr; } }; /// SizeOffsetWeakTrackingVH - Used by \p ObjectSizeOffsetEvaluator in a /// \p DenseMap. struct SizeOffsetWeakTrackingVH : public SizeOffsetType<WeakTrackingVH> { - SizeOffsetWeakTrackingVH() = default; + SizeOffsetWeakTrackingVH() : SizeOffsetType(nullptr, nullptr) {} SizeOffsetWeakTrackingVH(Value *Size, Value *Offset) : SizeOffsetType(Size, Offset) {} SizeOffsetWeakTrackingVH(const SizeOffsetValue &SOV) : SizeOffsetType(SOV.Size, SOV.Offset) {} - bool knownSize() const { return Size.pointsToAliveValue(); } - bool knownOffset() const { return Offset.pointsToAliveValue(); } + bool knownSize() const override { return Size.pointsToAliveValue(); } + bool knownOffset() const override { return Offset.pointsToAliveValue(); } }; /// Evaluate the size and offset of an object pointed to by a Value*. @@ -321,7 +325,7 @@ class ObjectSizeOffsetEvaluator ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, ObjectSizeOpts EvalOpts = {}); - static SizeOffsetValue unknown; + static SizeOffsetValue unknown() { return SizeOffsetValue(); } SizeOffsetValue compute(Value *V); diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp index e03f5c0977127f..bc1f3a132f0dc3 100644 --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -644,7 +644,7 @@ Value *llvm::lowerObjectSizeCall( ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, EvalOptions); SizeOffsetValue SizeOffsetPair = Eval.compute(ObjectSize->getArgOperand(0)); - if (SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown) { + if (SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown()) { IRBuilder<TargetFolder, IRBuilderCallbackInserter> Builder( Ctx, TargetFolder(DL), IRBuilderCallbackInserter([&](Instruction *I) { if (InsertedInstructions) @@ -683,8 +683,6 @@ STATISTIC(ObjectVisitorArgument, STATISTIC(ObjectVisitorLoad, "Number of load instructions with unsolved size and offset"); -SizeOffsetAPInt ObjectSizeOffsetVisitor::unknown; - APInt ObjectSizeOffsetVisitor::align(APInt Size, MaybeAlign Alignment) { if (Options.RoundToAlign && Alignment) return APInt(IntTyBits, alignTo(Size.getZExtValue(), *Alignment)); @@ -747,12 +745,12 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::computeValue(Value *V) { if (Instruction *I = dyn_cast<Instruction>(V)) { // If we have already seen this instruction, bail out. Cycles can happen in // unreachable code after constant propagation. - auto P = SeenInsts.try_emplace(I, ObjectSizeOffsetVisitor::unknown); + auto P = SeenInsts.try_emplace(I, ObjectSizeOffsetVisitor::unknown()); if (!P.second) return P.first->second; ++InstructionsVisited; if (InstructionsVisited > ObjectSizeOffsetVisitorMaxVisitInstructions) - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); SizeOffsetAPInt Res = visit(*I); // Cache the result for later visits. If we happened to visit this during // the above recursion, we would consider it unknown until now. @@ -772,7 +770,7 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::computeValue(Value *V) { LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor::compute() unhandled value: " << *V << '\n'); - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); } bool ObjectSizeOffsetVisitor::CheckedZextOrTrunc(APInt &I) { @@ -782,7 +780,7 @@ bool ObjectSizeOffsetVisitor::CheckedZextOrTrunc(APInt &I) { SizeOffsetAPInt ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) { TypeSize ElemSize = DL.getTypeAllocSize(I.getAllocatedType()); if (ElemSize.isScalable() && Options.EvalMode != ObjectSizeOpts::Mode::Min) - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); APInt Size(IntTyBits, ElemSize.getKnownMinValue()); if (!I.isArrayAllocation()) return SizeOffsetAPInt(align(Size, I.getAlign()), Zero); @@ -791,14 +789,14 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) { if (const ConstantInt *C = dyn_cast<ConstantInt>(ArraySize)) { APInt NumElems = C->getValue(); if (!CheckedZextOrTrunc(NumElems)) - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); bool Overflow; Size = Size.umul_ov(NumElems, Overflow); - return Overflow ? ObjectSizeOffsetVisitor::unknown + return Overflow ? ObjectSizeOffsetVisitor::unknown() : SizeOffsetAPInt(align(Size, I.getAlign()), Zero); } - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); } SizeOffsetAPInt ObjectSizeOffsetVisitor::visitArgument(Argument &A) { @@ -806,7 +804,7 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::visitArgument(Argument &A) { // No interprocedural analysis is done at the moment. if (!MemoryTy|| !MemoryTy->isSized()) { ++ObjectVisitorArgument; - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); } APInt Size(IntTyBits, DL.getTypeAllocSize(MemoryTy)); @@ -816,7 +814,7 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::visitArgument(Argument &A) { SizeOffsetAPInt ObjectSizeOffsetVisitor::visitCallBase(CallBase &CB) { if (std::optional<APInt> Size = getAllocSize(&CB, TLI)) return SizeOffsetAPInt(*Size, Zero); - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); } SizeOffsetAPInt @@ -829,24 +827,24 @@ ObjectSizeOffsetVisitor::visitConstantPointerNull(ConstantPointerNull &CPN) { // them on the floor, but it's unclear what we should do when a NULL from // addrspace(1) gets casted to addrspace(0) (or vice-versa). if (Options.NullIsUnknownSize || CPN.getType()->getAddressSpace()) - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); return SizeOffsetAPInt(Zero, Zero); } SizeOffsetAPInt ObjectSizeOffsetVisitor::visitExtractElementInst(ExtractElementInst &) { - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); } SizeOffsetAPInt ObjectSizeOffsetVisitor::visitExtractValueInst(ExtractValueInst &) { // Easy cases were already folded by previous passes. - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); } SizeOffsetAPInt ObjectSizeOffsetVisitor::visitGlobalAlias(GlobalAlias &GA) { if (GA.isInterposable()) - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); return computeImpl(GA.getAliasee()); } @@ -855,7 +853,7 @@ ObjectSizeOffsetVisitor::visitGlobalVariable(GlobalVariable &GV) { if (!GV.getValueType()->isSized() || GV.hasExternalWeakLinkage() || ((!GV.hasInitializer() || GV.isInterposable()) && Options.EvalMode != ObjectSizeOpts::Mode::Min)) - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); APInt Size(IntTyBits, DL.getTypeAllocSize(GV.getValueType())); return SizeOffsetAPInt(align(Size, GV.getAlign()), Zero); @@ -863,7 +861,7 @@ ObjectSizeOffsetVisitor::visitGlobalVariable(GlobalVariable &GV) { SizeOffsetAPInt ObjectSizeOffsetVisitor::visitIntToPtrInst(IntToPtrInst &) { // clueless - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); } SizeOffsetAPInt ObjectSizeOffsetVisitor::findLoadSizeOffset( @@ -877,7 +875,7 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::findLoadSizeOffset( return Where->second; auto Unknown = [&BB, &VisitedBlocks]() { - return VisitedBlocks[&BB] = ObjectSizeOffsetVisitor::unknown; + return VisitedBlocks[&BB] = ObjectSizeOffsetVisitor::unknown(); }; auto Known = [&BB, &VisitedBlocks](SizeOffsetAPInt SO) { return VisitedBlocks[&BB] = SO; @@ -979,7 +977,7 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::findLoadSizeOffset( SizeOffsetAPInt ObjectSizeOffsetVisitor::visitLoadInst(LoadInst &LI) { if (!Options.AA) { ++ObjectVisitorLoad; - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); } SmallDenseMap<BasicBlock *, SizeOffsetAPInt, 8> VisitedBlocks; @@ -996,7 +994,7 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::combineSizeOffset(SizeOffsetAPInt LHS, SizeOffsetAPInt RHS) { if (!LHS.bothKnown() || !RHS.bothKnown()) - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); switch (Options.EvalMode) { case ObjectSizeOpts::Mode::Min: @@ -1006,16 +1004,16 @@ ObjectSizeOffsetVisitor::combineSizeOffset(SizeOffsetAPInt LHS, case ObjectSizeOpts::Mode::ExactSizeFromOffset: return (getSizeWithOverflow(LHS).eq(getSizeWithOverflow(RHS))) ? LHS - : ObjectSizeOffsetVisitor::unknown; + : ObjectSizeOffsetVisitor::unknown(); case ObjectSizeOpts::Mode::ExactUnderlyingSizeAndOffset: - return LHS == RHS ? LHS : ObjectSizeOffsetVisitor::unknown; + return LHS == RHS ? LHS : ObjectSizeOffsetVisitor::unknown(); } llvm_unreachable("missing an eval mode"); } SizeOffsetAPInt ObjectSizeOffsetVisitor::visitPHINode(PHINode &PN) { if (PN.getNumIncomingValues() == 0) - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); auto IncomingValues = PN.incoming_values(); return std::accumulate(IncomingValues.begin() + 1, IncomingValues.end(), computeImpl(*IncomingValues.begin()), @@ -1036,15 +1034,13 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::visitUndefValue(UndefValue &) { SizeOffsetAPInt ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) { LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor unknown instruction:" << I << '\n'); - return ObjectSizeOffsetVisitor::unknown; + return ObjectSizeOffsetVisitor::unknown(); } // Just set these right here... SizeOffsetValue::SizeOffsetValue(const SizeOffsetWeakTrackingVH &SOT) : SizeOffsetType((Value *)SOT.Size, (Value *)SOT.Offset) {} -SizeOffsetValue ObjectSizeOffsetEvaluator::unknown; - ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator( const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, ObjectSizeOpts EvalOpts) @@ -1114,7 +1110,7 @@ SizeOffsetValue ObjectSizeOffsetEvaluator::compute_(Value *V) { // cleaned later if something fails. We also use this set to break cycles that // can occur in dead code. if (!SeenVals.insert(V).second) { - Result = ObjectSizeOffsetEvaluator::unknown; + Result = ObjectSizeOffsetEvaluator::unknown(); } else if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) { Result = visitGEPOperator(*GEP); } else if (Instruction *I = dyn_cast<Instruction>(V)) { @@ -1125,12 +1121,12 @@ SizeOffsetValue ObjectSizeOffsetEvaluator::compute_(Value *V) { isa<GlobalAlias>(V) || isa<GlobalVariable>(V)) { // Ignore values where we cannot do more than ObjectSizeVisitor. - Result = ObjectSizeOffsetEvaluator::unknown; + Result = ObjectSizeOffsetEvaluator::unknown(); } else { LLVM_DEBUG( dbgs() << "ObjectSizeOffsetEvaluator::compute() unhandled value: " << *V << '\n'); - Result = ObjectSizeOffsetEvaluator::unknown; + Result = ObjectSizeOffsetEvaluator::unknown(); } // Don't reuse CacheIt since it may be invalid at this point. @@ -1140,7 +1136,7 @@ SizeOffsetValue ObjectSizeOffsetEvaluator::compute_(Value *V) { SizeOffsetValue ObjectSizeOffsetEvaluator::visitAllocaInst(AllocaInst &I) { if (!I.getAllocatedType()->isSized()) - return ObjectSizeOffsetEvaluator::unknown; + return ObjectSizeOffsetEvaluator::unknown(); // must be a VLA assert(I.isArrayAllocation()); @@ -1162,12 +1158,12 @@ SizeOffsetValue ObjectSizeOffsetEvaluator::visitAllocaInst(AllocaInst &I) { SizeOffsetValue ObjectSizeOffsetEvaluator::visitCallBase(CallBase &CB) { std::optional<AllocFnsTy> FnData = getAllocationSize(&CB, TLI); if (!FnData) - return ObjectSizeOffsetEvaluator::unknown; + return ObjectSizeOffsetEvaluator::unknown(); // Handle strdup-like functions separately. if (FnData->AllocTy == StrDupLike) { // TODO: implement evaluation of strdup/strndup - return ObjectSizeOffsetEvaluator::unknown; + return ObjectSizeOffsetEvaluator::unknown(); } Value *FirstArg = CB.getArgOperand(FnData->FstParam); @@ -1183,18 +1179,18 @@ SizeOffsetValue ObjectSizeOffsetEvaluator::visitCallBase(CallBase &CB) { SizeOffsetValue ObjectSizeOffsetEvaluator::visitExtractElementInst(ExtractElementInst &) { - return ObjectSizeOffsetEvaluator::unknown; + return ObjectSizeOffsetEvaluator::unknown(); } SizeOffsetValue ObjectSizeOffsetEvaluator::visitExtractValueInst(ExtractValueInst &) { - return ObjectSizeOffsetEvaluator::unknown; + return ObjectSizeOffsetEvaluator::unknown(); } SizeOffsetValue ObjectSizeOffsetEvaluator::visitGEPOperator(GEPOperator &GEP) { SizeOffsetValue PtrData = compute_(GEP.getPointerOperand()); if (!PtrData.bothKnown()) - return ObjectSizeOffsetEvaluator::unknown; + return ObjectSizeOffsetEvaluator::unknown(); Value *Offset = emitGEPOffset(&Builder, DL, &GEP, /*NoAssumptions=*/true); Offset = Builder.CreateAdd(PtrData.Offset, Offset); @@ -1203,11 +1199,11 @@ SizeOffsetValue ObjectSizeOffsetEvaluator::visitGEPOperator(GEPOperator &GEP) { SizeOffsetValue ObjectSizeOffsetEvaluator::visitIntToPtrInst(IntToPtrInst &) { // clueless - return ObjectSizeOffsetEvaluator::unknown; + return ObjectSizeOffsetEvaluator::unknown(); } SizeOffsetValue ObjectSizeOffsetEvaluator::visitLoadInst(LoadInst &LI) { - return ObjectSizeOffsetEvaluator::unknown; + return ObjectSizeOffsetEvaluator::unknown(); } SizeOffsetValue ObjectSizeOffsetEvaluator::visitPHINode(PHINode &PHI) { @@ -1231,7 +1227,7 @@ SizeOffsetValue ObjectSizeOffsetEvaluator::visitPHINode(PHINode &PHI) { SizePHI->replaceAllUsesWith(PoisonValue::get(IntTy)); SizePHI->eraseFromParent(); InsertedInstructions.erase(SizePHI); - return ObjectSizeOffsetEvaluator::unknown; + return ObjectSizeOffsetEvaluator::unknown(); } SizePHI->addIncoming(EdgeData.Size, IncomingBlock); OffsetPHI->addIncoming(EdgeData.Offset, IncomingBlock); @@ -1258,7 +1254,7 @@ SizeOffsetValue ObjectSizeOffsetEvaluator::visitSelectInst(SelectInst &I) { SizeOffsetValue FalseSide = compute_(I.getFalseValue()); if (!TrueSide.bothKnown() || !FalseSide.bothKnown()) - return ObjectSizeOffsetEvaluator::unknown; + return ObjectSizeOffsetEvaluator::unknown(); if (TrueSide == FalseSide) return TrueSide; @@ -1272,5 +1268,5 @@ SizeOffsetValue ObjectSizeOffsetEvaluator::visitSelectInst(SelectInst &I) { SizeOffsetValue ObjectSizeOffsetEvaluator::visitInstruction(Instruction &I) { LLVM_DEBUG(dbgs() << "ObjectSizeOffsetEvaluator unknown instruction:" << I << '\n'); - return ObjectSizeOffsetEvaluator::unknown; + return ObjectSizeOffsetEvaluator::unknown(); } diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp index b4d83ef728bd12..cc5a4ee8c2bdf3 100644 --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -6726,7 +6726,7 @@ struct AAHeapToStackFunction final : public AAHeapToStack { ObjectSizeOpts Opts; ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, Opts); SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB); - assert(SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown && + assert(SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown() && cast<ConstantInt>(SizeOffsetPair.Offset)->isZero()); Size = SizeOffsetPair.Size; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits