1 // RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -fnew-ms-eh -emit-llvm -o - | opt -instnamer -S | FileCheck %s 2 3 void g(void); 4 5 ////////////////////////////////////////////////////////////////////////////// 6 // __leave with __except 7 8 // Nothing in the __try block can trap, so __try.cont isn't created. 9 int __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. 29 int __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 57 void abort(void) __attribute__((noreturn)); 58 59 // Nothing in the __try block can trap, so __finally.cont and friends aren't 60 // created. 61 int __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. 81 int __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. 101 int __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 128 int 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 178 int 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 232 int 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 286 int 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