Skip to content

Commit 3e39820

Browse files
authored
[sanitizer][NFCI] Add ASan/HWASan regression tests for @llvm.coro.id with promise allocas (#154894)
ASan and HWASan did not play nicely with @llvm.coro.id's that had non-null promises: rewriting the promise alloca violated the assumptions of the coro-early pass (see #154830 (comment) for analysis). Although this issue has been worked around already in ASan and HWASan (somewhat crudely, by disabling instrumentation for the entire presplit function; #99415, #154803), there is no test coverage to check the compiler would crash without the workarounds, if coro-early was run after ASan/HWASan (the existing `split-coro.ll` runs the passes in the opposite order and checks that ASan skips instrumentation). This patch adds simple tests (which succeed with the existing workarounds, and would crash without). These will be useful for tracking progress towards better workarounds.
1 parent 78ed417 commit 3e39820

File tree

2 files changed

+252
-0
lines changed

2 files changed

+252
-0
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
; RUN: opt < %s -passes='asan,coro-early' -S
2+
;
3+
; Regression test to see if ASan breaks the @llvm.coro.id intrinsic
4+
; (see commit bee2654300a8f524e05dd4cad41411d597246ac0)
5+
;
6+
; Forked from llvm/test/Transforms/Coroutines/coro-byval-param.ll
7+
8+
%promise_type = type { i8 }
9+
%struct.A = type <{ i64, i64, i32, [4 x i8] }>
10+
11+
; Function Attrs: noinline ssp uwtable mustprogress
12+
define ptr @foo(ptr nocapture readonly byval(%struct.A) align 8 %a1) #0 {
13+
entry:
14+
%__promise = alloca %promise_type, align 1
15+
%a2 = alloca %struct.A, align 8
16+
%0 = call token @llvm.coro.id(i32 16, ptr nonnull %__promise, ptr @foo, ptr null)
17+
%1 = call i1 @llvm.coro.alloc(token %0)
18+
br i1 %1, label %coro.alloc, label %coro.init
19+
20+
coro.alloc: ; preds = %entry
21+
%2 = call i64 @llvm.coro.size.i64()
22+
%call = call noalias nonnull ptr @_Znwm(i64 %2) #9
23+
br label %coro.init
24+
25+
coro.init: ; preds = %coro.alloc, %entry
26+
%3 = phi ptr [ null, %entry ], [ %call, %coro.alloc ]
27+
%4 = call ptr @llvm.coro.begin(token %0, ptr %3) #10
28+
call void @llvm.lifetime.start.p0(ptr nonnull %__promise) #2
29+
%call2 = call ptr @_ZN4task12promise_type17get_return_objectEv(ptr nonnull dereferenceable(1) %__promise)
30+
call void @initial_suspend(ptr nonnull dereferenceable(1) %__promise)
31+
%5 = call token @llvm.coro.save(ptr null)
32+
call fastcc void @_ZNSt12experimental13coroutines_v116coroutine_handleIN4task12promise_typeEE12from_addressEPv(ptr %4) #2
33+
%6 = call i8 @llvm.coro.suspend(token %5, i1 false)
34+
switch i8 %6, label %coro.ret [
35+
i8 0, label %init.ready
36+
i8 1, label %cleanup33
37+
]
38+
39+
init.ready: ; preds = %coro.init
40+
call void @llvm.lifetime.start.p0(ptr nonnull %a2) #2
41+
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a2, ptr align 8 %a1, i64 24, i1 false)
42+
call void @llvm.lifetime.end.p0(ptr nonnull %a2) #2
43+
call void @_ZN4task12promise_type13final_suspendEv(ptr nonnull dereferenceable(1) %__promise) #2
44+
%7 = call token @llvm.coro.save(ptr null)
45+
call fastcc void @_ZNSt12experimental13coroutines_v116coroutine_handleIN4task12promise_typeEE12from_addressEPv(ptr %4) #2
46+
%8 = call i8 @llvm.coro.suspend(token %7, i1 true) #10
47+
%switch = icmp ult i8 %8, 2
48+
br i1 %switch, label %cleanup33, label %coro.ret
49+
50+
cleanup33: ; preds = %init.ready, %coro.init
51+
call void @llvm.lifetime.end.p0(ptr nonnull %__promise) #2
52+
%9 = call ptr @llvm.coro.free(token %0, ptr %4)
53+
%.not = icmp eq ptr %9, null
54+
br i1 %.not, label %coro.ret, label %coro.free
55+
56+
coro.free: ; preds = %cleanup33
57+
call void @_ZdlPv(ptr nonnull %9) #2
58+
br label %coro.ret
59+
60+
coro.ret: ; preds = %coro.free, %cleanup33, %init.ready, %coro.init
61+
%10 = call i1 @llvm.coro.end(ptr null, i1 false, token none) #10
62+
ret ptr %call2
63+
}
64+
65+
; Function Attrs: argmemonly nounwind readonly
66+
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
67+
68+
; Function Attrs: nounwind
69+
declare i1 @llvm.coro.alloc(token) #2
70+
71+
; Function Attrs: nobuiltin nofree allocsize(0)
72+
declare nonnull ptr @_Znwm(i64) local_unnamed_addr #3
73+
74+
; Function Attrs: nounwind readnone
75+
declare i64 @llvm.coro.size.i64() #4
76+
77+
; Function Attrs: nounwind
78+
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
79+
80+
; Function Attrs: argmemonly nofree nosync nounwind willreturn
81+
declare void @llvm.lifetime.start.p0(ptr nocapture) #5
82+
83+
; Function Attrs: argmemonly nofree nounwind willreturn
84+
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #6
85+
86+
; Function Attrs: noinline nounwind ssp uwtable willreturn mustprogress
87+
declare ptr @_ZN4task12promise_type17get_return_objectEv(ptr nonnull dereferenceable(1)) local_unnamed_addr #7 align 2
88+
89+
; Function Attrs: noinline nounwind ssp uwtable willreturn mustprogress
90+
declare void @initial_suspend(ptr nonnull dereferenceable(1)) local_unnamed_addr #7 align 2
91+
92+
; Function Attrs: nounwind
93+
declare token @llvm.coro.save(ptr) #2
94+
95+
; Function Attrs: noinline nounwind ssp uwtable willreturn mustprogress
96+
declare hidden fastcc void @_ZNSt12experimental13coroutines_v116coroutine_handleIN4task12promise_typeEE12from_addressEPv(ptr) unnamed_addr #7 align 2
97+
98+
; Function Attrs: argmemonly nofree nosync nounwind willreturn
99+
declare void @llvm.lifetime.end.p0(ptr nocapture) #5
100+
101+
; Function Attrs: nounwind
102+
declare i8 @llvm.coro.suspend(token, i1) #2
103+
104+
; Function Attrs: noinline nounwind ssp uwtable willreturn mustprogress
105+
declare void @_ZN4task12promise_type13final_suspendEv(ptr nonnull dereferenceable(1)) local_unnamed_addr #7 align 2
106+
107+
; Function Attrs: nounwind
108+
declare i1 @llvm.coro.end(ptr, i1, token) #2
109+
110+
; Function Attrs: nobuiltin nounwind
111+
declare void @_ZdlPv(ptr) local_unnamed_addr #8
112+
113+
; Function Attrs: argmemonly nounwind readonly
114+
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
115+
116+
attributes #0 = { noinline ssp uwtable mustprogress presplitcoroutine sanitize_address "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
117+
attributes #1 = { argmemonly nounwind readonly }
118+
attributes #2 = { nounwind }
119+
attributes #3 = { nobuiltin nofree allocsize(0) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
120+
attributes #4 = { nounwind readnone }
121+
attributes #5 = { argmemonly nofree nosync nounwind willreturn }
122+
attributes #6 = { argmemonly nofree nounwind willreturn }
123+
attributes #7 = { noinline nounwind ssp uwtable willreturn mustprogress "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
124+
attributes #8 = { nobuiltin nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
125+
attributes #9 = { allocsize(0) }
126+
attributes #10 = { noduplicate }
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
; RUN: opt < %s -passes='hwasan,coro-early' -S
2+
;
3+
; Regression test to see if HWASan breaks the @llvm.coro.id intrinsic
4+
; (see commit de64f85f5d224c3304f377dd6e202c9d5415fce1)
5+
;
6+
; Forked from llvm/test/Transforms/Coroutines/coro-byval-param.ll
7+
8+
%promise_type = type { i8 }
9+
%struct.A = type <{ i64, i64, i32, [4 x i8] }>
10+
11+
; Function Attrs: noinline ssp uwtable mustprogress
12+
define ptr @foo(ptr nocapture readonly byval(%struct.A) align 8 %a1) #0 {
13+
entry:
14+
%__promise = alloca %promise_type, align 1
15+
%a2 = alloca %struct.A, align 8
16+
%0 = call token @llvm.coro.id(i32 16, ptr nonnull %__promise, ptr @foo, ptr null)
17+
%1 = call i1 @llvm.coro.alloc(token %0)
18+
br i1 %1, label %coro.alloc, label %coro.init
19+
20+
coro.alloc: ; preds = %entry
21+
%2 = call i64 @llvm.coro.size.i64()
22+
%call = call noalias nonnull ptr @_Znwm(i64 %2) #9
23+
br label %coro.init
24+
25+
coro.init: ; preds = %coro.alloc, %entry
26+
%3 = phi ptr [ null, %entry ], [ %call, %coro.alloc ]
27+
%4 = call ptr @llvm.coro.begin(token %0, ptr %3) #10
28+
call void @llvm.lifetime.start.p0(ptr nonnull %__promise) #2
29+
%call2 = call ptr @_ZN4task12promise_type17get_return_objectEv(ptr nonnull dereferenceable(1) %__promise)
30+
call void @initial_suspend(ptr nonnull dereferenceable(1) %__promise)
31+
%5 = call token @llvm.coro.save(ptr null)
32+
call fastcc void @_ZNSt12experimental13coroutines_v116coroutine_handleIN4task12promise_typeEE12from_addressEPv(ptr %4) #2
33+
%6 = call i8 @llvm.coro.suspend(token %5, i1 false)
34+
switch i8 %6, label %coro.ret [
35+
i8 0, label %init.ready
36+
i8 1, label %cleanup33
37+
]
38+
39+
init.ready: ; preds = %coro.init
40+
call void @llvm.lifetime.start.p0(ptr nonnull %a2) #2
41+
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a2, ptr align 8 %a1, i64 24, i1 false)
42+
call void @llvm.lifetime.end.p0(ptr nonnull %a2) #2
43+
call void @_ZN4task12promise_type13final_suspendEv(ptr nonnull dereferenceable(1) %__promise) #2
44+
%7 = call token @llvm.coro.save(ptr null)
45+
call fastcc void @_ZNSt12experimental13coroutines_v116coroutine_handleIN4task12promise_typeEE12from_addressEPv(ptr %4) #2
46+
%8 = call i8 @llvm.coro.suspend(token %7, i1 true) #10
47+
%switch = icmp ult i8 %8, 2
48+
br i1 %switch, label %cleanup33, label %coro.ret
49+
50+
cleanup33: ; preds = %init.ready, %coro.init
51+
call void @llvm.lifetime.end.p0(ptr nonnull %__promise) #2
52+
%9 = call ptr @llvm.coro.free(token %0, ptr %4)
53+
%.not = icmp eq ptr %9, null
54+
br i1 %.not, label %coro.ret, label %coro.free
55+
56+
coro.free: ; preds = %cleanup33
57+
call void @_ZdlPv(ptr nonnull %9) #2
58+
br label %coro.ret
59+
60+
coro.ret: ; preds = %coro.free, %cleanup33, %init.ready, %coro.init
61+
%10 = call i1 @llvm.coro.end(ptr null, i1 false, token none) #10
62+
ret ptr %call2
63+
}
64+
65+
; Function Attrs: argmemonly nounwind readonly
66+
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
67+
68+
; Function Attrs: nounwind
69+
declare i1 @llvm.coro.alloc(token) #2
70+
71+
; Function Attrs: nobuiltin nofree allocsize(0)
72+
declare nonnull ptr @_Znwm(i64) local_unnamed_addr #3
73+
74+
; Function Attrs: nounwind readnone
75+
declare i64 @llvm.coro.size.i64() #4
76+
77+
; Function Attrs: nounwind
78+
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
79+
80+
; Function Attrs: argmemonly nofree nosync nounwind willreturn
81+
declare void @llvm.lifetime.start.p0(ptr nocapture) #5
82+
83+
; Function Attrs: argmemonly nofree nounwind willreturn
84+
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #6
85+
86+
; Function Attrs: noinline nounwind ssp uwtable willreturn mustprogress
87+
declare ptr @_ZN4task12promise_type17get_return_objectEv(ptr nonnull dereferenceable(1)) local_unnamed_addr #7 align 2
88+
89+
; Function Attrs: noinline nounwind ssp uwtable willreturn mustprogress
90+
declare void @initial_suspend(ptr nonnull dereferenceable(1)) local_unnamed_addr #7 align 2
91+
92+
; Function Attrs: nounwind
93+
declare token @llvm.coro.save(ptr) #2
94+
95+
; Function Attrs: noinline nounwind ssp uwtable willreturn mustprogress
96+
declare hidden fastcc void @_ZNSt12experimental13coroutines_v116coroutine_handleIN4task12promise_typeEE12from_addressEPv(ptr) unnamed_addr #7 align 2
97+
98+
; Function Attrs: argmemonly nofree nosync nounwind willreturn
99+
declare void @llvm.lifetime.end.p0(ptr nocapture) #5
100+
101+
; Function Attrs: nounwind
102+
declare i8 @llvm.coro.suspend(token, i1) #2
103+
104+
; Function Attrs: noinline nounwind ssp uwtable willreturn mustprogress
105+
declare void @_ZN4task12promise_type13final_suspendEv(ptr nonnull dereferenceable(1)) local_unnamed_addr #7 align 2
106+
107+
; Function Attrs: nounwind
108+
declare i1 @llvm.coro.end(ptr, i1, token) #2
109+
110+
; Function Attrs: nobuiltin nounwind
111+
declare void @_ZdlPv(ptr) local_unnamed_addr #8
112+
113+
; Function Attrs: argmemonly nounwind readonly
114+
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
115+
116+
attributes #0 = { noinline ssp uwtable mustprogress presplitcoroutine sanitize_hwaddress "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
117+
attributes #1 = { argmemonly nounwind readonly }
118+
attributes #2 = { nounwind }
119+
attributes #3 = { nobuiltin nofree allocsize(0) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
120+
attributes #4 = { nounwind readnone }
121+
attributes #5 = { argmemonly nofree nosync nounwind willreturn }
122+
attributes #6 = { argmemonly nofree nounwind willreturn }
123+
attributes #7 = { noinline nounwind ssp uwtable willreturn mustprogress "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
124+
attributes #8 = { nobuiltin nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }
125+
attributes #9 = { allocsize(0) }
126+
attributes #10 = { noduplicate }

0 commit comments

Comments
 (0)