1 // RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fexceptions -fms-extensions -emit-llvm -o - | FileCheck %s 2 3 // FIXME: Perform this outlining automatically CodeGen. 4 void try_body(int numerator, int denominator, int *myres) { 5 *myres = numerator / denominator; 6 } 7 // CHECK-LABEL: define void @try_body(i32 %numerator, i32 %denominator, i32* %myres) 8 // CHECK: sdiv i32 9 // CHECK: store i32 %{{.*}}, i32* 10 // CHECK: ret void 11 12 int safe_div(int numerator, int denominator, int *res) { 13 int myres = 0; 14 int success = 1; 15 __try { 16 try_body(numerator, denominator, &myres); 17 } __except (1) { 18 success = -42; 19 } 20 *res = myres; 21 return success; 22 } 23 // CHECK-LABEL: define i32 @safe_div(i32 %numerator, i32 %denominator, i32* %res) 24 // CHECK: invoke void @try_body(i32 %{{.*}}, i32 %{{.*}}, i32* %{{.*}}) 25 // CHECK: to label %{{.*}} unwind label %[[lpad:[^ ]*]] 26 // 27 // CHECK: [[lpad]] 28 // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 29 // CHECK-NEXT: catch i8* null 30 // CHECK-NOT: br i1 31 // CHECK: br label %[[except:[^ ]*]] 32 // CHECK: [[except]] 33 // CHECK-NEXT: store i32 -42, i32* %[[success:[^ ]*]] 34 // 35 // CHECK: %[[res:[^ ]*]] = load i32* %[[success]] 36 // CHECK: ret i32 %[[res]] 37 38 void j(void); 39 40 // FIXME: Implement local variable captures in filter expressions. 41 int filter_expr_capture() { 42 int r = 42; 43 __try { 44 j(); 45 } __except(/*r =*/ -1) { 46 r = 13; 47 } 48 return r; 49 } 50 51 // CHECK-LABEL: define i32 @filter_expr_capture() 52 // FIXMECHECK: %[[captures]] = call i8* @llvm.frameallocate(i32 4) 53 // CHECK: store i32 42, i32* %[[r:[^ ,]*]] 54 // CHECK: invoke void @j() 55 // 56 // CHECK: landingpad 57 // CHECK-NEXT: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@filter_expr_capture@@" to i8*) 58 // CHECK: store i32 13, i32* %[[r]] 59 // 60 // CHECK: %[[rv:[^ ]*]] = load i32* %[[r]] 61 // CHECK: ret i32 %[[rv]] 62 63 // CHECK-LABEL: define internal i32 @"\01?filt$0@0@filter_expr_capture@@"(i8* %exception_pointers, i8* %frame_pointer) 64 // FIXMECHECK: %[[captures]] = call i8* @llvm.framerecover(i8* bitcast (i32 ()* @filter_expr_capture, i8* %frame_pointer) 65 // FIXMECHECK: store i32 -1, i32* %{{.*}} 66 // CHECK: ret i32 -1 67 68 int nested_try() { 69 int r = 42; 70 __try { 71 __try { 72 j(); 73 r = 0; 74 } __except(_exception_code() == 123) { 75 r = 123; 76 } 77 } __except(_exception_code() == 456) { 78 r = 456; 79 } 80 return r; 81 } 82 // CHECK-LABEL: define i32 @nested_try() 83 // CHECK: store i32 42, i32* %[[r:[^ ,]*]] 84 // CHECK: invoke void @j() 85 // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 86 // 87 // CHECK: [[cont]] 88 // CHECK: store i32 0, i32* %[[r]] 89 // CHECK: br label %[[inner_try_cont:[^ ]*]] 90 // 91 // CHECK: [[lpad]] 92 // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 93 // CHECK: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$1@0@nested_try@@" to i8*) 94 // CHECK: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@nested_try@@" to i8*) 95 // CHECK: store i8* %{{.*}}, i8** %[[ehptr_slot:[^ ]*]] 96 // CHECK: store i32 %{{.*}}, i32* %[[sel_slot:[^ ]*]] 97 // 98 // CHECK: load i32* %[[sel_slot]] 99 // CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @"\01?filt$1@0@nested_try@@" to i8*)) 100 // CHECK: icmp eq i32 101 // CHECK: br i1 102 // 103 // CHECK: load i32* %[[sel_slot]] 104 // CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@nested_try@@" to i8*)) 105 // CHECK: icmp eq i32 106 // CHECK: br i1 107 // 108 // CHECK: store i32 456, i32* %[[r]] 109 // CHECK: br label %[[outer_try_cont:[^ ]*]] 110 // 111 // CHECK: [[outer_try_cont]] 112 // CHECK: %[[r_load:[^ ]*]] = load i32* %[[r]] 113 // CHECK: ret i32 %[[r_load]] 114 // 115 // CHECK: store i32 123, i32* %[[r]] 116 // CHECK: br label %[[inner_try_cont]] 117 // 118 // CHECK: [[inner_try_cont]] 119 // CHECK: br label %[[outer_try_cont]] 120 121 // FIXME: This lowering of __finally can't actually work, it will have to 122 // change. 123 static unsigned g = 0; 124 void basic_finally() { 125 ++g; 126 __try { 127 j(); 128 } __finally { 129 --g; 130 } 131 } 132 // CHECK-LABEL: define void @basic_finally() 133 // CHECK: load i32* @g 134 // CHECK: add i32 %{{.*}}, 1 135 // CHECK: store i32 %{{.*}}, i32* @g 136 // 137 // CHECK: invoke void @j() 138 // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 139 // 140 // CHECK: [[cont]] 141 // CHECK: load i32* @g 142 // CHECK: add i32 %{{.*}}, -1 143 // CHECK: store i32 %{{.*}}, i32* @g 144 // CHECK: ret void 145 // 146 // CHECK: [[lpad]] 147 // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) 148 // CHECK-NEXT: cleanup 149 // CHECK: load i32* @g 150 // CHECK: add i32 %{{.*}}, -1 151 // CHECK: store i32 %{{.*}}, i32* @g 152 // CHECK: resume 153