25
25
#include " llvm/IR/Constants.h"
26
26
#include " llvm/IR/DataLayout.h"
27
27
#include " llvm/IR/DerivedTypes.h"
28
+ #include " llvm/IR/Dominators.h"
28
29
#include " llvm/IR/Function.h"
29
30
#include " llvm/IR/GlobalAlias.h"
30
31
#include " llvm/IR/GlobalVariable.h"
@@ -590,19 +591,28 @@ Value *llvm::lowerObjectSizeCall(IntrinsicInst *ObjectSize,
590
591
const TargetLibraryInfo *TLI,
591
592
bool MustSucceed) {
592
593
return lowerObjectSizeCall (ObjectSize, DL, TLI, /* AAResults=*/ nullptr ,
593
- MustSucceed);
594
+ /* DT= */ nullptr , MustSucceed);
594
595
}
595
596
596
597
Value *llvm::lowerObjectSizeCall (
597
598
IntrinsicInst *ObjectSize, const DataLayout &DL,
598
599
const TargetLibraryInfo *TLI, AAResults *AA, bool MustSucceed,
599
600
SmallVectorImpl<Instruction *> *InsertedInstructions) {
601
+ return lowerObjectSizeCall (ObjectSize, DL, TLI, AA, /* DT=*/ nullptr ,
602
+ MustSucceed, InsertedInstructions);
603
+ }
604
+
605
+ Value *llvm::lowerObjectSizeCall (
606
+ IntrinsicInst *ObjectSize, const DataLayout &DL,
607
+ const TargetLibraryInfo *TLI, AAResults *AA, DominatorTree *DT,
608
+ bool MustSucceed, SmallVectorImpl<Instruction *> *InsertedInstructions) {
600
609
assert (ObjectSize->getIntrinsicID () == Intrinsic::objectsize &&
601
610
" ObjectSize must be a call to llvm.objectsize!" );
602
611
603
612
bool MaxVal = cast<ConstantInt>(ObjectSize->getArgOperand (1 ))->isZero ();
604
613
ObjectSizeOpts EvalOptions;
605
614
EvalOptions.AA = AA;
615
+ EvalOptions.DT = DT;
606
616
607
617
// Unless we have to fold this to something, try to be as accurate as
608
618
// possible.
@@ -716,7 +726,6 @@ OffsetSpan ObjectSizeOffsetVisitor::computeImpl(Value *V) {
716
726
// value that is passed to computeImpl.
717
727
IntTyBits = DL.getIndexTypeSizeInBits (V->getType ());
718
728
Zero = APInt::getZero (IntTyBits);
719
-
720
729
OffsetSpan ORT = computeValue (V);
721
730
722
731
bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits;
@@ -794,6 +803,26 @@ OffsetSpan ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) {
794
803
Size = Size.umul_ov (NumElems, Overflow);
795
804
return Overflow ? ObjectSizeOffsetVisitor::unknown ()
796
805
: OffsetSpan (Zero, align (Size, I.getAlign ()));
806
+ } else {
807
+ ConstantRange CR =
808
+ computeConstantRange (ArraySize, /* ForSigned*/ false ,
809
+ /* UseInstrInfo*/ true , /* AC=*/ nullptr ,
810
+ /* CtxtI=*/ &I, /* DT=*/ Options.DT );
811
+ if (CR.isFullSet ())
812
+ return ObjectSizeOffsetVisitor::unknown ();
813
+ APInt Bound;
814
+ if (Options.EvalMode == ObjectSizeOpts::Mode::Max) {
815
+ Bound = CR.getUnsignedMax ();
816
+ // Upper bound actually unknown.
817
+ if (Bound.isMaxValue ())
818
+ return ObjectSizeOffsetVisitor::unknown ();
819
+ } else {
820
+ Bound = CR.getUnsignedMin ();
821
+ // Lower bound actually unknown.
822
+ if (Bound.isMinValue ())
823
+ return ObjectSizeOffsetVisitor::unknown ();
824
+ }
825
+ return OffsetSpan (Zero, align (Bound, I.getAlign ()));
797
826
}
798
827
return ObjectSizeOffsetVisitor::unknown ();
799
828
}
@@ -811,7 +840,32 @@ OffsetSpan ObjectSizeOffsetVisitor::visitArgument(Argument &A) {
811
840
}
812
841
813
842
OffsetSpan ObjectSizeOffsetVisitor::visitCallBase (CallBase &CB) {
814
- if (std::optional<APInt> Size = getAllocSize (&CB, TLI))
843
+ if (std::optional<APInt> Size =
844
+ getAllocSize (&CB, TLI, [&CB, this ](const Value *V) -> const Value * {
845
+ if (!V->getType ()->isIntegerTy ())
846
+ return V;
847
+ if (isa<ConstantInt>(V))
848
+ return V;
849
+ ConstantRange CR = computeConstantRange (
850
+ V, /* ForSigned*/ false , /* UseInstrInfo*/ true , /* AC=*/ nullptr ,
851
+ /* CtxtI=*/ &CB, /* DT=*/ Options.DT );
852
+ if (CR.isFullSet ())
853
+ return V;
854
+
855
+ APInt Bound;
856
+ if (Options.EvalMode == ObjectSizeOpts::Mode::Max) {
857
+ Bound = CR.getUnsignedMax ();
858
+ // Upper bound actually unknown.
859
+ if (Bound.isMaxValue ())
860
+ return V;
861
+ } else {
862
+ Bound = CR.getUnsignedMin ();
863
+ // Lower bound actually unknown.
864
+ if (Bound.isMinValue ())
865
+ return V;
866
+ }
867
+ return ConstantInt::get (V->getType (), Bound);
868
+ }))
815
869
return OffsetSpan (Zero, *Size);
816
870
return ObjectSizeOffsetVisitor::unknown ();
817
871
}
@@ -856,6 +910,48 @@ OffsetSpan ObjectSizeOffsetVisitor::visitGlobalVariable(GlobalVariable &GV) {
856
910
return OffsetSpan (Zero, align (Size, GV.getAlign ()));
857
911
}
858
912
913
+ OffsetSpan ObjectSizeOffsetVisitor::visitGetElementPtr (GetElementPtrInst &GEP) {
914
+ OffsetSpan PtrData = computeImpl (GEP.getPointerOperand ());
915
+ if (!PtrData.bothKnown ())
916
+ return ObjectSizeOffsetVisitor::unknown ();
917
+
918
+ if (Options.EvalMode == ObjectSizeOpts::Mode::Min ||
919
+ Options.EvalMode == ObjectSizeOpts::Mode::Max) {
920
+ unsigned BitWidth = PtrData.After .getBitWidth ();
921
+ APInt ConstantOffset = Zero;
922
+ SmallMapVector<Value *, APInt, 4 > VariableOffsets;
923
+ if (!GEP.collectOffset (DL, BitWidth, VariableOffsets, ConstantOffset))
924
+ return ObjectSizeOffsetVisitor::unknown ();
925
+
926
+ ConstantRange AccumulatedRange = ConstantOffset;
927
+ for (auto const &VO : VariableOffsets) {
928
+ ConstantRange CR = computeConstantRange (
929
+ VO.first , /* ForSigned*/ true , /* UseInstrInfo*/ true , /* AC=*/ nullptr ,
930
+ /* CtxtI=*/ &GEP, /* DT=*/ Options.DT );
931
+ if (CR.isFullSet ())
932
+ return ObjectSizeOffsetVisitor::unknown ();
933
+
934
+ AccumulatedRange = AccumulatedRange.add (CR.multiply (VO.second ));
935
+ }
936
+
937
+ APInt Bound;
938
+ if (Options.EvalMode == ObjectSizeOpts::Mode::Min) {
939
+ Bound = AccumulatedRange.getSignedMax ();
940
+ // Upper bound actually unknown.
941
+ if (Bound.isMaxSignedValue ())
942
+ return ObjectSizeOffsetVisitor::unknown ();
943
+ } else {
944
+ Bound = AccumulatedRange.getSignedMin ();
945
+ // Lower bound actually unknown.
946
+ if (Bound.isMinSignedValue ())
947
+ return ObjectSizeOffsetVisitor::unknown ();
948
+ }
949
+
950
+ return {PtrData.Before + Bound, PtrData.After - Bound};
951
+ }
952
+ return ObjectSizeOffsetVisitor::unknown ();
953
+ }
954
+
859
955
OffsetSpan ObjectSizeOffsetVisitor::visitIntToPtrInst (IntToPtrInst &) {
860
956
// clueless
861
957
return ObjectSizeOffsetVisitor::unknown ();
0 commit comments