xref: /llvm-project/llvm/test/Transforms/LowerTypeTests/cfi-nounwind-direct-call.ll (revision 93de97d750548cd90c53efd4367dbd0367aa30fd)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --include-generated-funcs --version 2
2; RUN: opt < %s -passes='lowertypetests,default<O3>' -S | FileCheck %s
3
4; This IR is based of the following C++
5; which was compiled with:
6; clang -cc1 -fexceptions -fcxx-exceptions \
7; -std=c++11 -internal-isystem llvm-project/build/lib/clang/17/include \
8; -nostdsysteminc -triple x86_64-unknown-linux -fsanitize=cfi-icall \
9; -fsanitize-cfi-cross-dso -fsanitize-trap=cfi-icall -Oz -S -emit-llvm
10; int (*catch_ptr)(int);
11; int nothrow_e (int num) noexcept {
12;   if (num) return 1;
13;   return 0;
14; }
15; int call_catch(int num) {
16;   catch_ptr = &nothrow_e;
17;   return catch_ptr(num);
18; }
19
20target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
21target triple = "x86_64-unknown-linux"
22
23@catch_ptr = local_unnamed_addr global ptr null, align 8
24@llvm.used = appending global [1 x ptr] [ptr @__cfi_check_fail], section "llvm.metadata"
25
26; Function Attrs: minsize mustprogress nofree norecurse nosync nounwind optsize willreturn memory(none)
27define dso_local noundef i32 @_Z9nothrow_ei(i32 noundef %num) #0 !type !4 !type !5 !type !6 {
28entry:
29  %tobool.not = icmp ne i32 %num, 0
30  %. = zext i1 %tobool.not to i32
31  ret i32 %.
32}
33
34; Function Attrs: minsize mustprogress nounwind optsize
35define dso_local noundef i32 @_Z10call_catchi(i32 noundef %num) local_unnamed_addr #1 !type !4 !type !5 !type !6 {
36entry:
37  store ptr @_Z9nothrow_ei, ptr @catch_ptr, align 8, !tbaa !7
38  %0 = tail call i1 @llvm.type.test(ptr nonnull @_Z9nothrow_ei, metadata !"_ZTSFiiE"), !nosanitize !11
39  br i1 %0, label %cfi.cont, label %cfi.slowpath, !prof !12, !nosanitize !11
40
41cfi.slowpath:                                     ; preds = %entry
42  tail call void @__cfi_slowpath(i64 5174074510188755522, ptr nonnull @_Z9nothrow_ei) #5, !nosanitize !11
43  br label %cfi.cont, !nosanitize !11
44
45cfi.cont:                                         ; preds = %cfi.slowpath, %entry
46  %tobool.not.i = icmp ne i32 %num, 0
47  %..i = zext i1 %tobool.not.i to i32
48  ret i32 %..i
49}
50
51; Function Attrs: mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none)
52declare i1 @llvm.type.test(ptr, metadata) #2
53
54declare void @__cfi_slowpath(i64, ptr) local_unnamed_addr
55
56; Function Attrs: minsize optsize
57define weak_odr hidden void @__cfi_check_fail(ptr noundef %0, ptr noundef %1) #3 {
58entry:
59  %.not = icmp eq ptr %0, null, !nosanitize !11
60  br i1 %.not, label %trap, label %cont, !nosanitize !11
61
62trap:                                             ; preds = %cont, %entry
63  tail call void @llvm.ubsantrap(i8 2) #6, !nosanitize !11
64  unreachable, !nosanitize !11
65
66cont:                                             ; preds = %entry
67  %2 = load i8, ptr %0, align 4, !nosanitize !11
68  %switch = icmp ult i8 %2, 5
69  br i1 %switch, label %trap, label %cont6
70
71cont6:                                            ; preds = %cont
72  ret void, !nosanitize !11
73}
74
75; Function Attrs: cold noreturn nounwind
76declare void @llvm.ubsantrap(i8 immarg) #4
77
78define weak void @__cfi_check(i64 %0, ptr %1, ptr %2) local_unnamed_addr {
79entry:
80  tail call void @llvm.trap()
81  unreachable
82}
83
84; Function Attrs: cold noreturn nounwind
85declare void @llvm.trap() #4
86
87attributes #0 = { minsize mustprogress nofree norecurse nosync nounwind optsize willreturn memory(none) "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
88attributes #1 = { minsize mustprogress nounwind optsize "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
89attributes #2 = { mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) }
90attributes #3 = { minsize optsize "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
91attributes #4 = { cold noreturn nounwind }
92attributes #5 = { nounwind }
93attributes #6 = { noreturn nounwind }
94
95!llvm.module.flags = !{!0, !1, !2}
96!llvm.ident = !{!3}
97
98!0 = !{i32 1, !"wchar_size", i32 4}
99!1 = !{i32 4, !"Cross-DSO CFI", i32 1}
100!2 = !{i32 4, !"CFI Canonical Jump Tables", i32 0}
101!3 = !{!"clang version 17.0.2"}
102!4 = !{i64 0, !"_ZTSFiiE"}
103!5 = !{i64 0, !"_ZTSFiiE.generalized"}
104!6 = !{i64 0, i64 5174074510188755522}
105!7 = !{!8, !8, i64 0}
106!8 = !{!"any pointer", !9, i64 0}
107!9 = !{!"omnipotent char", !10, i64 0}
108!10 = !{!"Simple C++ TBAA"}
109!11 = !{}
110!12 = !{!"branch_weights", i32 1048575, i32 1}
111; CHECK: Function Attrs: minsize mustprogress nofree norecurse nosync nounwind optsize willreturn memory(none)
112; CHECK-LABEL: define dso_local noundef range(i32 0, 2) i32 @_Z9nothrow_ei
113; CHECK-SAME: (i32 noundef [[NUM:%.*]]) #[[ATTR0:[0-9]+]] !type [[META4:![0-9]+]] !type [[META5:![0-9]+]] !type [[META6:![0-9]+]] {
114; CHECK-NEXT:  entry:
115; CHECK-NEXT:    [[TOBOOL_NOT:%.*]] = icmp ne i32 [[NUM]], 0
116; CHECK-NEXT:    [[DOT:%.*]] = zext i1 [[TOBOOL_NOT]] to i32
117; CHECK-NEXT:    ret i32 [[DOT]]
118;
119;
120; CHECK: Function Attrs: minsize mustprogress nofree norecurse nosync nounwind optsize willreturn memory(write, argmem: none, inaccessiblemem: none)
121; CHECK-LABEL: define dso_local noundef range(i32 0, 2) i32 @_Z10call_catchi
122; CHECK-SAME: (i32 noundef [[NUM:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] !type [[META4]] !type [[META5]] !type [[META6]] {
123; CHECK-NEXT:  entry:
124; CHECK-NEXT:    store ptr @_Z9nothrow_ei.cfi_jt, ptr @catch_ptr, align 8, !tbaa [[TBAA7:![0-9]+]]
125; CHECK-NEXT:    [[TOBOOL_NOT_I:%.*]] = icmp ne i32 [[NUM]], 0
126; CHECK-NEXT:    [[DOT_I:%.*]] = zext i1 [[TOBOOL_NOT_I]] to i32
127; CHECK-NEXT:    ret i32 [[DOT_I]]
128;
129;
130; CHECK: Function Attrs: minsize optsize
131; CHECK-LABEL: define weak_odr hidden void @__cfi_check_fail
132; CHECK-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]]) #[[ATTR2:[0-9]+]] {
133; CHECK-NEXT:  entry:
134; CHECK-NEXT:    [[DOTNOT:%.*]] = icmp eq ptr [[TMP0]], null, !nosanitize [[META11:![0-9]+]]
135; CHECK-NEXT:    br i1 [[DOTNOT]], label [[TRAP:%.*]], label [[CONT:%.*]], !nosanitize [[META11]]
136; CHECK:       trap:
137; CHECK-NEXT:    tail call void @llvm.ubsantrap(i8 2) #[[ATTR6:[0-9]+]], !nosanitize [[META11]]
138; CHECK-NEXT:    unreachable, !nosanitize [[META11]]
139; CHECK:       cont:
140; CHECK-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP0]], align 4, !nosanitize [[META11]]
141; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i8 [[TMP2]], 5
142; CHECK-NEXT:    br i1 [[SWITCH]], label [[TRAP]], label [[CONT6:%.*]]
143; CHECK:       cont6:
144; CHECK-NEXT:    ret void, !nosanitize [[META11]]
145;
146;
147; CHECK-LABEL: define weak void @__cfi_check
148; CHECK-SAME: (i64 [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) local_unnamed_addr {
149; CHECK-NEXT:  entry:
150; CHECK-NEXT:    tail call void @llvm.trap()
151; CHECK-NEXT:    unreachable
152;
153;
154; CHECK: Function Attrs: naked nocf_check noinline nounwind
155; CHECK-LABEL: define internal void @_Z9nothrow_ei.cfi_jt
156; CHECK-SAME: () #[[ATTR5:[0-9]+]] align 8 {
157; CHECK-NEXT:  entry:
158; CHECK-NEXT:    tail call void asm sideeffect "jmp ${0:c}@plt\0Aint3\0Aint3\0Aint3\0A", "s"(ptr nonnull @_Z9nothrow_ei) #[[ATTR7:[0-9]+]]
159; CHECK-NEXT:    unreachable
160;
161