1// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | opt -instnamer -S | FileCheck %s 2 3void g(void); 4 5////////////////////////////////////////////////////////////////////////////// 6// __leave with __except 7 8// Nothing in the __try block can trap, so __try.cont isn't created. 9int __leave_with___except_simple() { 10 int myres = 0; 11 __try { 12 myres = 15; 13 __leave; 14 myres = 23; 15 } __except (1) { 16 return 0; 17 } 18 return 1; 19} 20// CHECK-LABEL: define i32 @__leave_with___except_simple() 21// CHECK: store i32 15, i32* %myres 22// CHECK-NEXT: br label %[[tryleave:[^ ]*]] 23// CHECK-NOT: store i32 23 24// CHECK: [[tryleave]] 25// CHECK-NEXT: ret i32 1 26 27 28// The "normal" case. 29int __leave_with___except() { 30 int myres = 0; 31 __try { 32 g(); 33 __leave; 34 myres = 23; 35 } __except (1) { 36 return 0; 37 } 38 return 1; 39} 40// CHECK-LABEL: define i32 @__leave_with___except() 41// CHECK: invoke void @g() 42// CHECK-NEXT: to label %[[cont:.*]] unwind label %{{.*}} 43// For __excepts, instead of an explicit __try.__leave label, we could use 44// use invoke.cont as __leave jump target instead. However, not doing this 45// keeps the CodeGen code simpler, __leave is very rare, and SimplifyCFG will 46// simplify this anyways. 47// CHECK: [[cont]] 48// CHECK-NEXT: br label %[[tryleave:[^ ]*]] 49// CHECK-NOT: store i32 23 50// CHECK: [[tryleave]] 51// CHECK-NEXT: br label % 52 53 54////////////////////////////////////////////////////////////////////////////// 55// __leave with __finally 56 57void abort(void) __attribute__((noreturn)); 58 59// Nothing in the __try block can trap, so __finally.cont and friends aren't 60// created. 61int __leave_with___finally_simple() { 62 int myres = 0; 63 __try { 64 myres = 15; 65 __leave; 66 myres = 23; 67 } __finally { 68 return 0; 69 } 70 return 1; 71} 72// CHECK-LABEL: define i32 @__leave_with___finally_simple() 73// CHECK: store i32 15, i32* %myres 74// CHECK-NEXT: br label %[[tryleave:[^ ]*]] 75// CHECK-NOT: store i32 23 76// CHECK: [[tryleave]] 77// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 78// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_simple@@"(i8 0, i8* %[[fp]]) 79 80// __finally block doesn't return, __finally.cont doesn't exist. 81int __leave_with___finally_noreturn() { 82 int myres = 0; 83 __try { 84 myres = 15; 85 __leave; 86 myres = 23; 87 } __finally { 88 abort(); 89 } 90 return 1; 91} 92// CHECK-LABEL: define i32 @__leave_with___finally_noreturn() 93// CHECK: store i32 15, i32* %myres 94// CHECK-NEXT: br label %[[tryleave:[^ ]*]] 95// CHECK-NOT: store i32 23 96// CHECK: [[tryleave]] 97// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 98// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_noreturn@@"(i8 0, i8* %[[fp]]) 99 100// The "normal" case. 101int __leave_with___finally() { 102 int myres = 0; 103 __try { 104 g(); 105 __leave; 106 myres = 23; 107 } __finally { 108 return 0; 109 } 110 return 1; 111} 112// CHECK-LABEL: define i32 @__leave_with___finally() 113// CHECK: invoke void @g() 114// CHECK-NEXT: to label %[[cont:.*]] unwind label %{{.*}} 115// For __finally, there needs to be an explicit __try.__leave, because 116// abnormal.termination.slot needs to be set there. 117// CHECK: [[cont]] 118// CHECK-NEXT: br label %[[tryleave:[^ ]*]] 119// CHECK-NOT: store i32 23 120// CHECK: [[tryleave]] 121// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 122// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally@@"(i8 0, i8* %[[fp]]) 123 124 125////////////////////////////////////////////////////////////////////////////// 126// Mixed, nested cases. 127 128int nested___except___finally() { 129 int myres = 0; 130 __try { 131 __try { 132 g(); 133 } __finally { 134 g(); 135 __leave; // Refers to the outer __try, not the __finally! 136 myres = 23; 137 return 0; 138 } 139 140 myres = 51; 141 } __except (1) { 142 } 143 return 1; 144} 145// CHECK-LABEL: define i32 @nested___except___finally() 146 147// CHECK-LABEL: invoke void @g() 148// CHECK-NEXT: to label %[[g1_cont1:.*]] unwind label %[[g1_lpad:.*]] 149 150// CHECK: [[g1_cont1]] 151// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 152// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i8 0, i8* %[[fp]]) 153// CHECK-NEXT: to label %[[fin_cont:.*]] unwind label %[[g2_lpad:.*]] 154 155// CHECK: [[fin_cont]] 156// CHECK: store i32 51, i32* % 157// CHECK-NEXT: br label %[[trycont:[^ ]*]] 158 159// CHECK: [[g1_lpad]] 160// CHECK-NEXT: cleanuppad 161// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 162// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i8 1, i8* %[[fp]]) 163// CHECK-NEXT: to label %[[g1_resume:.*]] unwind label %[[g2_lpad]] 164// CHECK: cleanupret {{.*}} unwind label %[[g2_lpad]] 165 166// CHECK: [[g2_lpad]] 167// CHECK: catchpad {{.*}} [i8* null] 168// CHECK: catchret 169// CHECK: br label %[[trycont]] 170 171// CHECK: [[trycont]] 172// CHECK-NEXT: ret i32 1 173 174// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___except___finally@@"(i8 %abnormal_termination, i8* %frame_pointer) 175// CHECK: call void @g() 176// CHECK: unreachable 177 178int nested___except___except() { 179 int myres = 0; 180 __try { 181 __try { 182 g(); 183 myres = 16; 184 } __except (1) { 185 g(); 186 __leave; // Refers to the outer __try, not the __except we're in! 187 myres = 23; 188 return 0; 189 } 190 191 myres = 51; 192 } __except (1) { 193 } 194 return 1; 195} 196// The order of basic blocks in the below doesn't matter. 197// CHECK-LABEL: define i32 @nested___except___except() 198 199// CHECK-LABEL: invoke void @g() 200// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] 201 202// CHECK: [[g1_lpad]] 203// CHECK: catchpad {{.*}} [i8* null] 204// CHECK: catchret {{.*}} to label %[[except:[^ ]*]] 205// CHECK: [[except]] 206// CHECK: invoke void @g() 207// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] 208 209// CHECK: [[g2_lpad]] 210// CHECK: catchpad {{.*}} [i8* null] 211// CHECK: catchret 212// CHECK: br label %[[trycont4:[^ ]*]] 213 214// CHECK: [[trycont4]] 215// CHECK-NEXT: ret i32 1 216 217// CHECK: [[g2_cont]] 218// CHECK-NEXT: br label %[[tryleave:[^ ]*]] 219// CHECK-NOT: store i32 23 220 221// CHECK: [[g1_cont]] 222// CHECK: store i32 16, i32* %myres 223// CHECK-NEXT: br label %[[trycont:[^ ]*]] 224 225// CHECK: [[trycont]] 226// CHECK-NEXT: store i32 51, i32* %myres 227// CHECK-NEXT: br label %[[tryleave]] 228 229// CHECK: [[tryleave]] 230// CHECK-NEXT: br label %[[trycont4]] 231 232int nested___finally___except() { 233 int myres = 0; 234 __try { 235 __try { 236 g(); 237 } __except (1) { 238 g(); 239 __leave; // Refers to the outer __try, not the __except! 240 myres = 23; 241 return 0; 242 } 243 244 myres = 51; 245 } __finally { 246 } 247 return 1; 248} 249// The order of basic blocks in the below doesn't matter. 250// CHECK-LABEL: define i32 @nested___finally___except() 251 252// CHECK-LABEL: invoke void @g() 253// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] 254 255// CHECK: [[g1_lpad]] 256// CHECK: catchpad 257// CHECK: catchret 258// CHECK: invoke void @g() 259// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] 260 261// CHECK: [[g2_cont]] 262// CHECK: br label %[[tryleave:[^ ]*]] 263// CHECK-NOT: 23 264 265// CHECK: [[g1_cont]] 266// CHECK-NEXT: br label %[[trycont:[^ ]*]] 267 268// CHECK: [[trycont]] 269// CHECK: store i32 51, i32* % 270// CHECK-NEXT: br label %[[tryleave]] 271 272// CHECK: [[tryleave]] 273// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 274// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i8 0, i8* %[[fp]]) 275// CHECK-NEXT: ret i32 1 276 277// CHECK: [[g2_lpad]] 278// CHECK: cleanuppad 279// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 280// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i8 1, i8* %[[fp]]) 281// CHECK: cleanupret {{.*}} unwind to caller 282 283// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___except@@"(i8 %abnormal_termination, i8* %frame_pointer) 284// CHECK: ret void 285 286int nested___finally___finally() { 287 int myres = 0; 288 __try { 289 __try { 290 g(); 291 myres = 16; 292 } __finally { 293 g(); 294 __leave; // Refers to the outer __try, not the __finally we're in! 295 myres = 23; 296 return 0; 297 } 298 299 myres = 51; 300 } __finally { 301 } 302 return 1; 303} 304// The order of basic blocks in the below doesn't matter. 305// CHECK-LABEL: define i32 @nested___finally___finally() 306 307// CHECK: invoke void @g() 308// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] 309 310// CHECK: [[g1_cont]] 311// CHECK: store i32 16, i32* %[[myres:[^ ]*]], 312// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 313// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i8 0, i8* %[[fp]]) 314// CHECK-NEXT: to label %[[finally_cont:.*]] unwind label %[[g2_lpad:.*]] 315 316// CHECK: [[finally_cont]] 317// CHECK: store i32 51, i32* %[[myres]] 318// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 319// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i8 0, i8* %[[fp]]) 320// CHECK-NEXT: ret i32 1 321 322// CHECK: [[g1_lpad]] 323// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad within none [] 324// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 325// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i8 1, i8* %[[fp]]) 326// CHECK-NEXT: to label %[[finally_cont2:.*]] unwind label %[[g2_lpad]] 327// CHECK: [[finally_cont2]] 328// CHECK: cleanupret from %[[padtoken]] unwind label %[[g2_lpad]] 329 330// CHECK: [[g2_lpad]] 331// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad within none [] 332// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() 333// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i8 1, i8* %[[fp]]) 334// CHECK: cleanupret from %[[padtoken]] unwind to caller 335 336// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer) 337// CHECK: ret void 338 339// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer) 340// CHECK: call void @g() 341// CHECK: unreachable 342