1*9880d681SAndroid Build Coastguard Worker; RUN: llc -mtriple x86_64-pc-windows-msvc < %s | FileCheck %s 2*9880d681SAndroid Build Coastguard Worker 3*9880d681SAndroid Build Coastguard Worker; This test case is also intended to be run manually as a complete functional 4*9880d681SAndroid Build Coastguard Worker; test. It should link, print something, and exit zero rather than crashing. 5*9880d681SAndroid Build Coastguard Worker; It is the hypothetical lowering of a C source program that looks like: 6*9880d681SAndroid Build Coastguard Worker; 7*9880d681SAndroid Build Coastguard Worker; int safe_div(int *n, int *d) { 8*9880d681SAndroid Build Coastguard Worker; int r; 9*9880d681SAndroid Build Coastguard Worker; __try { 10*9880d681SAndroid Build Coastguard Worker; __try { 11*9880d681SAndroid Build Coastguard Worker; r = *n / *d; 12*9880d681SAndroid Build Coastguard Worker; } __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) { 13*9880d681SAndroid Build Coastguard Worker; puts("EXCEPTION_ACCESS_VIOLATION"); 14*9880d681SAndroid Build Coastguard Worker; r = -1; 15*9880d681SAndroid Build Coastguard Worker; } 16*9880d681SAndroid Build Coastguard Worker; } __except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO) { 17*9880d681SAndroid Build Coastguard Worker; puts("EXCEPTION_INT_DIVIDE_BY_ZERO"); 18*9880d681SAndroid Build Coastguard Worker; r = -2; 19*9880d681SAndroid Build Coastguard Worker; } 20*9880d681SAndroid Build Coastguard Worker; return r; 21*9880d681SAndroid Build Coastguard Worker; } 22*9880d681SAndroid Build Coastguard Worker 23*9880d681SAndroid Build Coastguard Worker@str1 = internal constant [27 x i8] c"EXCEPTION_ACCESS_VIOLATION\00" 24*9880d681SAndroid Build Coastguard Worker@str2 = internal constant [29 x i8] c"EXCEPTION_INT_DIVIDE_BY_ZERO\00" 25*9880d681SAndroid Build Coastguard Worker 26*9880d681SAndroid Build Coastguard Workerdefine i32 @safe_div(i32* %n, i32* %d) personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) { 27*9880d681SAndroid Build Coastguard Workerentry: 28*9880d681SAndroid Build Coastguard Worker %r = alloca i32, align 4 29*9880d681SAndroid Build Coastguard Worker invoke void @try_body(i32* %r, i32* %n, i32* %d) 30*9880d681SAndroid Build Coastguard Worker to label %__try.cont unwind label %lpad0 31*9880d681SAndroid Build Coastguard Worker 32*9880d681SAndroid Build Coastguard Workerlpad0: 33*9880d681SAndroid Build Coastguard Worker %cs0 = catchswitch within none [label %handler0] unwind label %lpad1 34*9880d681SAndroid Build Coastguard Worker 35*9880d681SAndroid Build Coastguard Workerhandler0: 36*9880d681SAndroid Build Coastguard Worker %p0 = catchpad within %cs0 [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt0 to i8*)] 37*9880d681SAndroid Build Coastguard Worker call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0)) [ "funclet"(token %p0) ] 38*9880d681SAndroid Build Coastguard Worker store i32 -1, i32* %r, align 4 39*9880d681SAndroid Build Coastguard Worker catchret from %p0 to label %__try.cont 40*9880d681SAndroid Build Coastguard Worker 41*9880d681SAndroid Build Coastguard Workerlpad1: 42*9880d681SAndroid Build Coastguard Worker %cs1 = catchswitch within none [label %handler1] unwind to caller 43*9880d681SAndroid Build Coastguard Worker 44*9880d681SAndroid Build Coastguard Workerhandler1: 45*9880d681SAndroid Build Coastguard Worker %p1 = catchpad within %cs1 [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt1 to i8*)] 46*9880d681SAndroid Build Coastguard Worker call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0)) [ "funclet"(token %p1) ] 47*9880d681SAndroid Build Coastguard Worker store i32 -2, i32* %r, align 4 48*9880d681SAndroid Build Coastguard Worker catchret from %p1 to label %__try.cont 49*9880d681SAndroid Build Coastguard Worker 50*9880d681SAndroid Build Coastguard Worker__try.cont: 51*9880d681SAndroid Build Coastguard Worker %safe_ret = load i32, i32* %r, align 4 52*9880d681SAndroid Build Coastguard Worker ret i32 %safe_ret 53*9880d681SAndroid Build Coastguard Worker} 54*9880d681SAndroid Build Coastguard Worker 55*9880d681SAndroid Build Coastguard Worker; Normal path code 56*9880d681SAndroid Build Coastguard Worker 57*9880d681SAndroid Build Coastguard Worker; CHECK: {{^}}safe_div: 58*9880d681SAndroid Build Coastguard Worker; CHECK: .seh_proc safe_div 59*9880d681SAndroid Build Coastguard Worker; CHECK: .seh_handler __C_specific_handler, @unwind, @except 60*9880d681SAndroid Build Coastguard Worker; CHECK: .Ltmp0: 61*9880d681SAndroid Build Coastguard Worker; CHECK: leaq [[rloc:.*\(%rbp\)]], %rcx 62*9880d681SAndroid Build Coastguard Worker; CHECK: callq try_body 63*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .Ltmp1 64*9880d681SAndroid Build Coastguard Worker; CHECK: [[cont_bb:\.LBB0_[0-9]+]]: 65*9880d681SAndroid Build Coastguard Worker; CHECK: movl [[rloc]], %eax 66*9880d681SAndroid Build Coastguard Worker; CHECK: retq 67*9880d681SAndroid Build Coastguard Worker 68*9880d681SAndroid Build Coastguard Worker; Landing pad code 69*9880d681SAndroid Build Coastguard Worker 70*9880d681SAndroid Build Coastguard Worker; CHECK: [[handler1:\.LBB0_[0-9]+]]: # %handler1 71*9880d681SAndroid Build Coastguard Worker; CHECK: callq puts 72*9880d681SAndroid Build Coastguard Worker; CHECK: movl $-2, [[rloc]] 73*9880d681SAndroid Build Coastguard Worker; CHECK: jmp [[cont_bb]] 74*9880d681SAndroid Build Coastguard Worker 75*9880d681SAndroid Build Coastguard Worker; CHECK: [[handler0:\.LBB0_[0-9]+]]: # %handler0 76*9880d681SAndroid Build Coastguard Worker; CHECK: callq puts 77*9880d681SAndroid Build Coastguard Worker; CHECK: movl $-1, [[rloc]] 78*9880d681SAndroid Build Coastguard Worker; CHECK: jmp [[cont_bb]] 79*9880d681SAndroid Build Coastguard Worker 80*9880d681SAndroid Build Coastguard Worker; CHECK: .seh_handlerdata 81*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .Lsafe_div$parent_frame_offset 82*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16 83*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .Llsda_begin0: 84*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .long .Ltmp0@IMGREL+1 85*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .long .Ltmp1@IMGREL+1 86*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .long safe_div_filt0@IMGREL 87*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .long [[handler0]]@IMGREL 88*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .long .Ltmp0@IMGREL+1 89*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .long .Ltmp1@IMGREL+1 90*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .long safe_div_filt1@IMGREL 91*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .long [[handler1]]@IMGREL 92*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: .Llsda_end0: 93*9880d681SAndroid Build Coastguard Worker; CHECK: .text 94*9880d681SAndroid Build Coastguard Worker; CHECK: .seh_endproc 95*9880d681SAndroid Build Coastguard Worker 96*9880d681SAndroid Build Coastguard Workerdefine void @try_body(i32* %r, i32* %n, i32* %d) { 97*9880d681SAndroid Build Coastguard Workerentry: 98*9880d681SAndroid Build Coastguard Worker %0 = load i32, i32* %n, align 4 99*9880d681SAndroid Build Coastguard Worker %1 = load i32, i32* %d, align 4 100*9880d681SAndroid Build Coastguard Worker %div = sdiv i32 %0, %1 101*9880d681SAndroid Build Coastguard Worker store i32 %div, i32* %r, align 4 102*9880d681SAndroid Build Coastguard Worker ret void 103*9880d681SAndroid Build Coastguard Worker} 104*9880d681SAndroid Build Coastguard Worker 105*9880d681SAndroid Build Coastguard Worker; The prototype of these filter functions is: 106*9880d681SAndroid Build Coastguard Worker; int filter(EXCEPTION_POINTERS *eh_ptrs, void *rbp); 107*9880d681SAndroid Build Coastguard Worker 108*9880d681SAndroid Build Coastguard Worker; The definition of EXCEPTION_POINTERS is: 109*9880d681SAndroid Build Coastguard Worker; typedef struct _EXCEPTION_POINTERS { 110*9880d681SAndroid Build Coastguard Worker; EXCEPTION_RECORD *ExceptionRecord; 111*9880d681SAndroid Build Coastguard Worker; CONTEXT *ContextRecord; 112*9880d681SAndroid Build Coastguard Worker; } EXCEPTION_POINTERS; 113*9880d681SAndroid Build Coastguard Worker 114*9880d681SAndroid Build Coastguard Worker; The definition of EXCEPTION_RECORD is: 115*9880d681SAndroid Build Coastguard Worker; typedef struct _EXCEPTION_RECORD { 116*9880d681SAndroid Build Coastguard Worker; DWORD ExceptionCode; 117*9880d681SAndroid Build Coastguard Worker; ... 118*9880d681SAndroid Build Coastguard Worker; } EXCEPTION_RECORD; 119*9880d681SAndroid Build Coastguard Worker 120*9880d681SAndroid Build Coastguard Worker; The exception code can be retreived with two loads, one for the record 121*9880d681SAndroid Build Coastguard Worker; pointer and one for the code. The values of local variables can be 122*9880d681SAndroid Build Coastguard Worker; accessed via rbp, but that would require additional not yet implemented LLVM 123*9880d681SAndroid Build Coastguard Worker; support. 124*9880d681SAndroid Build Coastguard Worker 125*9880d681SAndroid Build Coastguard Workerdefine i32 @safe_div_filt0(i8* %eh_ptrs, i8* %rbp) { 126*9880d681SAndroid Build Coastguard Worker %eh_ptrs_c = bitcast i8* %eh_ptrs to i32** 127*9880d681SAndroid Build Coastguard Worker %eh_rec = load i32*, i32** %eh_ptrs_c 128*9880d681SAndroid Build Coastguard Worker %eh_code = load i32, i32* %eh_rec 129*9880d681SAndroid Build Coastguard Worker ; EXCEPTION_ACCESS_VIOLATION = 0xC0000005 130*9880d681SAndroid Build Coastguard Worker %cmp = icmp eq i32 %eh_code, 3221225477 131*9880d681SAndroid Build Coastguard Worker %filt.res = zext i1 %cmp to i32 132*9880d681SAndroid Build Coastguard Worker ret i32 %filt.res 133*9880d681SAndroid Build Coastguard Worker} 134*9880d681SAndroid Build Coastguard Worker 135*9880d681SAndroid Build Coastguard Workerdefine i32 @safe_div_filt1(i8* %eh_ptrs, i8* %rbp) { 136*9880d681SAndroid Build Coastguard Worker %eh_ptrs_c = bitcast i8* %eh_ptrs to i32** 137*9880d681SAndroid Build Coastguard Worker %eh_rec = load i32*, i32** %eh_ptrs_c 138*9880d681SAndroid Build Coastguard Worker %eh_code = load i32, i32* %eh_rec 139*9880d681SAndroid Build Coastguard Worker ; EXCEPTION_INT_DIVIDE_BY_ZERO = 0xC0000094 140*9880d681SAndroid Build Coastguard Worker %cmp = icmp eq i32 %eh_code, 3221225620 141*9880d681SAndroid Build Coastguard Worker %filt.res = zext i1 %cmp to i32 142*9880d681SAndroid Build Coastguard Worker ret i32 %filt.res 143*9880d681SAndroid Build Coastguard Worker} 144*9880d681SAndroid Build Coastguard Worker 145*9880d681SAndroid Build Coastguard Worker@str_result = internal constant [21 x i8] c"safe_div result: %d\0A\00" 146*9880d681SAndroid Build Coastguard Worker 147*9880d681SAndroid Build Coastguard Workerdefine i32 @main() { 148*9880d681SAndroid Build Coastguard Worker %d.addr = alloca i32, align 4 149*9880d681SAndroid Build Coastguard Worker %n.addr = alloca i32, align 4 150*9880d681SAndroid Build Coastguard Worker 151*9880d681SAndroid Build Coastguard Worker store i32 10, i32* %n.addr, align 4 152*9880d681SAndroid Build Coastguard Worker store i32 2, i32* %d.addr, align 4 153*9880d681SAndroid Build Coastguard Worker %r1 = call i32 @safe_div(i32* %n.addr, i32* %d.addr) 154*9880d681SAndroid Build Coastguard Worker call void (i8*, ...) @printf(i8* getelementptr ([21 x i8], [21 x i8]* @str_result, i32 0, i32 0), i32 %r1) 155*9880d681SAndroid Build Coastguard Worker 156*9880d681SAndroid Build Coastguard Worker store i32 10, i32* %n.addr, align 4 157*9880d681SAndroid Build Coastguard Worker store i32 0, i32* %d.addr, align 4 158*9880d681SAndroid Build Coastguard Worker %r2 = call i32 @safe_div(i32* %n.addr, i32* %d.addr) 159*9880d681SAndroid Build Coastguard Worker call void (i8*, ...) @printf(i8* getelementptr ([21 x i8], [21 x i8]* @str_result, i32 0, i32 0), i32 %r2) 160*9880d681SAndroid Build Coastguard Worker 161*9880d681SAndroid Build Coastguard Worker %r3 = call i32 @safe_div(i32* %n.addr, i32* null) 162*9880d681SAndroid Build Coastguard Worker call void (i8*, ...) @printf(i8* getelementptr ([21 x i8], [21 x i8]* @str_result, i32 0, i32 0), i32 %r3) 163*9880d681SAndroid Build Coastguard Worker ret i32 0 164*9880d681SAndroid Build Coastguard Worker} 165*9880d681SAndroid Build Coastguard Worker 166*9880d681SAndroid Build Coastguard Workerdeclare i32 @__C_specific_handler(...) 167*9880d681SAndroid Build Coastguard Workerdeclare i32 @llvm.eh.typeid.for(i8*) readnone nounwind 168*9880d681SAndroid Build Coastguard Workerdeclare void @puts(i8*) 169*9880d681SAndroid Build Coastguard Workerdeclare void @printf(i8*, ...) 170*9880d681SAndroid Build Coastguard Workerdeclare void @abort() 171