Home | History | Annotate | Download | only in WinEH
      1 ; RUN: opt -mtriple=i686-pc-windows-msvc -S -x86-winehstate  < %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 %rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] }
      7 %eh.CatchableType = type { i32, i8*, i32, i32, i32, i32, i8* }
      8 %eh.CatchableTypeArray.1 = type { i32, [1 x %eh.CatchableType*] }
      9 %eh.ThrowInfo = type { i32, i8*, i8*, i8* }
     10 
     11 $"\01??_R0H@8" = comdat any
     12 
     13 $"_CT??_R0H@84" = comdat any
     14 
     15 $_CTA1H = comdat any
     16 
     17 $_TI1H = comdat any
     18 
     19 @"\01??_7type_info@@6B@" = external constant i8*
     20 @"\01??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
     21 @"_CT??_R0H@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i32 -1, i32 0, i32 4, i8* null }, section ".xdata", comdat
     22 @_CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0H@84"] }, section ".xdata", comdat
     23 @_TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @_CTA1H to i8*) }, section ".xdata", comdat
     24 
     25 define i32 @main() #0 personality i32 (...)* @__CxxFrameHandler3 {
     26 entry:
     27   %tmp = alloca i32, align 4
     28   ; CHECK: entry:
     29   ; CHECK:   store i32 -1
     30   ; CHECK:   call void @g(i32 3)
     31   ; CHECK-NEXT:   call void @g(i32 4)
     32   ; CHECK-NEXT:   call void @g(i32 5)
     33   call void @g(i32 3)
     34   call void @g(i32 4)
     35   call void @g(i32 5)
     36   store i32 0, i32* %tmp, align 4
     37   %0 = bitcast i32* %tmp to i8*
     38   ; CHECK:   store i32 0
     39   ; CHECK:   invoke void @_CxxThrowException(
     40   invoke void @_CxxThrowException(i8* %0, %eh.ThrowInfo* nonnull @_TI1H) #1
     41           to label %unreachable.for.entry unwind label %catch.dispatch
     42 
     43 catch.dispatch:                                   ; preds = %entry
     44   %cs1 = catchswitch within none [label %catch] unwind to caller
     45 
     46 catch:                                            ; preds = %catch.dispatch
     47   %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
     48   ; CHECK: catch:
     49   ; CHECK:   store i32 2
     50   ; CHECK:   invoke void @_CxxThrowException(
     51   invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) [ "funclet"(token %1) ]
     52           to label %unreachable unwind label %catch.dispatch.1
     53 
     54 catch.dispatch.1:                                 ; preds = %catch
     55   %cs2 = catchswitch within %1 [label %catch.3] unwind to caller
     56 catch.3:                                          ; preds = %catch.dispatch.1
     57   %2 = catchpad within %cs2 [i8* null, i32 u0x40, i8* null]
     58   ; CHECK: catch.3:
     59   ; CHECK:   store i32 3
     60   ; CHECK:   call void @g(i32 1)
     61   ; CHECK-NEXT:   call void @g(i32 2)
     62   ; CHECK-NEXT:   call void @g(i32 3)
     63   call void @g(i32 1)
     64   call void @g(i32 2)
     65   call void @g(i32 3)
     66   catchret from %2 to label %try.cont
     67 
     68 try.cont:                                         ; preds = %catch.3
     69   ; CHECK: try.cont:
     70   ; CHECK:   store i32 1
     71   ; CHECK:   call void @g(i32 2)
     72   ; CHECK-NEXT:   call void @g(i32 3)
     73   ; CHECK-NEXT:   call void @g(i32 4)
     74   call void @g(i32 2)
     75   call void @g(i32 3)
     76   call void @g(i32 4)
     77   unreachable
     78 
     79 unreachable:                                      ; preds = %catch
     80   unreachable
     81 
     82 unreachable.for.entry:                            ; preds = %entry
     83   unreachable
     84 }
     85 
     86 define i32 @nopads() #0 personality i32 (...)* @__CxxFrameHandler3 {
     87   ret i32 0
     88 }
     89 
     90 ; CHECK-LABEL: define i32 @nopads()
     91 ; CHECK-NEXT: ret i32 0
     92 ; CHECK-NOT: __ehhandler$nopads
     93 
     94 ; CHECK-LABEL: define void @PR25926()
     95 define void @PR25926() personality i32 (...)* @__CxxFrameHandler3 {
     96 entry:
     97   ; CHECK: entry:
     98   ; CHECK:   store i32 -1
     99   ; CHECK:   store i32 0
    100   ; CHECK:   invoke void @_CxxThrowException(
    101   invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null)
    102           to label %unreachable unwind label %catch.dispatch
    103 
    104 catch.dispatch:                                   ; preds = %entry
    105   %0 = catchswitch within none [label %catch] unwind to caller
    106 
    107 catch:                                            ; preds = %catch.dispatch
    108   %1 = catchpad within %0 [i8* null, i32 64, i8* null]
    109   ; CHECK: catch:
    110   ; CHECK:   store i32 3
    111   ; CHECK:   invoke void @_CxxThrowException(
    112   invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) [ "funclet"(token %1) ]
    113           to label %unreachable1 unwind label %catch.dispatch1
    114 
    115 catch.dispatch1:                                  ; preds = %catch
    116   %2 = catchswitch within %1 [label %catch2] unwind label %ehcleanup
    117 
    118 catch2:                                           ; preds = %catch.dispatch1
    119   %3 = catchpad within %2 [i8* null, i32 64, i8* null]
    120   catchret from %3 to label %try.cont
    121 
    122 try.cont:                                         ; preds = %catch2
    123   ; CHECK: try.cont:
    124   ; CHECK:   store i32 1
    125   ; CHECK:   call void @dtor()
    126   ; CHECK-NEXT:   call void @dtor()
    127   ; CHECK-NEXT:   call void @dtor()
    128   call void @dtor() #3 [ "funclet"(token %1) ]
    129   call void @dtor() #3 [ "funclet"(token %1) ]
    130   call void @dtor() #3 [ "funclet"(token %1) ]
    131   catchret from %1 to label %try.cont4
    132 
    133 try.cont4:                                        ; preds = %try.cont
    134   ret void
    135 
    136 ehcleanup:                                        ; preds = %catch.dispatch1
    137   %4 = cleanuppad within %1 []
    138   ; CHECK: ehcleanup:
    139   ; CHECK:   call void @dtor()
    140   call void @dtor() #3 [ "funclet"(token %4) ]
    141   cleanupret from %4 unwind to caller
    142 
    143 unreachable:                                      ; preds = %entry
    144   unreachable
    145 
    146 unreachable1:                                     ; preds = %catch
    147   unreachable
    148 }
    149 
    150 ; CHECK-LABEL: define void @required_state_store(
    151 define void @required_state_store(i1 zeroext %cond) personality i32 (...)* @_except_handler3 {
    152 entry:
    153   %__exception_code = alloca i32, align 4
    154   call void (...) @llvm.localescape(i32* nonnull %__exception_code)
    155 ; CHECK:   store i32 -1
    156 ; CHECK:   call void @g(i32 0)
    157   call void @g(i32 0)
    158   br i1 %cond, label %if.then, label %if.end
    159 
    160 if.then:                                          ; preds = %entry
    161 ; CHECK:        store i32 0
    162 ; CHECK-NEXT:   invoke void @g(i32 1)
    163   invoke void @g(i32 1)
    164           to label %if.end unwind label %catch.dispatch
    165 
    166 catch.dispatch:                                   ; preds = %if.then
    167   %0 = catchswitch within none [label %__except.ret] unwind to caller
    168 
    169 __except.ret:                                     ; preds = %catch.dispatch
    170   %1 = catchpad within %0 [i8* bitcast (i32 ()* @"\01?filt$0@0@required_state_store@@" to i8*)]
    171   catchret from %1 to label %if.end
    172 
    173 if.end:                                           ; preds = %if.then, %__except.ret, %entry
    174 ; CHECK:        store i32 -1
    175 ; CHECK-NEXT:   call void @dtor()
    176   call void @dtor()
    177   ret void
    178 }
    179 
    180 define internal i32 @"\01?filt$0@0@required_state_store@@"() {
    181 entry:
    182   %0 = tail call i8* @llvm.frameaddress(i32 1)
    183   %1 = tail call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void (i1)* @required_state_store to i8*), i8* %0)
    184   %2 = tail call i8* @llvm.localrecover(i8* bitcast (void (i1)* @required_state_store to i8*), i8* %1, i32 0)
    185   %__exception_code = bitcast i8* %2 to i32*
    186   %3 = getelementptr inbounds i8, i8* %0, i32 -20
    187   %4 = bitcast i8* %3 to { i32*, i8* }**
    188   %5 = load { i32*, i8* }*, { i32*, i8* }** %4, align 4
    189   %6 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %5, i32 0, i32 0
    190   %7 = load i32*, i32** %6, align 4
    191   %8 = load i32, i32* %7, align 4
    192   store i32 %8, i32* %__exception_code, align 4
    193   ret i32 1
    194 }
    195 
    196 declare void @g(i32) #0
    197 
    198 declare void @dtor()
    199 
    200 declare x86_stdcallcc void @_CxxThrowException(i8*, %eh.ThrowInfo*)
    201 
    202 declare i32 @__CxxFrameHandler3(...)
    203 
    204 declare i8* @llvm.frameaddress(i32)
    205 
    206 declare i8* @llvm.x86.seh.recoverfp(i8*, i8*)
    207 
    208 declare i8* @llvm.localrecover(i8*, i8*, i32)
    209 
    210 declare void @llvm.localescape(...)
    211 
    212 declare i32 @_except_handler3(...)
    213 
    214 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" }
    215 attributes #1 = { noreturn }
    216 
    217 !llvm.ident = !{!0}
    218 
    219 !0 = !{!"clang version 3.8.0 (trunk 245153) (llvm/trunk 245238)"}
    220