Skip to content

[llvm] Fix __builtin_object_size interaction between Negative Offset … #111827

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 47 additions & 24 deletions llvm/include/llvm/Analysis/MemoryBuiltins.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,21 +221,43 @@ struct SizeOffsetAPInt : public SizeOffsetType<APInt, SizeOffsetAPInt> {
static bool known(const APInt &V) { return V.getBitWidth() > 1; }
};

/// OffsetSpan - Used internally by \p ObjectSizeOffsetVisitor. Represents a
/// point in memory as a pair of allocated bytes before and after it.
struct OffsetSpan {
APInt Before; /// Number of allocated bytes before this point.
APInt After; /// Number of allocated bytes after this point.

OffsetSpan() = default;
OffsetSpan(APInt Before, APInt After) : Before(Before), After(After) {}

bool knownBefore() const { return known(Before); }
bool knownAfter() const { return known(After); }
bool anyKnown() const { return knownBefore() || knownAfter(); }
bool bothKnown() const { return knownBefore() && knownAfter(); }

bool operator==(const OffsetSpan &RHS) const {
return Before == RHS.Before && After == RHS.After;
}
bool operator!=(const OffsetSpan &RHS) const { return !(*this == RHS); }

static bool known(const APInt &V) { return V.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.
class ObjectSizeOffsetVisitor
: public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetAPInt> {
: public InstVisitor<ObjectSizeOffsetVisitor, OffsetSpan> {
const DataLayout &DL;
const TargetLibraryInfo *TLI;
ObjectSizeOpts Options;
unsigned IntTyBits;
APInt Zero;
SmallDenseMap<Instruction *, SizeOffsetAPInt, 8> SeenInsts;
SmallDenseMap<Instruction *, OffsetSpan, 8> SeenInsts;
unsigned InstructionsVisited;

APInt align(APInt Size, MaybeAlign Align);

static SizeOffsetAPInt unknown() { return SizeOffsetAPInt(); }
static OffsetSpan unknown() { return OffsetSpan(); }

public:
ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI,
Expand All @@ -245,29 +267,30 @@ class ObjectSizeOffsetVisitor

// These are "private", except they can't actually be made private. Only
// compute() should be used by external users.
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);
OffsetSpan visitAllocaInst(AllocaInst &I);
OffsetSpan visitArgument(Argument &A);
OffsetSpan visitCallBase(CallBase &CB);
OffsetSpan visitConstantPointerNull(ConstantPointerNull &);
OffsetSpan visitExtractElementInst(ExtractElementInst &I);
OffsetSpan visitExtractValueInst(ExtractValueInst &I);
OffsetSpan visitGlobalAlias(GlobalAlias &GA);
OffsetSpan visitGlobalVariable(GlobalVariable &GV);
OffsetSpan visitIntToPtrInst(IntToPtrInst &);
OffsetSpan visitLoadInst(LoadInst &I);
OffsetSpan visitPHINode(PHINode &);
OffsetSpan visitSelectInst(SelectInst &I);
OffsetSpan visitUndefValue(UndefValue &);
OffsetSpan visitInstruction(Instruction &I);

private:
SizeOffsetAPInt findLoadSizeOffset(
LoadInst &LoadFrom, BasicBlock &BB, BasicBlock::iterator From,
SmallDenseMap<BasicBlock *, SizeOffsetAPInt, 8> &VisitedBlocks,
unsigned &ScannedInstCount);
SizeOffsetAPInt combineSizeOffset(SizeOffsetAPInt LHS, SizeOffsetAPInt RHS);
SizeOffsetAPInt computeImpl(Value *V);
SizeOffsetAPInt computeValue(Value *V);
OffsetSpan
findLoadOffsetRange(LoadInst &LoadFrom, BasicBlock &BB,
BasicBlock::iterator From,
SmallDenseMap<BasicBlock *, OffsetSpan, 8> &VisitedBlocks,
unsigned &ScannedInstCount);
OffsetSpan combineOffsetRange(OffsetSpan LHS, OffsetSpan RHS);
OffsetSpan computeImpl(Value *V);
OffsetSpan computeValue(Value *V);
bool CheckedZextOrTrunc(APInt &I);
};

Expand Down
Loading
Loading