brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · 7ae1004 Raw
163 lines · plain
1; RUN: llc -mtriple i686-pc-windows-msvc < %s | FileCheck %s2 3; This test case is also intended to be run manually as a complete functional4; test. It should link, print something, and exit zero rather than crashing.5; It is the hypothetical lowering of a C source program that looks like:6;7;   int safe_div(int *n, int *d) {8;     int r;9;     __try {10;       __try {11;         r = *n / *d;12;       } __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) {13;         puts("EXCEPTION_ACCESS_VIOLATION");14;         r = -1;15;       }16;     } __except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO) {17;       puts("EXCEPTION_INT_DIVIDE_BY_ZERO");18;       r = -2;19;     }20;     return r;21;   }22 23@str1 = internal constant [27 x i8] c"EXCEPTION_ACCESS_VIOLATION\00"24@str2 = internal constant [29 x i8] c"EXCEPTION_INT_DIVIDE_BY_ZERO\00"25 26define i32 @safe_div(ptr %n, ptr %d) personality ptr @_except_handler3 {27entry:28  %r = alloca i32, align 429  store i32 42, ptr %r30  invoke void @try_body(ptr %r, ptr %n, ptr %d)31          to label %__try.cont unwind label %lpad032 33lpad0:34  %cs0 = catchswitch within none [label %handler0] unwind label %lpad135 36handler0:37  %p0 = catchpad within %cs0 [ptr @safe_div_filt0]38  call void @puts(ptr @str1) [ "funclet"(token %p0) ]39  store i32 -1, ptr %r, align 440  catchret from %p0 to label %__try.cont41 42lpad1:43  %cs1 = catchswitch within none [label %handler1] unwind to caller44 45handler1:46  %p1 = catchpad within %cs1 [ptr @safe_div_filt1]47  call void @puts(ptr @str2) [ "funclet"(token %p1) ]48  store i32 -2, ptr %r, align 449  catchret from %p1 to label %__try.cont50 51__try.cont:52  %safe_ret = load i32, ptr %r, align 453  ret i32 %safe_ret54}55 56; Normal path code57 58; CHECK: {{^}}_safe_div:59; CHECK: movl $42, [[rloc:.*\(%ebp\)]]60; CHECK: leal [[rloc]],61; CHECK: calll _try_body62; CHECK: [[cont_bb:LBB0_[0-9]+]]:63; CHECK: movl [[rloc]], %eax64; CHECK: retl65 66; Landing pad code67 68; CHECK: [[handler1:LBB0_[0-9]+]]: # %handler169; 	Restore SP70; CHECK: movl {{.*}}(%ebp), %esp71; CHECK: calll _puts72; CHECK: jmp [[cont_bb]]73 74; CHECK: [[handler0:LBB0_[0-9]+]]: # %handler075; 	Restore SP76; CHECK: movl {{.*}}(%ebp), %esp77; CHECK: calll _puts78; CHECK: jmp [[cont_bb]]79 80; CHECK: .section .xdata,"dr"81; CHECK: L__ehtable$safe_div:82; CHECK-NEXT: .long -183; CHECK-NEXT: .long _safe_div_filt184; CHECK-NEXT: .long [[handler1]]85; CHECK-NEXT: .long 086; CHECK-NEXT: .long _safe_div_filt087; CHECK-NEXT: .long [[handler0]]88 89define void @try_body(ptr %r, ptr %n, ptr %d) {90entry:91  %0 = load i32, ptr %n, align 492  %1 = load i32, ptr %d, align 493  %div = sdiv i32 %0, %194  store i32 %div, ptr %r, align 495  ret void96}97 98; The prototype of these filter functions is:99; int filter(EXCEPTION_POINTERS *eh_ptrs, ptr rbp);100 101; The definition of EXCEPTION_POINTERS is:102;   typedef struct _EXCEPTION_POINTERS {103;     EXCEPTION_RECORD *ExceptionRecord;104;     CONTEXT          *ContextRecord;105;   } EXCEPTION_POINTERS;106 107; The definition of EXCEPTION_RECORD is:108;   typedef struct _EXCEPTION_RECORD {109;     DWORD ExceptionCode;110;     ...111;   } EXCEPTION_RECORD;112 113define i32 @safe_div_filt0() {114  %ebp = call ptr @llvm.frameaddress(i32 1)115  %eh_ptrs.addr.i8 = getelementptr inbounds i8, ptr %ebp, i32 -20116  %eh_ptrs = load ptr, ptr %eh_ptrs.addr.i8117  %eh_rec = load ptr, ptr %eh_ptrs118  %eh_code = load i32, ptr %eh_rec119  ; EXCEPTION_ACCESS_VIOLATION = 0xC0000005120  %cmp = icmp eq i32 %eh_code, 3221225477121  %filt.res = zext i1 %cmp to i32122  ret i32 %filt.res123}124define i32 @safe_div_filt1() {125  %ebp = call ptr @llvm.frameaddress(i32 1)126  %eh_ptrs.addr.i8 = getelementptr inbounds i8, ptr %ebp, i32 -20127  %eh_ptrs = load ptr, ptr %eh_ptrs.addr.i8128  %eh_rec = load ptr, ptr %eh_ptrs129  %eh_code = load i32, ptr %eh_rec130  ; EXCEPTION_INT_DIVIDE_BY_ZERO = 0xC0000094131  %cmp = icmp eq i32 %eh_code, 3221225620132  %filt.res = zext i1 %cmp to i32133  ret i32 %filt.res134}135 136@str_result = internal constant [21 x i8] c"safe_div result: %d\0A\00"137 138define i32 @main() {139  %d.addr = alloca i32, align 4140  %n.addr = alloca i32, align 4141 142  store i32 10, ptr %n.addr, align 4143  store i32 2, ptr %d.addr, align 4144  %r1 = call i32 @safe_div(ptr %n.addr, ptr %d.addr)145  call void (ptr, ...) @printf(ptr @str_result, i32 %r1)146 147  store i32 10, ptr %n.addr, align 4148  store i32 0, ptr %d.addr, align 4149  %r2 = call i32 @safe_div(ptr %n.addr, ptr %d.addr)150  call void (ptr, ...) @printf(ptr @str_result, i32 %r2)151 152  %r3 = call i32 @safe_div(ptr %n.addr, ptr null)153  call void (ptr, ...) @printf(ptr @str_result, i32 %r3)154  ret i32 0155}156 157declare i32 @_except_handler3(...)158declare i32 @llvm.eh.typeid.for(ptr) readnone nounwind159declare void @puts(ptr)160declare void @printf(ptr, ...)161declare void @abort()162declare ptr @llvm.frameaddress(i32)163