fix PR17635: false positive with packed structures
LLVM optimizers may widen accesses to packed structures that overflow the structure itself, but should be in bounds up to the alignment of the object llvm-svn: 193317
This commit is contained in:
parent
c5cae0f20c
commit
340b0463e6
|
@ -228,6 +228,7 @@ class ObjectSizeOffsetEvaluator
|
||||||
Value *Zero;
|
Value *Zero;
|
||||||
CacheMapTy CacheMap;
|
CacheMapTy CacheMap;
|
||||||
PtrSetTy SeenVals;
|
PtrSetTy SeenVals;
|
||||||
|
bool RoundToAlign;
|
||||||
|
|
||||||
SizeOffsetEvalType unknown() {
|
SizeOffsetEvalType unknown() {
|
||||||
return std::make_pair((Value*)0, (Value*)0);
|
return std::make_pair((Value*)0, (Value*)0);
|
||||||
|
@ -236,7 +237,7 @@ class ObjectSizeOffsetEvaluator
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ObjectSizeOffsetEvaluator(const DataLayout *DL, const TargetLibraryInfo *TLI,
|
ObjectSizeOffsetEvaluator(const DataLayout *DL, const TargetLibraryInfo *TLI,
|
||||||
LLVMContext &Context);
|
LLVMContext &Context, bool RoundToAlign = false);
|
||||||
SizeOffsetEvalType compute(Value *V);
|
SizeOffsetEvalType compute(Value *V);
|
||||||
|
|
||||||
bool knownSize(SizeOffsetEvalType SizeOffset) {
|
bool knownSize(SizeOffsetEvalType SizeOffset) {
|
||||||
|
|
|
@ -588,8 +588,10 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) {
|
||||||
|
|
||||||
ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator(const DataLayout *DL,
|
ObjectSizeOffsetEvaluator::ObjectSizeOffsetEvaluator(const DataLayout *DL,
|
||||||
const TargetLibraryInfo *TLI,
|
const TargetLibraryInfo *TLI,
|
||||||
LLVMContext &Context)
|
LLVMContext &Context,
|
||||||
: DL(DL), TLI(TLI), Context(Context), Builder(Context, TargetFolder(DL)) {
|
bool RoundToAlign)
|
||||||
|
: DL(DL), TLI(TLI), Context(Context), Builder(Context, TargetFolder(DL)),
|
||||||
|
RoundToAlign(RoundToAlign) {
|
||||||
IntTy = DL->getIntPtrType(Context);
|
IntTy = DL->getIntPtrType(Context);
|
||||||
Zero = ConstantInt::get(IntTy, 0);
|
Zero = ConstantInt::get(IntTy, 0);
|
||||||
}
|
}
|
||||||
|
@ -614,7 +616,7 @@ SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute(Value *V) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) {
|
SizeOffsetEvalType ObjectSizeOffsetEvaluator::compute_(Value *V) {
|
||||||
ObjectSizeOffsetVisitor Visitor(DL, TLI, Context);
|
ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, RoundToAlign);
|
||||||
SizeOffsetType Const = Visitor.compute(V);
|
SizeOffsetType Const = Visitor.compute(V);
|
||||||
if (Visitor.bothKnown(Const))
|
if (Visitor.bothKnown(Const))
|
||||||
return std::make_pair(ConstantInt::get(Context, Const.first),
|
return std::make_pair(ConstantInt::get(Context, Const.first),
|
||||||
|
|
|
@ -172,7 +172,8 @@ bool BoundsChecking::runOnFunction(Function &F) {
|
||||||
TrapBB = 0;
|
TrapBB = 0;
|
||||||
BuilderTy TheBuilder(F.getContext(), TargetFolder(TD));
|
BuilderTy TheBuilder(F.getContext(), TargetFolder(TD));
|
||||||
Builder = &TheBuilder;
|
Builder = &TheBuilder;
|
||||||
ObjectSizeOffsetEvaluator TheObjSizeEval(TD, TLI, F.getContext());
|
ObjectSizeOffsetEvaluator TheObjSizeEval(TD, TLI, F.getContext(),
|
||||||
|
/*RoundToAlign=*/true);
|
||||||
ObjSizeEval = &TheObjSizeEval;
|
ObjSizeEval = &TheObjSizeEval;
|
||||||
|
|
||||||
// check HANDLE_MEMORY_INST in include/llvm/Instruction.def for memory
|
// check HANDLE_MEMORY_INST in include/llvm/Instruction.def for memory
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
; RUN: opt < %s -bounds-checking -S | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
|
||||||
|
|
||||||
|
%struct.s2_packed = type <{ i64, i32, i32, i32, i16, i8 }>
|
||||||
|
|
||||||
|
; CHECK-LABEL: @f
|
||||||
|
; CHECK-NOT: trap
|
||||||
|
define i16 @f() {
|
||||||
|
entry:
|
||||||
|
%packed1 = alloca %struct.s2_packed, align 8
|
||||||
|
%gep = getelementptr inbounds %struct.s2_packed* %packed1, i32 0, i32 4
|
||||||
|
%ptr = bitcast i16* %gep to i32*
|
||||||
|
%val = load i32* %ptr, align 4
|
||||||
|
%valt = trunc i32 %val to i16
|
||||||
|
ret i16 %valt
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @f
|
||||||
|
; CHECK: call void @llvm.trap()
|
||||||
|
define i16 @f2() {
|
||||||
|
entry:
|
||||||
|
%packed1 = alloca %struct.s2_packed, align 8
|
||||||
|
%gep = getelementptr inbounds %struct.s2_packed* %packed1, i32 0, i32 4
|
||||||
|
%ptr = bitcast i16* %gep to i48*
|
||||||
|
%val = load i48* %ptr, align 4
|
||||||
|
%valt = trunc i48 %val to i16
|
||||||
|
ret i16 %valt
|
||||||
|
}
|
Loading…
Reference in New Issue