Home | History | Annotate | Download | only in X86
      1 ; RUN: llc < %s | FileCheck %s
      2 
      3 target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
      4 target triple = "i686-pc-windows-msvc"
      5 
      6 define void @try_except() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
      7 entry:
      8   %__exception_code = alloca i32, align 4
      9   call void (...) @llvm.localescape(i32* %__exception_code)
     10   invoke void @f(i32 1) #3
     11           to label %invoke.cont unwind label %catch.dispatch
     12 
     13 catch.dispatch:                                   ; preds = %entry
     14   %cs1 = catchswitch within none [label %__except.ret] unwind to caller
     15 
     16 __except.ret:                                     ; preds = %catch.dispatch
     17   %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
     18   catchret from %0 to label %__except
     19 
     20 __except:                                         ; preds = %__except.ret
     21   call void @f(i32 2)
     22   br label %__try.cont
     23 
     24 __try.cont:                                       ; preds = %__except, %invoke.cont
     25   call void @f(i32 3)
     26   ret void
     27 
     28 invoke.cont:                                      ; preds = %entry
     29   br label %__try.cont
     30 }
     31 
     32 ; CHECK-LABEL: _try_except:
     33 ;     Store state #0
     34 ; CHECK: movl $0, -[[state:[0-9]+]](%ebp)
     35 ; CHECK: movl $1, (%esp)
     36 ; CHECK: calll _f
     37 ; CHECK: movl $-1, -[[state]](%ebp)
     38 ; CHECK: movl $3, (%esp)
     39 ; CHECK: calll _f
     40 ; CHECK: retl
     41 
     42 ;   __except
     43 ; CHECK: movl $-1, -[[state]](%ebp)
     44 ; CHECK: movl $2, (%esp)
     45 ; CHECK: calll _f
     46 
     47 ; CHECK: .section        .xdata,"dr"
     48 ; CHECK: L__ehtable$try_except:
     49 ; CHECK:         .long   -1
     50 ; CHECK:         .long   _try_except_filter_catchall
     51 ; CHECK:         .long   LBB0_1
     52 
     53 define internal i32 @try_except_filter_catchall() #0 {
     54 entry:
     55   %0 = call i8* @llvm.frameaddress(i32 1)
     56   %1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @try_except to i8*), i8* %0)
     57   %2 = call i8* @llvm.localrecover(i8* bitcast (void ()* @try_except to i8*), i8* %1, i32 0)
     58   %__exception_code = bitcast i8* %2 to i32*
     59   %3 = getelementptr inbounds i8, i8* %0, i32 -20
     60   %4 = bitcast i8* %3 to i8**
     61   %5 = load i8*, i8** %4, align 4
     62   %6 = bitcast i8* %5 to { i32*, i8* }*
     63   %7 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %6, i32 0, i32 0
     64   %8 = load i32*, i32** %7, align 4
     65   %9 = load i32, i32* %8, align 4
     66   store i32 %9, i32* %__exception_code, align 4
     67   ret i32 1
     68 }
     69 
     70 define void @nested_exceptions() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
     71 entry:
     72   %__exception_code = alloca i32, align 4
     73   call void (...) @llvm.localescape(i32* %__exception_code)
     74   invoke void @crash() #3
     75           to label %__try.cont unwind label %catch.dispatch
     76 
     77 catch.dispatch:                                   ; preds = %entry
     78   %cs1 = catchswitch within none [label %__except.ret] unwind label %catch.dispatch.11
     79 
     80 __except.ret:                                     ; preds = %catch.dispatch
     81   %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
     82   catchret from %0 to label %__try.cont
     83 
     84 __try.cont:                                       ; preds = %entry, %__except.ret
     85   invoke void @crash() #3
     86           to label %__try.cont.9 unwind label %catch.dispatch.5
     87 
     88 catch.dispatch.5:                                 ; preds = %__try.cont
     89   %cs2 = catchswitch within none [label %__except.ret.7] unwind label %catch.dispatch.11
     90 
     91 __except.ret.7:                                   ; preds = %catch.dispatch.5
     92   %1 = catchpad within %cs2 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
     93   catchret from %1 to label %__try.cont.9
     94 
     95 __try.cont.9:                                     ; preds = %__try.cont, %__except.ret.7
     96   invoke void @crash() #3
     97           to label %__try.cont.15 unwind label %catch.dispatch.11
     98 
     99 catch.dispatch.11:                                ; preds = %catchendblock, %catchendblock.6, %__try.cont.9
    100   %cs3 = catchswitch within none [label %__except.ret.13] unwind label %catch.dispatch.17
    101 
    102 __except.ret.13:                                  ; preds = %catch.dispatch.11
    103   %2 = catchpad within %cs3 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
    104   catchret from %2 to label %__try.cont.15
    105 
    106 __try.cont.15:                                    ; preds = %__try.cont.9, %__except.ret.13
    107   invoke void @crash() #3
    108           to label %__try.cont.35 unwind label %catch.dispatch.17
    109 
    110 catch.dispatch.17:                                ; preds = %catchendblock.12, %__try.cont.15
    111   %cs4 = catchswitch within none [label %__except.ret.19] unwind to caller
    112 
    113 __except.ret.19:                                  ; preds = %catch.dispatch.17
    114   %3 = catchpad within %cs4 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
    115   catchret from %3 to label %__except.20
    116 
    117 __except.20:                                      ; preds = %__except.ret.19
    118   invoke void @crash() #3
    119           to label %__try.cont.27 unwind label %catch.dispatch.23
    120 
    121 catch.dispatch.23:                                ; preds = %__except.20
    122   %cs5 = catchswitch within none [label %__except.ret.25] unwind to caller
    123 
    124 __except.ret.25:                                  ; preds = %catch.dispatch.23
    125   %4 = catchpad within %cs5 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
    126   catchret from %4 to label %__try.cont.27
    127 
    128 __try.cont.27:                                    ; preds = %__except.20, %__except.ret.25
    129   invoke void @crash() #3
    130           to label %__try.cont.35 unwind label %catch.dispatch.30
    131 
    132 catch.dispatch.30:                                ; preds = %__try.cont.27
    133   %cs6 = catchswitch within none [label %__except.ret.32] unwind to caller
    134 
    135 __except.ret.32:                                  ; preds = %catch.dispatch.30
    136   %5 = catchpad within %cs6 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
    137   catchret from %5 to label %__try.cont.35
    138 
    139 __try.cont.35:                                    ; preds = %__try.cont.15, %__try.cont.27, %__except.ret.32
    140   ret void
    141 }
    142 
    143 ; This table is equivalent to the one produced by MSVC, even if it isn't in
    144 ; quite the same order.
    145 
    146 ; CHECK-LABEL: _nested_exceptions:
    147 ; CHECK: L__ehtable$nested_exceptions:
    148 ; CHECK:         .long   -1
    149 ; CHECK:         .long   _nested_exceptions_filter_catchall
    150 ; CHECK:         .long   LBB
    151 ; CHECK:         .long   0
    152 ; CHECK:         .long   _nested_exceptions_filter_catchall
    153 ; CHECK:         .long   LBB
    154 ; CHECK:         .long   1
    155 ; CHECK:         .long   _nested_exceptions_filter_catchall
    156 ; CHECK:         .long   LBB
    157 ; CHECK:         .long   1
    158 ; CHECK:         .long   _nested_exceptions_filter_catchall
    159 ; CHECK:         .long   LBB
    160 ; CHECK:         .long   -1
    161 ; CHECK:         .long   _nested_exceptions_filter_catchall
    162 ; CHECK:         .long   LBB
    163 ; CHECK:         .long   -1
    164 ; CHECK:         .long   _nested_exceptions_filter_catchall
    165 ; CHECK:         .long   LBB
    166 
    167 declare void @crash() #0
    168 
    169 define internal i32 @nested_exceptions_filter_catchall() #0 {
    170 entry:
    171   %0 = call i8* @llvm.frameaddress(i32 1)
    172   %1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @nested_exceptions to i8*), i8* %0)
    173   %2 = call i8* @llvm.localrecover(i8* bitcast (void ()* @nested_exceptions to i8*), i8* %1, i32 0)
    174   %__exception_code3 = bitcast i8* %2 to i32*
    175   %3 = getelementptr inbounds i8, i8* %0, i32 -20
    176   %4 = bitcast i8* %3 to i8**
    177   %5 = load i8*, i8** %4, align 4
    178   %6 = bitcast i8* %5 to { i32*, i8* }*
    179   %7 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %6, i32 0, i32 0
    180   %8 = load i32*, i32** %7, align 4
    181   %9 = load i32, i32* %8, align 4
    182   store i32 %9, i32* %__exception_code3, align 4
    183   ret i32 1
    184 }
    185 
    186 define void @code_in_catchpad() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
    187 entry:
    188   invoke void @f(i32 1) #3
    189           to label %__except unwind label %catch.dispatch
    190 
    191 catch.dispatch:                                   ; preds = %entry
    192   %cs1 = catchswitch within none [label %__except.ret] unwind to caller
    193 
    194 __except.ret:                                     ; preds = %catch.dispatch
    195   %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
    196   call void @f(i32 2) [ "funclet"(token %0) ]
    197   catchret from %0 to label %__except
    198 
    199 __except:
    200   ret void
    201 }
    202 
    203 ; CHECK-LABEL: _code_in_catchpad:
    204 ; CHECK: # %__except.ret
    205 ; CHECK-NEXT:         movl    -24(%ebp), %esp
    206 ; CHECK-NEXT:         addl    $12, %ebp
    207 ; CHECK-NEXT:         movl    $-1, -16(%ebp)
    208 ; CHECK-NEXT:         movl    $2, (%esp)
    209 ; CHECK-NEXT:         calll   _f
    210 
    211 
    212 ; Function Attrs: nounwind readnone
    213 declare i8* @llvm.frameaddress(i32) #1
    214 
    215 ; Function Attrs: nounwind readnone
    216 declare i8* @llvm.x86.seh.recoverfp(i8*, i8*) #1
    217 
    218 ; Function Attrs: nounwind readnone
    219 declare i8* @llvm.localrecover(i8*, i8*, i32) #1
    220 
    221 declare void @f(i32) #0
    222 
    223 declare i32 @_except_handler3(...)
    224 
    225 ; Function Attrs: nounwind
    226 declare void @llvm.localescape(...) #2
    227 
    228 attributes #0 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
    229 attributes #1 = { nounwind readnone }
    230 attributes #2 = { nounwind }
    231 attributes #3 = { noinline }
    232