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 = ¬hrow_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