1// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | 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.frameaddress(i32 0) 78// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_simple@@"(i1 zeroext false, 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.frameaddress(i32 0) 98// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_noreturn@@"(i1 zeroext false, 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.frameaddress(i32 0) 122// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally@@"(i1 zeroext false, 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.frameaddress(i32 0) 152// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i1 zeroext false, 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: landingpad 161// CHECK-NEXT: catch i8* null 162// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 163// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i1 zeroext true, i8* %[[fp]]) 164// CHECK-NEXT: to label %[[g1_resume:.*]] unwind label %[[g2_lpad]] 165 166// CHECK: [[g2_lpad]] 167// CHECK: br label %[[trycont]] 168 169// CHECK: [[trycont]] 170// CHECK-NEXT: ret i32 1 171 172// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___except___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) 173// CHECK: call void @g() 174// CHECK: unreachable 175 176int nested___except___except() { 177 int myres = 0; 178 __try { 179 __try { 180 g(); 181 myres = 16; 182 } __except (1) { 183 g(); 184 __leave; // Refers to the outer __try, not the __except we're in! 185 myres = 23; 186 return 0; 187 } 188 189 myres = 51; 190 } __except (1) { 191 } 192 return 1; 193} 194// The order of basic blocks in the below doesn't matter. 195// CHECK-LABEL: define i32 @nested___except___except() 196 197// CHECK-LABEL: invoke void @g() 198// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] 199 200// CHECK: [[g1_cont]] 201// CHECK: store i32 16, i32* %myres 202// CHECK-NEXT: br label %[[trycont:[^ ]*]] 203 204// CHECK: [[g1_lpad]] 205// CHECK: br label %[[except:[^ ]*]] 206 207// CHECK: [[except]] 208// CHECK-NEXT: invoke void @g() 209// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] 210 211// CHECK: [[g2_cont]] 212// CHECK-NEXT: br label %[[tryleave:[^ ]*]] 213// CHECK-NOT: store i32 23 214 215// CHECK: [[g2_lpad]] 216// CHECK: br label %[[outerexcept:[^ ]*]] 217 218// CHECK: [[outerexcept]] 219// CHECK-NEXT: br label %[[trycont4:[^ ]*]] 220 221// CHECK: [[trycont4]] 222// CHECK-NEXT: ret i32 1 223 224// CHECK: [[trycont]] 225// CHECK-NEXT: store i32 51, i32* %myres 226// CHECK-NEXT: br label %[[tryleave]] 227 228// CHECK: [[tryleave]] 229// CHECK-NEXT: br label %[[trycont4]] 230 231int nested___finally___except() { 232 int myres = 0; 233 __try { 234 __try { 235 g(); 236 } __except (1) { 237 g(); 238 __leave; // Refers to the outer __try, not the __except! 239 myres = 23; 240 return 0; 241 } 242 243 myres = 51; 244 } __finally { 245 } 246 return 1; 247} 248// The order of basic blocks in the below doesn't matter. 249// CHECK-LABEL: define i32 @nested___finally___except() 250 251// CHECK-LABEL: invoke void @g() 252// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] 253 254// CHECK: [[g1_cont]] 255// CHECK-NEXT: br label %[[trycont:[^ ]*]] 256 257// CHECK: [[g1_lpad]] 258// CHECK: br label %[[except:[^ ]*]] 259 260// CHECK: [[except]] 261// CHECK-NEXT: invoke void @g() 262// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] 263 264// CHECK: [[g2_cont]] 265// CHECK-NEXT: br label %[[tryleave:[^ ]*]] 266// CHECK-NOT: 23 267 268// CHECK: [[g2_lpad]] 269// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 270// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i1 zeroext true, i8* %[[fp]]) 271// CHECK-NEXT: br label %[[ehresume:[^ ]*]] 272 273// CHECK: [[trycont]] 274// CHECK: store i32 51, i32* % 275// CHECK-NEXT: br label %[[tryleave]] 276 277// CHECK: [[tryleave]] 278// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 279// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i1 zeroext false, i8* %[[fp]]) 280// CHECK-NEXT: ret i32 1 281 282// CHECK: [[ehresume]] 283// CHECK: resume 284 285// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___except@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) 286// CHECK: ret void 287 288int nested___finally___finally() { 289 int myres = 0; 290 __try { 291 __try { 292 g(); 293 myres = 16; 294 } __finally { 295 g(); 296 __leave; // Refers to the outer __try, not the __finally we're in! 297 myres = 23; 298 return 0; 299 } 300 301 myres = 51; 302 } __finally { 303 } 304 return 1; 305} 306// The order of basic blocks in the below doesn't matter. 307// CHECK-LABEL: define i32 @nested___finally___finally() 308 309// CHECK-LABEL: invoke void @g() 310// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] 311 312// CHECK: [[g1_cont]] 313// CHECK: store i32 16, i32* %[[myres:[^ ]*]], 314// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 315// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]]) 316// CHECK-NEXT: to label %[[finally_cont:.*]] unwind label %[[g2_lpad:.*]] 317 318// CHECK: [[finally_cont]] 319// CHECK: store i32 51, i32* %[[myres]] 320// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 321// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]]) 322// CHECK-NEXT: ret i32 1 323 324// CHECK: [[g1_lpad]] 325// CHECK-NEXT: landingpad 326// CHECK-NEXT: cleanup 327// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 328// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext true, i8* %[[fp]]) 329// CHECK-NEXT: to label %[[finally_cont2:.*]] unwind label %[[g2_lpad]] 330 331// CHECK: [[g2_lpad]] 332// CHECK-NEXT: landingpad 333// CHECK-NEXT: cleanup 334// CHECK: br label %[[ehcleanup:.*]] 335 336// CHECK: [[finally_cont2]] 337// CHECK: br label %[[ehcleanup]] 338 339// CHECK: [[ehcleanup]] 340// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) 341// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext true, i8* %[[fp]]) 342// CHECK: resume 343 344// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) 345// CHECK: ret void 346 347// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) 348// CHECK: call void @g() 349// CHECK: unreachable 350