1 // RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - \ 2 // RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X64 3 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - \ 4 // RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X86 5 // RUN: %clang_cc1 %s -triple aarch64-windows -fms-extensions -emit-llvm -o - \ 6 // RUN: | FileCheck %s --check-prefixes=CHECK,ARM64 7 // RUN: %clang_cc1 %s -triple i686-pc-windows-gnu -fms-extensions -emit-llvm -o - \ 8 // RUN: | FileCheck %s --check-prefix=X86-GNU 9 // RUN: %clang_cc1 %s -triple x86_64-pc-windows-gnu -fms-extensions -emit-llvm -o - \ 10 // RUN: | FileCheck %s --check-prefix=X64-GNU 11 12 void try_body(int numerator, int denominator, int *myres) { 13 *myres = numerator / denominator; 14 } 15 // CHECK-LABEL: define dso_local void @try_body(i32 noundef %numerator, i32 noundef %denominator, i32* noundef %myres) 16 // CHECK: sdiv i32 17 // CHECK: store i32 %{{.*}}, i32* 18 // CHECK: ret void 19 20 int safe_div(int numerator, int denominator, int *res) { 21 int myres = 0; 22 int success = 1; 23 __try { 24 try_body(numerator, denominator, &myres); 25 } __except (1) { 26 success = -42; 27 } 28 *res = myres; 29 return success; 30 } 31 32 // CHECK-LABEL: define dso_local i32 @safe_div(i32 noundef %numerator, i32 noundef %denominator, i32* noundef %res) 33 // X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 34 // ARM64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 35 // X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) 36 // CHECK: invoke void @try_body(i32 noundef %{{.*}}, i32 noundef %{{.*}}, i32* noundef %{{.*}}) #[[NOINLINE:[0-9]+]] 37 // CHECK: to label %{{.*}} unwind label %[[catchpad:[^ ]*]] 38 // 39 // CHECK: [[catchpad]] 40 // X64: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* null] 41 // ARM64: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* null] 42 // X86: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* bitcast (i32 ()* @"?filt$0@0@safe_div@@" to i8*)] 43 // CHECK-NEXT: catchret from %[[padtoken]] to label %[[except:[^ ]*]] 44 // 45 // CHECK: [[except]] 46 // CHECK: store i32 -42, i32* %[[success:[^ ]*]] 47 // 48 // CHECK: %[[res:[^ ]*]] = load i32, i32* %[[success]] 49 // CHECK: ret i32 %[[res]] 50 51 // 32-bit SEH needs this filter to save the exception code. 52 // 53 // X86-LABEL: define internal i32 @"?filt$0@0@safe_div@@"() 54 // X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress.p0i8(i32 1) 55 // X86: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (i32 (i32, i32, i32*)* @safe_div to i8*), i8* %[[ebp]]) 56 // X86: call i8* @llvm.localrecover(i8* bitcast (i32 (i32, i32, i32*)* @safe_div to i8*), i8* %[[fp]], i32 0) 57 // X86: load i8*, i8** 58 // X86: load i32*, i32** 59 // X86: load i32, i32* 60 // X86: store i32 %{{.*}}, i32* 61 // X86: ret i32 1 62 63 // Mingw uses msvcrt, so it can also use _except_handler3. 64 // X86-GNU-LABEL: define dso_local i32 @safe_div(i32 noundef %numerator, i32 noundef %denominator, i32* noundef %res) 65 // X86-GNU-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) 66 // X64-GNU-LABEL: define dso_local i32 @safe_div(i32 noundef %numerator, i32 noundef %denominator, i32* noundef %res) 67 // X64-GNU-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 68 69 void j(void); 70 71 int filter_expr_capture(void) { 72 int r = 42; 73 __try { 74 j(); 75 } __except(r = -1) { 76 r = 13; 77 } 78 return r; 79 } 80 81 // CHECK-LABEL: define dso_local i32 @filter_expr_capture() 82 // X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 83 // ARM64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 84 // X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) 85 // X64: call void (...) @llvm.localescape(i32* %[[r:[^ ,]*]]) 86 // ARM64: call void (...) @llvm.localescape(i32* %[[r:[^ ,]*]]) 87 // X86: call void (...) @llvm.localescape(i32* %[[r:[^ ,]*]], i32* %[[code:[^ ,]*]]) 88 // CHECK: store i32 42, i32* %[[r]] 89 // CHECK: invoke void @j() #[[NOINLINE]] 90 // 91 // CHECK: catchpad within %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"?filt$0@0@filter_expr_capture@@" to i8*)] 92 // CHECK: store i32 13, i32* %[[r]] 93 // 94 // CHECK: %[[rv:[^ ]*]] = load i32, i32* %[[r]] 95 // CHECK: ret i32 %[[rv]] 96 97 // X64-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"(i8* noundef %exception_pointers, i8* noundef %frame_pointer) 98 // X64: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer) 99 // X64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0) 100 // 101 // ARM64-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"(i8* noundef %exception_pointers, i8* noundef %frame_pointer) 102 // ARM64: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer) 103 // ARM64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0) 104 // 105 // X86-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"() 106 // X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress.p0i8(i32 1) 107 // X86: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[ebp]]) 108 // X86: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0) 109 // 110 // CHECK: store i32 -1, i32* %{{.*}} 111 // CHECK: ret i32 -1 112 113 int nested_try(void) { 114 int r = 42; 115 __try { 116 __try { 117 j(); 118 r = 0; 119 } __except(_exception_code() == 123) { 120 r = 123; 121 } 122 } __except(_exception_code() == 456) { 123 r = 456; 124 } 125 return r; 126 } 127 // CHECK-LABEL: define dso_local i32 @nested_try() 128 // X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 129 // ARM64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 130 // X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) 131 // CHECK: store i32 42, i32* %[[r:[^ ,]*]] 132 // CHECK: invoke void @j() #[[NOINLINE]] 133 // CHECK: to label %[[cont:[^ ]*]] unwind label %[[cswitch_inner:[^ ]*]] 134 // 135 // CHECK: [[cswitch_inner]] 136 // CHECK: %[[cs_inner:[^ ]*]] = catchswitch within none [label %[[cpad_inner:[^ ]*]]] unwind label %[[cswitch_outer:[^ ]*]] 137 // 138 // CHECK: [[cswitch_outer]] 139 // CHECK: %[[cs_outer:[^ ]*]] = catchswitch within none [label %[[cpad_outer:[^ ]*]]] unwind to caller 140 // 141 // CHECK: [[cpad_outer]] 142 // CHECK: catchpad within %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"?filt$0@0@nested_try@@" to i8*)] 143 // CHECK-NEXT: catchret {{.*}} to label %[[except_outer:[^ ]*]] 144 // 145 // CHECK: [[except_outer]] 146 // CHECK: store i32 456, i32* %[[r]] 147 // CHECK: br label %[[outer_try_cont:[^ ]*]] 148 // 149 // CHECK: [[outer_try_cont]] 150 // CHECK: %[[r_load:[^ ]*]] = load i32, i32* %[[r]] 151 // CHECK: ret i32 %[[r_load]] 152 // 153 // CHECK: [[cpad_inner]] 154 // CHECK: catchpad within %[[cs_inner]] [i8* bitcast (i32 ({{.*}})* @"?filt$1@0@nested_try@@" to i8*)] 155 // CHECK-NEXT: catchret {{.*}} to label %[[except_inner:[^ ]*]] 156 // 157 // CHECK: [[except_inner]] 158 // CHECK: store i32 123, i32* %[[r]] 159 // CHECK: br label %[[inner_try_cont:[^ ]*]] 160 // 161 // CHECK: [[inner_try_cont]] 162 // CHECK: br label %[[outer_try_cont]] 163 // 164 // CHECK: [[cont]] 165 // CHECK: store i32 0, i32* %[[r]] 166 // CHECK: br label %[[inner_try_cont]] 167 // 168 // CHECK-LABEL: define internal i32 @"?filt$0@0@nested_try@@"({{.*}}) 169 // X86: call i8* @llvm.eh.recoverfp({{.*}}) 170 // CHECK: load i32*, i32** 171 // CHECK: load i32, i32* 172 // CHECK: icmp eq i32 %{{.*}}, 456 173 // 174 // CHECK-LABEL: define internal i32 @"?filt$1@0@nested_try@@"({{.*}}) 175 // X86: call i8* @llvm.eh.recoverfp({{.*}}) 176 // CHECK: load i32*, i32** 177 // CHECK: load i32, i32* 178 // CHECK: icmp eq i32 %{{.*}}, 123 179 180 int basic_finally(int g) { 181 __try { 182 j(); 183 } __finally { 184 ++g; 185 } 186 return g; 187 } 188 // CHECK-LABEL: define dso_local i32 @basic_finally(i32 noundef %g) 189 // X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 190 // ARM64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 191 // X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) 192 // CHECK: %[[g_addr:[^ ]*]] = alloca i32, align 4 193 // CHECK: call void (...) @llvm.localescape(i32* %[[g_addr]]) 194 // CHECK: store i32 %g, i32* %[[g_addr]] 195 // 196 // CHECK: invoke void @j() 197 // CHECK: to label %[[cont:[^ ]*]] unwind label %[[cleanuppad:[^ ]*]] 198 // 199 // CHECK: [[cont]] 200 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 201 // CHECK: call void @"?fin$0@0@basic_finally@@"({{i8 noundef( zeroext)?}} 0, i8* noundef %[[fp]]) 202 // CHECK: load i32, i32* %[[g_addr]], align 4 203 // CHECK: ret i32 204 // 205 // CHECK: [[cleanuppad]] 206 // CHECK: %[[padtoken:[^ ]*]] = cleanuppad within none [] 207 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 208 // CHECK: call void @"?fin$0@0@basic_finally@@"({{i8 noundef( zeroext)?}} 1, i8* noundef %[[fp]]) 209 // CHECK: cleanupret from %[[padtoken]] unwind to caller 210 211 // CHECK: define internal void @"?fin$0@0@basic_finally@@"({{i8 noundef( zeroext)?}} %abnormal_termination, i8* noundef %frame_pointer) 212 // CHECK: call i8* @llvm.localrecover(i8* bitcast (i32 (i32)* @basic_finally to i8*), i8* %frame_pointer, i32 0) 213 // CHECK: load i32, i32* %{{.*}}, align 4 214 // CHECK: add nsw i32 %{{.*}}, 1 215 // CHECK: store i32 %{{.*}}, i32* %{{.*}}, align 4 216 // CHECK: ret void 217 218 int returns_int(void); 219 int except_return(void) { 220 __try { 221 return returns_int(); 222 } __except(1) { 223 return 42; 224 } 225 } 226 // CHECK-LABEL: define dso_local i32 @except_return() 227 // CHECK: %[[tmp:[^ ]*]] = invoke i32 @returns_int() 228 // CHECK: to label %[[cont:[^ ]*]] unwind label %[[catchpad:[^ ]*]] 229 // 230 // CHECK: [[catchpad]] 231 // CHECK: catchpad 232 // CHECK: catchret 233 // CHECK: store i32 42, i32* %[[rv:[^ ]*]] 234 // CHECK: br label %[[retbb:[^ ]*]] 235 // 236 // CHECK: [[cont]] 237 // CHECK: store i32 %[[tmp]], i32* %[[rv]] 238 // CHECK: br label %[[retbb]] 239 // 240 // CHECK: [[retbb]] 241 // CHECK: %[[r:[^ ]*]] = load i32, i32* %[[rv]] 242 // CHECK: ret i32 %[[r]] 243 244 245 // PR 24751: don't assert if a variable is used twice in a __finally block. 246 // Also, make sure we don't do redundant work to capture/project it. 247 void finally_capture_twice(int x) { 248 __try { 249 } __finally { 250 int y = x; 251 int z = x; 252 } 253 } 254 // 255 // CHECK-LABEL: define dso_local void @finally_capture_twice( 256 // CHECK: [[X:%.*]] = alloca i32, align 4 257 // CHECK: call void (...) @llvm.localescape(i32* [[X]]) 258 // CHECK-NEXT: store i32 {{.*}}, i32* [[X]], align 4 259 // CHECK-NEXT: [[LOCAL:%.*]] = call i8* @llvm.localaddress() 260 // CHECK-NEXT: call void [[FINALLY:@.*]](i8 noundef{{ zeroext | }}0, i8* noundef [[LOCAL]]) 261 // CHECK: define internal void [[FINALLY]]( 262 // CHECK: [[LOCAL:%.*]] = call i8* @llvm.localrecover( 263 // CHECK: [[X:%.*]] = bitcast i8* [[LOCAL]] to i32* 264 // CHECK-NEXT: [[Y:%.*]] = alloca i32, align 4 265 // CHECK-NEXT: [[Z:%.*]] = alloca i32, align 4 266 // CHECK-NEXT: store i8* 267 // CHECK-NEXT: store i8 268 // CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[X]], align 4 269 // CHECK-NEXT: store i32 [[T0]], i32* [[Y]], align 4 270 // CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[X]], align 4 271 // CHECK-NEXT: store i32 [[T0]], i32* [[Z]], align 4 272 // CHECK-NEXT: ret void 273 274 int exception_code_in_except(void) { 275 __try { 276 try_body(0, 0, 0); 277 } __except(1) { 278 return _exception_code(); 279 } 280 } 281 282 // CHECK-LABEL: define dso_local i32 @exception_code_in_except() 283 // CHECK: %[[ret_slot:[^ ]*]] = alloca i32 284 // CHECK: %[[code_slot:[^ ]*]] = alloca i32 285 // CHECK: invoke void @try_body(i32 noundef 0, i32 noundef 0, i32* noundef null) 286 // CHECK: %[[pad:[^ ]*]] = catchpad 287 // CHECK: catchret from %[[pad]] 288 // X64: %[[code:[^ ]*]] = call i32 @llvm.eh.exceptioncode(token %[[pad]]) 289 // X64: store i32 %[[code]], i32* %[[code_slot]] 290 // ARM64: %[[code:[^ ]*]] = call i32 @llvm.eh.exceptioncode(token %[[pad]]) 291 // ARM64: store i32 %[[code]], i32* %[[code_slot]] 292 // CHECK: %[[ret1:[^ ]*]] = load i32, i32* %[[code_slot]] 293 // CHECK: store i32 %[[ret1]], i32* %[[ret_slot]] 294 // CHECK: %[[ret2:[^ ]*]] = load i32, i32* %[[ret_slot]] 295 // CHECK: ret i32 %[[ret2]] 296 297 // CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} } 298