mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-02 18:26:04 +00:00

Summary: Now that there is a one-to-one mapping from MachineFunction to WinEHFuncInfo, we don't need to use a DenseMap to select the right WinEHFuncInfo for the current funclet. The main challenge here is that X86WinEHStatePass is an IR pass that doesn't have access to the MachineFunction. I gave it its own WinEHFuncInfo object that it uses to calculate state numbers, which it then throws away. As long as nobody creates or removes EH pads between this pass and SDAG construction, we will get the same state numbers. The other thing X86WinEHStatePass does is to mark the EH registration node. Instead of communicating which alloca was the registration through WinEHFuncInfo, I added the llvm.x86.seh.ehregnode intrinsic. This intrinsic generates no code and simply marks the alloca in use. Reviewers: JCTremoulet Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D14668 llvm-svn: 253378
101 lines
3.4 KiB
LLVM
101 lines
3.4 KiB
LLVM
; RUN: llc -mtriple=i686-windows-msvc < %s | FileCheck %s
|
|
|
|
; 32-bit catch-all has to use a filter function because that's how it saves the
|
|
; exception code.
|
|
|
|
@str = linkonce_odr unnamed_addr constant [27 x i8] c"GetExceptionCode(): 0x%lx\0A\00", align 1
|
|
|
|
declare i32 @_except_handler3(...)
|
|
declare void @crash()
|
|
declare i32 @printf(i8* nocapture readonly, ...) nounwind
|
|
declare i32 @llvm.eh.typeid.for(i8*)
|
|
declare i8* @llvm.frameaddress(i32)
|
|
declare i8* @llvm.localrecover(i8*, i8*, i32)
|
|
declare void @llvm.localescape(...)
|
|
declare i8* @llvm.x86.seh.recoverfp(i8*, i8*)
|
|
|
|
define i32 @main() personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
|
|
entry:
|
|
%__exceptioncode = alloca i32, align 4
|
|
call void (...) @llvm.localescape(i32* %__exceptioncode)
|
|
invoke void @crash() #5
|
|
to label %__try.cont unwind label %lpad
|
|
|
|
lpad: ; preds = %entry
|
|
%p = catchpad [i8* bitcast (i32 ()* @"filt$main" to i8*)]
|
|
to label %__except unwind label %endpad
|
|
|
|
__except: ; preds = %lpad
|
|
%code = load i32, i32* %__exceptioncode, align 4
|
|
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %code) #4
|
|
catchret %p to label %__try.cont
|
|
|
|
endpad: ; preds = %lpad
|
|
catchendpad unwind to caller
|
|
|
|
__try.cont: ; preds = %entry, %__except
|
|
ret i32 0
|
|
}
|
|
|
|
define internal i32 @"filt$main"() {
|
|
entry:
|
|
%ebp = tail call i8* @llvm.frameaddress(i32 1)
|
|
%parentfp = tail call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @main to i8*), i8* %ebp)
|
|
%code.i8 = tail call i8* @llvm.localrecover(i8* bitcast (i32 ()* @main to i8*), i8* %parentfp, i32 0)
|
|
%__exceptioncode = bitcast i8* %code.i8 to i32*
|
|
%info.addr = getelementptr inbounds i8, i8* %ebp, i32 -20
|
|
%0 = bitcast i8* %info.addr to i32***
|
|
%1 = load i32**, i32*** %0, align 4
|
|
%2 = load i32*, i32** %1, align 4
|
|
%3 = load i32, i32* %2, align 4
|
|
store i32 %3, i32* %__exceptioncode, align 4
|
|
ret i32 1
|
|
}
|
|
|
|
; Check that we can get the exception code from eax to the printf.
|
|
|
|
; CHECK-LABEL: _main:
|
|
; CHECK: pushl %ebp
|
|
; CHECK: movl %esp, %ebp
|
|
; Ensure that we push *all* the CSRs, since they are clobbered by the
|
|
; __except block.
|
|
; CHECK: pushl %ebx
|
|
; CHECK: pushl %edi
|
|
; CHECK: pushl %esi
|
|
|
|
; CHECK: Lmain$frame_escape_0 = [[code_offs:[-0-9]+]]
|
|
; CHECK: movl %esp, [[reg_offs:[-0-9]+]](%ebp)
|
|
; CHECK: movl $L__ehtable$main,
|
|
; EH state 0
|
|
; CHECK: movl $0, -16(%ebp)
|
|
; CHECK: calll _crash
|
|
; CHECK: popl %esi
|
|
; CHECK: popl %edi
|
|
; CHECK: popl %ebx
|
|
; CHECK: retl
|
|
; CHECK: LBB0_[[lpbb:[0-9]+]]: # %lpad{{$}}
|
|
; stackrestore
|
|
; CHECK: movl -24(%ebp), %esp
|
|
; EH state -1
|
|
; CHECK: movl [[code_offs]](%ebp), %[[code:[a-z]+]]
|
|
; CHECK-DAG: movl %[[code]], 4(%esp)
|
|
; CHECK-DAG: movl $_str, (%esp)
|
|
; CHECK: calll _printf
|
|
|
|
; CHECK: .section .xdata,"dr"
|
|
; CHECK: Lmain$parent_frame_offset = [[reg_offs]]
|
|
; CHECK: .align 4
|
|
; CHECK: L__ehtable$main
|
|
; CHECK-NEXT: .long -1
|
|
; CHECK-NEXT: .long _filt$main
|
|
; CHECK-NEXT: .long LBB0_[[lpbb]]
|
|
|
|
; CHECK-LABEL: _filt$main:
|
|
; CHECK: pushl %ebp
|
|
; CHECK: movl %esp, %ebp
|
|
; CHECK: movl (%ebp), %[[oldebp:[a-z]+]]
|
|
; CHECK: movl -20(%[[oldebp]]), %[[ehinfo:[a-z]+]]
|
|
; CHECK: movl (%[[ehinfo]]), %[[ehrec:[a-z]+]]
|
|
; CHECK: movl (%[[ehrec]]), %[[ehcode:[a-z]+]]
|
|
; CHECK: movl %[[ehcode]], {{.*}}(%{{.*}})
|