[Lldb-commits] [lldb] [llvm] [libc] [mlir] [clang] [NFC][ObjectSizeOffset] Use classes instead of std::pair (PR #76882)
Bill Wendling via lldb-commits
lldb-commits at lists.llvm.org
Fri Jan 5 18:01:13 PST 2024
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 <morbo at google.com>
Date: Wed, 3 Jan 2024 13:22:37 -0800
Subject: [PATCH 1/9] [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 <morbo at google.com>
Date: Wed, 3 Jan 2024 16:19:16 -0800
Subject: [PATCH 2/9] 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 <morbo at google.com>
Date: Wed, 3 Jan 2024 16:22:03 -0800
Subject: [PATCH 3/9] 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 <morbo at google.com>
Date: Wed, 3 Jan 2024 17:45:48 -0800
Subject: [PATCH 4/9] 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 <morbo at google.com>
Date: Thu, 4 Jan 2024 00:08:47 -0800
Subject: [PATCH 5/9] 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 <morbo at google.com>
Date: Thu, 4 Jan 2024 04:37:59 -0800
Subject: [PATCH 6/9] 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;
}
>From e777bceac315b602c1b1e284ee8d6a7e5af505c7 Mon Sep 17 00:00:00 2001
From: Bill Wendling <morbo at google.com>
Date: Thu, 4 Jan 2024 11:44:24 -0800
Subject: [PATCH 7/9] Use CRTP instead of virtual functions.
---
llvm/include/llvm/Analysis/MemoryBuiltins.h | 52 ++++++++++++---------
1 file changed, 30 insertions(+), 22 deletions(-)
diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h
index 2849e2da545a68..85974f7b5660e8 100644
--- a/llvm/include/llvm/Analysis/MemoryBuiltins.h
+++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h
@@ -190,38 +190,37 @@ 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, class C> class SizeOffsetType {
+public:
T Size;
T Offset;
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 anyKnown() const { return knownSize() || knownOffset(); }
- bool bothKnown() const { return knownSize() && knownOffset(); }
+ bool anyKnown() const { return C::known(Size) || C::known(Offset); }
+ bool bothKnown() const { return C::known(Size) && C::known(Offset); }
- bool operator==(const SizeOffsetType<T> &RHS) const {
- // 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, C> &RHS) const {
+ return Size == RHS.Size && Offset == RHS.Offset;
}
- bool operator!=(const SizeOffsetType<T> &RHS) const {
+ bool operator!=(const SizeOffsetType<T, C> &RHS) const {
return !(*this == RHS);
}
};
/// SizeOffsetAPInt - Used by \p ObjectSizeOffsetVisitor, which works with
/// \p APInts.
-struct SizeOffsetAPInt : public SizeOffsetType<APInt> {
+class SizeOffsetAPInt : public SizeOffsetType<APInt, SizeOffsetAPInt> {
+ friend class SizeOffsetType;
+ static bool known(APInt V) { return V.getBitWidth() > 1; }
+
+public:
SizeOffsetAPInt() = default;
SizeOffsetAPInt(APInt Size, APInt Offset) : SizeOffsetType(Size, Offset) {}
- bool knownSize() const override { return Size.getBitWidth() > 1; }
- bool knownOffset() const override { return Offset.getBitWidth() > 1; }
+ bool knownSize() const { return SizeOffsetAPInt::known(Size); }
+ bool knownOffset() const { return SizeOffsetAPInt::known(Offset); }
};
/// Evaluate the size and offset of an object pointed to by a Value*
@@ -276,27 +275,36 @@ class ObjectSizeOffsetVisitor
/// SizeOffsetValue - Used by \p ObjectSizeOffsetEvaluator, which works with
/// \p Values.
-struct SizeOffsetWeakTrackingVH;
-struct SizeOffsetValue : public SizeOffsetType<Value *> {
+class SizeOffsetWeakTrackingVH;
+class SizeOffsetValue : public SizeOffsetType<Value *, SizeOffsetValue> {
+ friend class SizeOffsetType;
+ static bool known(Value *V) { return V != nullptr; }
+
+public:
SizeOffsetValue() : SizeOffsetType(nullptr, nullptr) {}
SizeOffsetValue(Value *Size, Value *Offset) : SizeOffsetType(Size, Offset) {}
SizeOffsetValue(const SizeOffsetWeakTrackingVH &SOT);
- bool knownSize() const override { return Size != nullptr; }
- bool knownOffset() const override { return Offset != nullptr; }
+ bool knownSize() const { return SizeOffsetValue::known(Size); }
+ bool knownOffset() const { return SizeOffsetValue::known(Offset); }
};
/// SizeOffsetWeakTrackingVH - Used by \p ObjectSizeOffsetEvaluator in a
/// \p DenseMap.
-struct SizeOffsetWeakTrackingVH : public SizeOffsetType<WeakTrackingVH> {
+class SizeOffsetWeakTrackingVH
+ : public SizeOffsetType<WeakTrackingVH, SizeOffsetWeakTrackingVH> {
+ friend class SizeOffsetType;
+ static bool known(WeakTrackingVH V) { return V.pointsToAliveValue(); }
+
+public:
SizeOffsetWeakTrackingVH() : SizeOffsetType(nullptr, nullptr) {}
SizeOffsetWeakTrackingVH(Value *Size, Value *Offset)
: SizeOffsetType(Size, Offset) {}
SizeOffsetWeakTrackingVH(const SizeOffsetValue &SOV)
: SizeOffsetType(SOV.Size, SOV.Offset) {}
- bool knownSize() const override { return Size.pointsToAliveValue(); }
- bool knownOffset() const override { return Offset.pointsToAliveValue(); }
+ bool knownSize() const { return SizeOffsetWeakTrackingVH::known(Size); }
+ bool knownOffset() const { return SizeOffsetWeakTrackingVH::known(Offset); }
};
/// Evaluate the size and offset of an object pointed to by a Value*.
>From 3cc7bd5eaacae2a65c00c26aefc1d360e486be5a Mon Sep 17 00:00:00 2001
From: Bill Wendling <morbo at google.com>
Date: Thu, 4 Jan 2024 15:14:50 -0800
Subject: [PATCH 8/9] Remove needless cast.
---
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 bc1f3a132f0dc3..46a7a921d86d3d 100644
--- a/llvm/lib/Analysis/MemoryBuiltins.cpp
+++ b/llvm/lib/Analysis/MemoryBuiltins.cpp
@@ -1039,7 +1039,7 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) {
// Just set these right here...
SizeOffsetValue::SizeOffsetValue(const SizeOffsetWeakTrackingVH &SOT)
- : SizeOffsetType((Value *)SOT.Size, (Value *)SOT.Offset) {}
+ : SizeOffsetType(SOT.Size, SOT.Offset) {}
ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator(
const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context,
>From 19cd2c97844d392d1634b597868077a6bbed2876 Mon Sep 17 00:00:00 2001
From: Bill Wendling <morbo at google.com>
Date: Fri, 5 Jan 2024 18:00:47 -0800
Subject: [PATCH 9/9] Move known{Size,Offset} into the base class.
---
llvm/include/llvm/Analysis/MemoryBuiltins.h | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h
index 85974f7b5660e8..d080a5956a4d8b 100644
--- a/llvm/include/llvm/Analysis/MemoryBuiltins.h
+++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h
@@ -198,8 +198,10 @@ template <typename T, class C> class SizeOffsetType {
SizeOffsetType() = default;
SizeOffsetType(T Size, T Offset) : Size(Size), Offset(Offset) {}
- bool anyKnown() const { return C::known(Size) || C::known(Offset); }
- bool bothKnown() const { return C::known(Size) && C::known(Offset); }
+ bool knownSize() const { return C::known(Size); }
+ bool knownOffset() const { return C::known(Offset); }
+ bool anyKnown() const { return knownSize() || knownOffset(); }
+ bool bothKnown() const { return knownSize() && knownOffset(); }
bool operator==(const SizeOffsetType<T, C> &RHS) const {
return Size == RHS.Size && Offset == RHS.Offset;
@@ -218,9 +220,6 @@ class SizeOffsetAPInt : public SizeOffsetType<APInt, SizeOffsetAPInt> {
public:
SizeOffsetAPInt() = default;
SizeOffsetAPInt(APInt Size, APInt Offset) : SizeOffsetType(Size, Offset) {}
-
- bool knownSize() const { return SizeOffsetAPInt::known(Size); }
- bool knownOffset() const { return SizeOffsetAPInt::known(Offset); }
};
/// Evaluate the size and offset of an object pointed to by a Value*
@@ -284,9 +283,6 @@ class SizeOffsetValue : public SizeOffsetType<Value *, SizeOffsetValue> {
SizeOffsetValue() : SizeOffsetType(nullptr, nullptr) {}
SizeOffsetValue(Value *Size, Value *Offset) : SizeOffsetType(Size, Offset) {}
SizeOffsetValue(const SizeOffsetWeakTrackingVH &SOT);
-
- bool knownSize() const { return SizeOffsetValue::known(Size); }
- bool knownOffset() const { return SizeOffsetValue::known(Offset); }
};
/// SizeOffsetWeakTrackingVH - Used by \p ObjectSizeOffsetEvaluator in a
@@ -302,9 +298,6 @@ class SizeOffsetWeakTrackingVH
: SizeOffsetType(Size, Offset) {}
SizeOffsetWeakTrackingVH(const SizeOffsetValue &SOV)
: SizeOffsetType(SOV.Size, SOV.Offset) {}
-
- bool knownSize() const { return SizeOffsetWeakTrackingVH::known(Size); }
- bool knownOffset() const { return SizeOffsetWeakTrackingVH::known(Offset); }
};
/// Evaluate the size and offset of an object pointed to by a Value*.
More information about the lldb-commits
mailing list