232 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			LLVM
		
	
	
	
			
		
		
	
	
			232 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			LLVM
		
	
	
	
; RUN: llc < %s | FileCheck %s
 | 
						|
 | 
						|
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
 | 
						|
target triple = "i686-pc-windows-msvc"
 | 
						|
 | 
						|
define void @try_except() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
 | 
						|
entry:
 | 
						|
  %__exception_code = alloca i32, align 4
 | 
						|
  call void (...) @llvm.localescape(i32* %__exception_code)
 | 
						|
  invoke void @f(i32 1) #3
 | 
						|
          to label %invoke.cont unwind label %catch.dispatch
 | 
						|
 | 
						|
catch.dispatch:                                   ; preds = %entry
 | 
						|
  %cs1 = catchswitch within none [label %__except.ret] unwind to caller
 | 
						|
 | 
						|
__except.ret:                                     ; preds = %catch.dispatch
 | 
						|
  %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
 | 
						|
  catchret from %0 to label %__except
 | 
						|
 | 
						|
__except:                                         ; preds = %__except.ret
 | 
						|
  call void @f(i32 2)
 | 
						|
  br label %__try.cont
 | 
						|
 | 
						|
__try.cont:                                       ; preds = %__except, %invoke.cont
 | 
						|
  call void @f(i32 3)
 | 
						|
  ret void
 | 
						|
 | 
						|
invoke.cont:                                      ; preds = %entry
 | 
						|
  br label %__try.cont
 | 
						|
}
 | 
						|
 | 
						|
; CHECK-LABEL: _try_except:
 | 
						|
;     Store state #0
 | 
						|
; CHECK: movl $0, -[[state:[0-9]+]](%ebp)
 | 
						|
; CHECK: pushl $1
 | 
						|
; CHECK: calll _f
 | 
						|
; CHECK: movl $-1, -[[state]](%ebp)
 | 
						|
; CHECK: pushl $3
 | 
						|
; CHECK: calll _f
 | 
						|
; CHECK: retl
 | 
						|
 | 
						|
;   __except
 | 
						|
; CHECK: movl $-1, -[[state]](%ebp)
 | 
						|
; CHECK: pushl $2
 | 
						|
; CHECK: calll _f
 | 
						|
 | 
						|
; CHECK: .section        .xdata,"dr"
 | 
						|
; CHECK: L__ehtable$try_except:
 | 
						|
; CHECK:         .long   -1                          # ToState
 | 
						|
; CHECK:         .long   _try_except_filter_catchall # Filter
 | 
						|
; CHECK:         .long   LBB0_1
 | 
						|
 | 
						|
define internal i32 @try_except_filter_catchall() #0 {
 | 
						|
entry:
 | 
						|
  %0 = call i8* @llvm.frameaddress(i32 1)
 | 
						|
  %1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @try_except to i8*), i8* %0)
 | 
						|
  %2 = call i8* @llvm.localrecover(i8* bitcast (void ()* @try_except to i8*), i8* %1, i32 0)
 | 
						|
  %__exception_code = bitcast i8* %2 to i32*
 | 
						|
  %3 = getelementptr inbounds i8, i8* %0, i32 -20
 | 
						|
  %4 = bitcast i8* %3 to i8**
 | 
						|
  %5 = load i8*, i8** %4, align 4
 | 
						|
  %6 = bitcast i8* %5 to { i32*, i8* }*
 | 
						|
  %7 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %6, i32 0, i32 0
 | 
						|
  %8 = load i32*, i32** %7, align 4
 | 
						|
  %9 = load i32, i32* %8, align 4
 | 
						|
  store i32 %9, i32* %__exception_code, align 4
 | 
						|
  ret i32 1
 | 
						|
}
 | 
						|
 | 
						|
define void @nested_exceptions() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
 | 
						|
entry:
 | 
						|
  %__exception_code = alloca i32, align 4
 | 
						|
  call void (...) @llvm.localescape(i32* %__exception_code)
 | 
						|
  invoke void @crash() #3
 | 
						|
          to label %__try.cont unwind label %catch.dispatch
 | 
						|
 | 
						|
catch.dispatch:                                   ; preds = %entry
 | 
						|
  %cs1 = catchswitch within none [label %__except.ret] unwind label %catch.dispatch.11
 | 
						|
 | 
						|
__except.ret:                                     ; preds = %catch.dispatch
 | 
						|
  %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
 | 
						|
  catchret from %0 to label %__try.cont
 | 
						|
 | 
						|
__try.cont:                                       ; preds = %entry, %__except.ret
 | 
						|
  invoke void @crash() #3
 | 
						|
          to label %__try.cont.9 unwind label %catch.dispatch.5
 | 
						|
 | 
						|
catch.dispatch.5:                                 ; preds = %__try.cont
 | 
						|
  %cs2 = catchswitch within none [label %__except.ret.7] unwind label %catch.dispatch.11
 | 
						|
 | 
						|
__except.ret.7:                                   ; preds = %catch.dispatch.5
 | 
						|
  %1 = catchpad within %cs2 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
 | 
						|
  catchret from %1 to label %__try.cont.9
 | 
						|
 | 
						|
__try.cont.9:                                     ; preds = %__try.cont, %__except.ret.7
 | 
						|
  invoke void @crash() #3
 | 
						|
          to label %__try.cont.15 unwind label %catch.dispatch.11
 | 
						|
 | 
						|
catch.dispatch.11:                                ; preds = %catchendblock, %catchendblock.6, %__try.cont.9
 | 
						|
  %cs3 = catchswitch within none [label %__except.ret.13] unwind label %catch.dispatch.17
 | 
						|
 | 
						|
__except.ret.13:                                  ; preds = %catch.dispatch.11
 | 
						|
  %2 = catchpad within %cs3 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
 | 
						|
  catchret from %2 to label %__try.cont.15
 | 
						|
 | 
						|
__try.cont.15:                                    ; preds = %__try.cont.9, %__except.ret.13
 | 
						|
  invoke void @crash() #3
 | 
						|
          to label %__try.cont.35 unwind label %catch.dispatch.17
 | 
						|
 | 
						|
catch.dispatch.17:                                ; preds = %catchendblock.12, %__try.cont.15
 | 
						|
  %cs4 = catchswitch within none [label %__except.ret.19] unwind to caller
 | 
						|
 | 
						|
__except.ret.19:                                  ; preds = %catch.dispatch.17
 | 
						|
  %3 = catchpad within %cs4 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
 | 
						|
  catchret from %3 to label %__except.20
 | 
						|
 | 
						|
__except.20:                                      ; preds = %__except.ret.19
 | 
						|
  invoke void @crash() #3
 | 
						|
          to label %__try.cont.27 unwind label %catch.dispatch.23
 | 
						|
 | 
						|
catch.dispatch.23:                                ; preds = %__except.20
 | 
						|
  %cs5 = catchswitch within none [label %__except.ret.25] unwind to caller
 | 
						|
 | 
						|
__except.ret.25:                                  ; preds = %catch.dispatch.23
 | 
						|
  %4 = catchpad within %cs5 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
 | 
						|
  catchret from %4 to label %__try.cont.27
 | 
						|
 | 
						|
__try.cont.27:                                    ; preds = %__except.20, %__except.ret.25
 | 
						|
  invoke void @crash() #3
 | 
						|
          to label %__try.cont.35 unwind label %catch.dispatch.30
 | 
						|
 | 
						|
catch.dispatch.30:                                ; preds = %__try.cont.27
 | 
						|
  %cs6 = catchswitch within none [label %__except.ret.32] unwind to caller
 | 
						|
 | 
						|
__except.ret.32:                                  ; preds = %catch.dispatch.30
 | 
						|
  %5 = catchpad within %cs6 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
 | 
						|
  catchret from %5 to label %__try.cont.35
 | 
						|
 | 
						|
__try.cont.35:                                    ; preds = %__try.cont.15, %__try.cont.27, %__except.ret.32
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
; This table is equivalent to the one produced by MSVC, even if it isn't in
 | 
						|
; quite the same order.
 | 
						|
 | 
						|
; CHECK-LABEL: _nested_exceptions:
 | 
						|
; CHECK: L__ehtable$nested_exceptions:
 | 
						|
; CHECK:         .long   -1
 | 
						|
; CHECK:         .long   _nested_exceptions_filter_catchall
 | 
						|
; CHECK:         .long   LBB
 | 
						|
; CHECK:         .long   0
 | 
						|
; CHECK:         .long   _nested_exceptions_filter_catchall
 | 
						|
; CHECK:         .long   LBB
 | 
						|
; CHECK:         .long   1
 | 
						|
; CHECK:         .long   _nested_exceptions_filter_catchall
 | 
						|
; CHECK:         .long   LBB
 | 
						|
; CHECK:         .long   1
 | 
						|
; CHECK:         .long   _nested_exceptions_filter_catchall
 | 
						|
; CHECK:         .long   LBB
 | 
						|
; CHECK:         .long   -1
 | 
						|
; CHECK:         .long   _nested_exceptions_filter_catchall
 | 
						|
; CHECK:         .long   LBB
 | 
						|
; CHECK:         .long   -1
 | 
						|
; CHECK:         .long   _nested_exceptions_filter_catchall
 | 
						|
; CHECK:         .long   LBB
 | 
						|
 | 
						|
declare void @crash() #0
 | 
						|
 | 
						|
define internal i32 @nested_exceptions_filter_catchall() #0 {
 | 
						|
entry:
 | 
						|
  %0 = call i8* @llvm.frameaddress(i32 1)
 | 
						|
  %1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @nested_exceptions to i8*), i8* %0)
 | 
						|
  %2 = call i8* @llvm.localrecover(i8* bitcast (void ()* @nested_exceptions to i8*), i8* %1, i32 0)
 | 
						|
  %__exception_code3 = bitcast i8* %2 to i32*
 | 
						|
  %3 = getelementptr inbounds i8, i8* %0, i32 -20
 | 
						|
  %4 = bitcast i8* %3 to i8**
 | 
						|
  %5 = load i8*, i8** %4, align 4
 | 
						|
  %6 = bitcast i8* %5 to { i32*, i8* }*
 | 
						|
  %7 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %6, i32 0, i32 0
 | 
						|
  %8 = load i32*, i32** %7, align 4
 | 
						|
  %9 = load i32, i32* %8, align 4
 | 
						|
  store i32 %9, i32* %__exception_code3, align 4
 | 
						|
  ret i32 1
 | 
						|
}
 | 
						|
 | 
						|
define void @code_in_catchpad() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
 | 
						|
entry:
 | 
						|
  invoke void @f(i32 1) #3
 | 
						|
          to label %__except unwind label %catch.dispatch
 | 
						|
 | 
						|
catch.dispatch:                                   ; preds = %entry
 | 
						|
  %cs1 = catchswitch within none [label %__except.ret] unwind to caller
 | 
						|
 | 
						|
__except.ret:                                     ; preds = %catch.dispatch
 | 
						|
  %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
 | 
						|
  call void @f(i32 2) [ "funclet"(token %0) ]
 | 
						|
  catchret from %0 to label %__except
 | 
						|
 | 
						|
__except:
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
; CHECK-LABEL: _code_in_catchpad:
 | 
						|
; CHECK: # %__except.ret
 | 
						|
; CHECK-NEXT:         movl    -24(%ebp), %esp
 | 
						|
; CHECK-NEXT:         addl    $12, %ebp
 | 
						|
; CHECK-NEXT:         movl    $-1, -16(%ebp)
 | 
						|
; CHECK-NEXT:         pushl   $2
 | 
						|
; CHECK-NEXT:         calll   _f
 | 
						|
 | 
						|
 | 
						|
; Function Attrs: nounwind readnone
 | 
						|
declare i8* @llvm.frameaddress(i32) #1
 | 
						|
 | 
						|
; Function Attrs: nounwind readnone
 | 
						|
declare i8* @llvm.x86.seh.recoverfp(i8*, i8*) #1
 | 
						|
 | 
						|
; Function Attrs: nounwind readnone
 | 
						|
declare i8* @llvm.localrecover(i8*, i8*, i32) #1
 | 
						|
 | 
						|
declare void @f(i32) #0
 | 
						|
 | 
						|
declare i32 @_except_handler3(...)
 | 
						|
 | 
						|
; Function Attrs: nounwind
 | 
						|
declare void @llvm.localescape(...) #2
 | 
						|
 | 
						|
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" }
 | 
						|
attributes #1 = { nounwind readnone }
 | 
						|
attributes #2 = { nounwind }
 | 
						|
attributes #3 = { noinline }
 |