2015-06-12 06:32:23 +08:00
|
|
|
; 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)
|
Rename llvm.frameescape and llvm.framerecover to localescape and localrecover
Summary:
Initially, these intrinsics seemed like part of a family of "frame"
related intrinsics, but now I think that's more confusing than helpful.
Initially, the LangRef specified that this would create a new kind of
allocation that would be allocated at a fixed offset from the frame
pointer (EBP/RBP). We ended up dropping that design, and leaving the
stack frame layout alone.
These intrinsics are really about sharing local stack allocations, not
frame pointers. I intend to go further and add an `llvm.localaddress()`
intrinsic that returns whatever register (EBP, ESI, ESP, RBX) is being
used to address locals, which should not be confused with the frame
pointer.
Naming suggestions at this point are welcome, I'm happy to re-run sed.
Reviewers: majnemer, nicholas
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D11011
llvm-svn: 241633
2015-07-08 06:25:32 +08:00
|
|
|
declare i8* @llvm.localrecover(i8*, i8*, i32)
|
|
|
|
declare void @llvm.localescape(...)
|
2015-07-01 06:46:59 +08:00
|
|
|
declare i8* @llvm.x86.seh.recoverfp(i8*, i8*)
|
2015-06-12 06:32:23 +08:00
|
|
|
|
2015-06-18 04:52:32 +08:00
|
|
|
define i32 @main() personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
|
2015-06-12 06:32:23 +08:00
|
|
|
entry:
|
|
|
|
%__exceptioncode = alloca i32, align 4
|
Rename llvm.frameescape and llvm.framerecover to localescape and localrecover
Summary:
Initially, these intrinsics seemed like part of a family of "frame"
related intrinsics, but now I think that's more confusing than helpful.
Initially, the LangRef specified that this would create a new kind of
allocation that would be allocated at a fixed offset from the frame
pointer (EBP/RBP). We ended up dropping that design, and leaving the
stack frame layout alone.
These intrinsics are really about sharing local stack allocations, not
frame pointers. I intend to go further and add an `llvm.localaddress()`
intrinsic that returns whatever register (EBP, ESI, ESP, RBX) is being
used to address locals, which should not be confused with the frame
pointer.
Naming suggestions at this point are welcome, I'm happy to re-run sed.
Reviewers: majnemer, nicholas
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D11011
llvm-svn: 241633
2015-07-08 06:25:32 +08:00
|
|
|
call void (...) @llvm.localescape(i32* %__exceptioncode)
|
2015-06-12 06:32:23 +08:00
|
|
|
invoke void @crash() #5
|
|
|
|
to label %__try.cont unwind label %lpad
|
|
|
|
|
|
|
|
lpad: ; preds = %entry
|
2015-06-18 04:52:32 +08:00
|
|
|
%0 = landingpad { i8*, i32 }
|
2015-06-12 06:32:23 +08:00
|
|
|
catch i8* bitcast (i32 ()* @"filt$main" to i8*)
|
|
|
|
%1 = extractvalue { i8*, i32 } %0, 1
|
|
|
|
%2 = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @"filt$main" to i8*)) #4
|
|
|
|
%matches = icmp eq i32 %1, %2
|
|
|
|
br i1 %matches, label %__except, label %eh.resume
|
|
|
|
|
|
|
|
__except: ; preds = %lpad
|
|
|
|
%3 = 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 %3) #4
|
|
|
|
br label %__try.cont
|
|
|
|
|
|
|
|
__try.cont: ; preds = %entry, %__except
|
|
|
|
ret i32 0
|
|
|
|
|
|
|
|
eh.resume: ; preds = %lpad
|
|
|
|
resume { i8*, i32 } %0
|
|
|
|
}
|
|
|
|
|
|
|
|
define internal i32 @"filt$main"() {
|
|
|
|
entry:
|
2015-07-01 06:46:59 +08:00
|
|
|
%ebp = tail call i8* @llvm.frameaddress(i32 1)
|
|
|
|
%parentfp = tail call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @main to i8*), i8* %ebp)
|
Rename llvm.frameescape and llvm.framerecover to localescape and localrecover
Summary:
Initially, these intrinsics seemed like part of a family of "frame"
related intrinsics, but now I think that's more confusing than helpful.
Initially, the LangRef specified that this would create a new kind of
allocation that would be allocated at a fixed offset from the frame
pointer (EBP/RBP). We ended up dropping that design, and leaving the
stack frame layout alone.
These intrinsics are really about sharing local stack allocations, not
frame pointers. I intend to go further and add an `llvm.localaddress()`
intrinsic that returns whatever register (EBP, ESI, ESP, RBX) is being
used to address locals, which should not be confused with the frame
pointer.
Naming suggestions at this point are welcome, I'm happy to re-run sed.
Reviewers: majnemer, nicholas
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D11011
llvm-svn: 241633
2015-07-08 06:25:32 +08:00
|
|
|
%code.i8 = tail call i8* @llvm.localrecover(i8* bitcast (i32 ()* @main to i8*), i8* %parentfp, i32 0)
|
2015-07-01 06:46:59 +08:00
|
|
|
%__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
|
2015-06-12 06:32:23 +08:00
|
|
|
ret i32 1
|
|
|
|
}
|
|
|
|
|
|
|
|
; Check that we can get the exception code from eax to the printf.
|
|
|
|
|
|
|
|
; CHECK-LABEL: _main:
|
2015-07-10 06:09:41 +08:00
|
|
|
; 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
|
|
|
|
|
2015-06-12 06:32:23 +08:00
|
|
|
; CHECK: Lmain$frame_escape_0 = [[code_offs:[-0-9]+]]
|
|
|
|
; CHECK: Lmain$frame_escape_1 = [[reg_offs:[-0-9]+]]
|
|
|
|
; CHECK: movl %esp, [[reg_offs]](%ebp)
|
|
|
|
; CHECK: movl $L__ehtable$main,
|
|
|
|
; EH state 0
|
2015-07-10 06:09:41 +08:00
|
|
|
; CHECK: movl $0, -16(%ebp)
|
2015-06-12 06:32:23 +08:00
|
|
|
; CHECK: calll _crash
|
2015-07-10 06:09:41 +08:00
|
|
|
; CHECK: popl %esi
|
|
|
|
; CHECK: popl %edi
|
|
|
|
; CHECK: popl %ebx
|
2015-06-12 06:32:23 +08:00
|
|
|
; CHECK: retl
|
|
|
|
; CHECK: # Block address taken
|
|
|
|
; stackrestore
|
2015-07-10 06:09:41 +08:00
|
|
|
; CHECK: movl -24(%ebp), %esp
|
2015-06-12 06:32:23 +08:00
|
|
|
; EH state -1
|
|
|
|
; CHECK: movl [[code_offs]](%ebp), %[[code:[a-z]+]]
|
2015-07-10 06:09:41 +08:00
|
|
|
; CHECK: movl $-1, -16(%ebp)
|
2015-06-12 06:32:23 +08:00
|
|
|
; CHECK-DAG: movl %[[code]], 4(%esp)
|
|
|
|
; CHECK-DAG: movl $_str, (%esp)
|
|
|
|
; CHECK: calll _printf
|
|
|
|
|
|
|
|
; CHECK: .section .xdata,"dr"
|
2015-07-01 06:46:59 +08:00
|
|
|
; CHECK: Lmain$parent_frame_offset = Lmain$frame_escape_1
|
2015-06-12 06:32:23 +08:00
|
|
|
; CHECK: L__ehtable$main
|
|
|
|
; CHECK-NEXT: .long -1
|
|
|
|
; CHECK-NEXT: .long _filt$main
|
|
|
|
; CHECK-NEXT: .long Ltmp{{[0-9]+}}
|
|
|
|
|
|
|
|
; CHECK-LABEL: _filt$main:
|
2015-07-01 06:46:59 +08:00
|
|
|
; 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]], {{.*}}(%{{.*}})
|