Skip to content

Commit dee812a

Browse files
committed
[StackSafety] Fix union which produces wrapped sets
1 parent a6feeb1 commit dee812a

File tree

2 files changed

+56
-18
lines changed

2 files changed

+56
-18
lines changed

llvm/lib/Analysis/StackSafetyAnalysis.cpp

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,32 @@ static cl::opt<bool> StackSafetyRun("stack-safety-run", cl::init(false),
6161

6262
namespace {
6363

64+
// Check if we should bailout for such ranges.
65+
bool isUnsafe(const ConstantRange &R) {
66+
return R.isEmptySet() || R.isFullSet() || R.isUpperSignWrapped();
67+
}
68+
69+
ConstantRange addOverflowNever(const ConstantRange &L, const ConstantRange &R) {
70+
assert(!L.isSignWrappedSet());
71+
assert(!R.isSignWrappedSet());
72+
if (L.signedAddMayOverflow(R) !=
73+
ConstantRange::OverflowResult::NeverOverflows)
74+
return ConstantRange::getFull(L.getBitWidth());
75+
ConstantRange Result = L.add(R);
76+
assert(!Result.isSignWrappedSet());
77+
return Result;
78+
}
79+
80+
ConstantRange unionNoWrap(const ConstantRange &L, const ConstantRange &R) {
81+
assert(!L.isSignWrappedSet());
82+
assert(!R.isSignWrappedSet());
83+
auto Result = L.unionWith(R);
84+
// Two non-wrapped sets can produce wrapped.
85+
if (Result.isSignWrappedSet())
86+
Result = ConstantRange::getFull(Result.getBitWidth());
87+
return Result;
88+
}
89+
6490
/// Describes use of address in as a function call argument.
6591
template <typename CalleeTy> struct CallInfo {
6692
/// Function being called.
@@ -93,11 +119,7 @@ template <typename CalleeTy> struct UseInfo {
93119

94120
UseInfo(unsigned PointerSize) : Range{PointerSize, false} {}
95121

96-
void updateRange(const ConstantRange &R) {
97-
assert(!R.isUpperSignWrapped());
98-
Range = Range.unionWith(R);
99-
assert(!Range.isUpperSignWrapped());
100-
}
122+
void updateRange(const ConstantRange &R) { Range = unionNoWrap(Range, R); }
101123
};
102124

103125
template <typename CalleeTy>
@@ -108,18 +130,6 @@ raw_ostream &operator<<(raw_ostream &OS, const UseInfo<CalleeTy> &U) {
108130
return OS;
109131
}
110132

111-
// Check if we should bailout for such ranges.
112-
bool isUnsafe(const ConstantRange &R) {
113-
return R.isEmptySet() || R.isFullSet() || R.isUpperSignWrapped();
114-
}
115-
116-
ConstantRange addOverflowNever(const ConstantRange &L, const ConstantRange &R) {
117-
if (L.signedAddMayOverflow(R) !=
118-
ConstantRange::OverflowResult::NeverOverflows)
119-
return ConstantRange(L.getBitWidth(), true);
120-
return L.add(R);
121-
}
122-
123133
/// Calculate the allocation size of a given alloca. Returns empty range
124134
// in case of confution.
125135
ConstantRange getStaticAllocaSizeRange(const AllocaInst &AI) {
@@ -515,7 +525,7 @@ bool StackSafetyDataFlowAnalysis<CalleeTy>::updateOneUse(UseInfo<CalleeTy> &US,
515525
if (UpdateToFullSet)
516526
US.Range = UnknownRange;
517527
else
518-
US.Range = US.Range.unionWith(CalleeRange);
528+
US.updateRange(CalleeRange);
519529
}
520530
}
521531
return Changed;

llvm/test/Analysis/StackSafetyAnalysis/local.ll

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ target triple = "x86_64-unknown-linux-gnu"
1111
declare void @llvm.memset.p0i8.i32(i8* %dest, i8 %val, i32 %len, i1 %isvolatile)
1212
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
1313
declare void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
14+
declare void @llvm.memset.p0i8.i64(i8* %dest, i8 %val, i64 %len, i1 %isvolatile)
1415

1516
; Address leaked.
1617
define void @LeakAddress() {
@@ -81,6 +82,33 @@ entry:
8182
ret void
8283
}
8384

85+
define dso_local void @WriteMinMax(i8* %p) {
86+
; CHECK-LABEL: @WriteMinMax{{$}}
87+
; CHECK-NEXT: args uses:
88+
; CHECK-NEXT: p[]: full-set
89+
; CHECK-NEXT: allocas uses:
90+
; CHECK-EMPTY:
91+
entry:
92+
%p1 = getelementptr i8, i8* %p, i64 9223372036854775805
93+
store i8 0, i8* %p1, align 1
94+
%p2 = getelementptr i8, i8* %p, i64 -9223372036854775805
95+
store i8 0, i8* %p2, align 1
96+
ret void
97+
}
98+
99+
define dso_local void @WriteMax(i8* %p) {
100+
; CHECK-LABEL: @WriteMax{{$}}
101+
; CHECK-NEXT: args uses:
102+
; CHECK-NEXT: p[]: [-9223372036854775807,9223372036854775806)
103+
; CHECK-NEXT: allocas uses:
104+
; CHECK-EMPTY:
105+
entry:
106+
call void @llvm.memset.p0i8.i64(i8* %p, i8 1, i64 9223372036854775806, i1 0)
107+
%p2 = getelementptr i8, i8* %p, i64 -9223372036854775807
108+
call void @llvm.memset.p0i8.i64(i8* %p2, i8 1, i64 9223372036854775806, i1 0)
109+
ret void
110+
}
111+
84112
define void @StoreOutOfBounds() {
85113
; CHECK-LABEL: @StoreOutOfBounds dso_preemptable{{$}}
86114
; CHECK-NEXT: args uses:

0 commit comments

Comments
 (0)