Home | History | Annotate | Download | only in WinEH
      1 ; RUN: opt -S -winehprepare -sehprepare -mtriple=x86_64-windows-msvc < %s | FileCheck %s
      2 
      3 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
      4 target triple = "x86_64-pc-windows-msvc"
      5 
      6 declare void @cleanup()
      7 declare i32 @filt()
      8 declare void @might_crash()
      9 declare i32 @__C_specific_handler(...)
     10 declare i32 @llvm.eh.typeid.for(i8*)
     11 
     12 define i32 @simple_except_store() {
     13 entry:
     14   %retval = alloca i32
     15   store i32 0, i32* %retval
     16   invoke void @might_crash()
     17           to label %return unwind label %lpad
     18 
     19 lpad:
     20   %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
     21           catch i32 ()* @filt
     22   %sel = extractvalue { i8*, i32 } %ehvals, 1
     23   %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
     24   %matches = icmp eq i32 %sel, %filt_sel
     25   br i1 %matches, label %__except, label %eh.resume
     26 
     27 __except:
     28   store i32 1, i32* %retval
     29   br label %return
     30 
     31 return:
     32   %r = load i32, i32* %retval
     33   ret i32 %r
     34 
     35 eh.resume:
     36   resume { i8*, i32 } %ehvals
     37 }
     38 
     39 ; CHECK-LABEL: define i32 @simple_except_store()
     40 ; CHECK: landingpad { i8*, i32 }
     41 ; CHECK-NEXT: catch i32 ()* @filt
     42 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@simple_except_store, %__except))
     43 ; CHECK-NEXT: indirectbr {{.*}} [label %__except]
     44 
     45 define i32 @catch_all() {
     46 entry:
     47   %retval = alloca i32
     48   store i32 0, i32* %retval
     49   invoke void @might_crash()
     50           to label %return unwind label %lpad
     51 
     52 lpad:
     53   %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
     54           catch i8* null
     55   store i32 1, i32* %retval
     56   br label %return
     57 
     58 return:
     59   %r = load i32, i32* %retval
     60   ret i32 %r
     61 }
     62 
     63 ; CHECK-LABEL: define i32 @catch_all()
     64 ; CHECK: landingpad { i8*, i32 }
     65 ; CHECK-NEXT: catch i8* null
     66 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* blockaddress(@catch_all, %catch.all))
     67 ; CHECK-NEXT: indirectbr {{.*}} [label %catch.all]
     68 ;
     69 ; CHECK: catch.all:
     70 ; CHECK: store i32 1, i32* %retval
     71 
     72 
     73 define i32 @except_phi() {
     74 entry:
     75   invoke void @might_crash()
     76           to label %return unwind label %lpad
     77 
     78 lpad:
     79   %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
     80           catch i32 ()* @filt
     81   %sel = extractvalue { i8*, i32 } %ehvals, 1
     82   %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
     83   %matches = icmp eq i32 %sel, %filt_sel
     84   br i1 %matches, label %return, label %eh.resume
     85 
     86 return:
     87   %r = phi i32 [0, %entry], [1, %lpad]
     88   ret i32 %r
     89 
     90 eh.resume:
     91   resume { i8*, i32 } %ehvals
     92 }
     93 
     94 ; CHECK-LABEL: define i32 @except_phi()
     95 ; CHECK: landingpad { i8*, i32 }
     96 ; CHECK-NEXT: catch i32 ()* @filt
     97 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@except_phi, %return))
     98 ; CHECK-NEXT: indirectbr {{.*}} [label %return]
     99 ;
    100 ; CHECK: return:
    101 ; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad1 ]
    102 ; CHECK-NEXT: ret i32 %r
    103 
    104 define i32 @cleanup_and_except() {
    105 entry:
    106   invoke void @might_crash()
    107           to label %return unwind label %lpad
    108 
    109 lpad:
    110   %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
    111           cleanup
    112           catch i32 ()* @filt
    113   call void @cleanup()
    114   %sel = extractvalue { i8*, i32 } %ehvals, 1
    115   %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
    116   %matches = icmp eq i32 %sel, %filt_sel
    117   br i1 %matches, label %return, label %eh.resume
    118 
    119 return:
    120   %r = phi i32 [0, %entry], [1, %lpad]
    121   ret i32 %r
    122 
    123 eh.resume:
    124   resume { i8*, i32 } %ehvals
    125 }
    126 
    127 ; CHECK-LABEL: define i32 @cleanup_and_except()
    128 ; CHECK: landingpad { i8*, i32 }
    129 ; CHECK-NEXT: cleanup
    130 ; CHECK-NEXT: catch i32 ()* @filt
    131 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(
    132 ; CHECK: i32 0, void (i8*, i8*)* @cleanup_and_except.cleanup,
    133 ; CHECK: i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@cleanup_and_except, %return))
    134 ; CHECK-NEXT: indirectbr {{.*}} [label %return]
    135 ;
    136 ; CHECK: return:
    137 ; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad1 ]
    138 ; CHECK-NEXT: ret i32 %r
    139