Skip to content

Commit 01a103b

Browse files
[llvm] Fix __builtin_object_size interaction between Negative Offset … (#111827)
…and Select/Phi When picking a SizeOffsetAPInt through combineSizeOffset, the behavior differs if we're going to apply a constant offset that's positive or negative: If it's positive, then we need to compare the remaining bytes (i.e. Size - Offset), but if it's negative, we need to compare the preceding bytes (i.e. Offset). Fix #111709
1 parent c5eb591 commit 01a103b

File tree

4 files changed

+405
-89
lines changed

4 files changed

+405
-89
lines changed

llvm/include/llvm/Analysis/MemoryBuiltins.h

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -221,21 +221,43 @@ struct SizeOffsetAPInt : public SizeOffsetType<APInt, SizeOffsetAPInt> {
221221
static bool known(const APInt &V) { return V.getBitWidth() > 1; }
222222
};
223223

224+
/// OffsetSpan - Used internally by \p ObjectSizeOffsetVisitor. Represents a
225+
/// point in memory as a pair of allocated bytes before and after it.
226+
struct OffsetSpan {
227+
APInt Before; /// Number of allocated bytes before this point.
228+
APInt After; /// Number of allocated bytes after this point.
229+
230+
OffsetSpan() = default;
231+
OffsetSpan(APInt Before, APInt After) : Before(Before), After(After) {}
232+
233+
bool knownBefore() const { return known(Before); }
234+
bool knownAfter() const { return known(After); }
235+
bool anyKnown() const { return knownBefore() || knownAfter(); }
236+
bool bothKnown() const { return knownBefore() && knownAfter(); }
237+
238+
bool operator==(const OffsetSpan &RHS) const {
239+
return Before == RHS.Before && After == RHS.After;
240+
}
241+
bool operator!=(const OffsetSpan &RHS) const { return !(*this == RHS); }
242+
243+
static bool known(const APInt &V) { return V.getBitWidth() > 1; }
244+
};
245+
224246
/// Evaluate the size and offset of an object pointed to by a Value*
225247
/// statically. Fails if size or offset are not known at compile time.
226248
class ObjectSizeOffsetVisitor
227-
: public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetAPInt> {
249+
: public InstVisitor<ObjectSizeOffsetVisitor, OffsetSpan> {
228250
const DataLayout &DL;
229251
const TargetLibraryInfo *TLI;
230252
ObjectSizeOpts Options;
231253
unsigned IntTyBits;
232254
APInt Zero;
233-
SmallDenseMap<Instruction *, SizeOffsetAPInt, 8> SeenInsts;
255+
SmallDenseMap<Instruction *, OffsetSpan, 8> SeenInsts;
234256
unsigned InstructionsVisited;
235257

236258
APInt align(APInt Size, MaybeAlign Align);
237259

238-
static SizeOffsetAPInt unknown() { return SizeOffsetAPInt(); }
260+
static OffsetSpan unknown() { return OffsetSpan(); }
239261

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

246268
// These are "private", except they can't actually be made private. Only
247269
// compute() should be used by external users.
248-
SizeOffsetAPInt visitAllocaInst(AllocaInst &I);
249-
SizeOffsetAPInt visitArgument(Argument &A);
250-
SizeOffsetAPInt visitCallBase(CallBase &CB);
251-
SizeOffsetAPInt visitConstantPointerNull(ConstantPointerNull &);
252-
SizeOffsetAPInt visitExtractElementInst(ExtractElementInst &I);
253-
SizeOffsetAPInt visitExtractValueInst(ExtractValueInst &I);
254-
SizeOffsetAPInt visitGlobalAlias(GlobalAlias &GA);
255-
SizeOffsetAPInt visitGlobalVariable(GlobalVariable &GV);
256-
SizeOffsetAPInt visitIntToPtrInst(IntToPtrInst &);
257-
SizeOffsetAPInt visitLoadInst(LoadInst &I);
258-
SizeOffsetAPInt visitPHINode(PHINode &);
259-
SizeOffsetAPInt visitSelectInst(SelectInst &I);
260-
SizeOffsetAPInt visitUndefValue(UndefValue &);
261-
SizeOffsetAPInt visitInstruction(Instruction &I);
270+
OffsetSpan visitAllocaInst(AllocaInst &I);
271+
OffsetSpan visitArgument(Argument &A);
272+
OffsetSpan visitCallBase(CallBase &CB);
273+
OffsetSpan visitConstantPointerNull(ConstantPointerNull &);
274+
OffsetSpan visitExtractElementInst(ExtractElementInst &I);
275+
OffsetSpan visitExtractValueInst(ExtractValueInst &I);
276+
OffsetSpan visitGlobalAlias(GlobalAlias &GA);
277+
OffsetSpan visitGlobalVariable(GlobalVariable &GV);
278+
OffsetSpan visitIntToPtrInst(IntToPtrInst &);
279+
OffsetSpan visitLoadInst(LoadInst &I);
280+
OffsetSpan visitPHINode(PHINode &);
281+
OffsetSpan visitSelectInst(SelectInst &I);
282+
OffsetSpan visitUndefValue(UndefValue &);
283+
OffsetSpan visitInstruction(Instruction &I);
262284

263285
private:
264-
SizeOffsetAPInt findLoadSizeOffset(
265-
LoadInst &LoadFrom, BasicBlock &BB, BasicBlock::iterator From,
266-
SmallDenseMap<BasicBlock *, SizeOffsetAPInt, 8> &VisitedBlocks,
267-
unsigned &ScannedInstCount);
268-
SizeOffsetAPInt combineSizeOffset(SizeOffsetAPInt LHS, SizeOffsetAPInt RHS);
269-
SizeOffsetAPInt computeImpl(Value *V);
270-
SizeOffsetAPInt computeValue(Value *V);
286+
OffsetSpan
287+
findLoadOffsetRange(LoadInst &LoadFrom, BasicBlock &BB,
288+
BasicBlock::iterator From,
289+
SmallDenseMap<BasicBlock *, OffsetSpan, 8> &VisitedBlocks,
290+
unsigned &ScannedInstCount);
291+
OffsetSpan combineOffsetRange(OffsetSpan LHS, OffsetSpan RHS);
292+
OffsetSpan computeImpl(Value *V);
293+
OffsetSpan computeValue(Value *V);
271294
bool CheckedZextOrTrunc(APInt &I);
272295
};
273296

0 commit comments

Comments
 (0)