forked from OSchip/llvm-project
[StackSafety] Fix union which produces wrapped sets
This commit is contained in:
parent
a6feeb1c6b
commit
dee812a297
|
@ -61,6 +61,32 @@ static cl::opt<bool> StackSafetyRun("stack-safety-run", cl::init(false),
|
|||
|
||||
namespace {
|
||||
|
||||
// Check if we should bailout for such ranges.
|
||||
bool isUnsafe(const ConstantRange &R) {
|
||||
return R.isEmptySet() || R.isFullSet() || R.isUpperSignWrapped();
|
||||
}
|
||||
|
||||
ConstantRange addOverflowNever(const ConstantRange &L, const ConstantRange &R) {
|
||||
assert(!L.isSignWrappedSet());
|
||||
assert(!R.isSignWrappedSet());
|
||||
if (L.signedAddMayOverflow(R) !=
|
||||
ConstantRange::OverflowResult::NeverOverflows)
|
||||
return ConstantRange::getFull(L.getBitWidth());
|
||||
ConstantRange Result = L.add(R);
|
||||
assert(!Result.isSignWrappedSet());
|
||||
return Result;
|
||||
}
|
||||
|
||||
ConstantRange unionNoWrap(const ConstantRange &L, const ConstantRange &R) {
|
||||
assert(!L.isSignWrappedSet());
|
||||
assert(!R.isSignWrappedSet());
|
||||
auto Result = L.unionWith(R);
|
||||
// Two non-wrapped sets can produce wrapped.
|
||||
if (Result.isSignWrappedSet())
|
||||
Result = ConstantRange::getFull(Result.getBitWidth());
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// Describes use of address in as a function call argument.
|
||||
template <typename CalleeTy> struct CallInfo {
|
||||
/// Function being called.
|
||||
|
@ -93,11 +119,7 @@ template <typename CalleeTy> struct UseInfo {
|
|||
|
||||
UseInfo(unsigned PointerSize) : Range{PointerSize, false} {}
|
||||
|
||||
void updateRange(const ConstantRange &R) {
|
||||
assert(!R.isUpperSignWrapped());
|
||||
Range = Range.unionWith(R);
|
||||
assert(!Range.isUpperSignWrapped());
|
||||
}
|
||||
void updateRange(const ConstantRange &R) { Range = unionNoWrap(Range, R); }
|
||||
};
|
||||
|
||||
template <typename CalleeTy>
|
||||
|
@ -108,18 +130,6 @@ raw_ostream &operator<<(raw_ostream &OS, const UseInfo<CalleeTy> &U) {
|
|||
return OS;
|
||||
}
|
||||
|
||||
// Check if we should bailout for such ranges.
|
||||
bool isUnsafe(const ConstantRange &R) {
|
||||
return R.isEmptySet() || R.isFullSet() || R.isUpperSignWrapped();
|
||||
}
|
||||
|
||||
ConstantRange addOverflowNever(const ConstantRange &L, const ConstantRange &R) {
|
||||
if (L.signedAddMayOverflow(R) !=
|
||||
ConstantRange::OverflowResult::NeverOverflows)
|
||||
return ConstantRange(L.getBitWidth(), true);
|
||||
return L.add(R);
|
||||
}
|
||||
|
||||
/// Calculate the allocation size of a given alloca. Returns empty range
|
||||
// in case of confution.
|
||||
ConstantRange getStaticAllocaSizeRange(const AllocaInst &AI) {
|
||||
|
@ -515,7 +525,7 @@ bool StackSafetyDataFlowAnalysis<CalleeTy>::updateOneUse(UseInfo<CalleeTy> &US,
|
|||
if (UpdateToFullSet)
|
||||
US.Range = UnknownRange;
|
||||
else
|
||||
US.Range = US.Range.unionWith(CalleeRange);
|
||||
US.updateRange(CalleeRange);
|
||||
}
|
||||
}
|
||||
return Changed;
|
||||
|
|
|
@ -11,6 +11,7 @@ target triple = "x86_64-unknown-linux-gnu"
|
|||
declare void @llvm.memset.p0i8.i32(i8* %dest, i8 %val, i32 %len, i1 %isvolatile)
|
||||
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
|
||||
declare void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
|
||||
declare void @llvm.memset.p0i8.i64(i8* %dest, i8 %val, i64 %len, i1 %isvolatile)
|
||||
|
||||
; Address leaked.
|
||||
define void @LeakAddress() {
|
||||
|
@ -81,6 +82,33 @@ entry:
|
|||
ret void
|
||||
}
|
||||
|
||||
define dso_local void @WriteMinMax(i8* %p) {
|
||||
; CHECK-LABEL: @WriteMinMax{{$}}
|
||||
; CHECK-NEXT: args uses:
|
||||
; CHECK-NEXT: p[]: full-set
|
||||
; CHECK-NEXT: allocas uses:
|
||||
; CHECK-EMPTY:
|
||||
entry:
|
||||
%p1 = getelementptr i8, i8* %p, i64 9223372036854775805
|
||||
store i8 0, i8* %p1, align 1
|
||||
%p2 = getelementptr i8, i8* %p, i64 -9223372036854775805
|
||||
store i8 0, i8* %p2, align 1
|
||||
ret void
|
||||
}
|
||||
|
||||
define dso_local void @WriteMax(i8* %p) {
|
||||
; CHECK-LABEL: @WriteMax{{$}}
|
||||
; CHECK-NEXT: args uses:
|
||||
; CHECK-NEXT: p[]: [-9223372036854775807,9223372036854775806)
|
||||
; CHECK-NEXT: allocas uses:
|
||||
; CHECK-EMPTY:
|
||||
entry:
|
||||
call void @llvm.memset.p0i8.i64(i8* %p, i8 1, i64 9223372036854775806, i1 0)
|
||||
%p2 = getelementptr i8, i8* %p, i64 -9223372036854775807
|
||||
call void @llvm.memset.p0i8.i64(i8* %p2, i8 1, i64 9223372036854775806, i1 0)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @StoreOutOfBounds() {
|
||||
; CHECK-LABEL: @StoreOutOfBounds dso_preemptable{{$}}
|
||||
; CHECK-NEXT: args uses:
|
||||
|
|
Loading…
Reference in New Issue