mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-10 04:33:40 +00:00
In particular, this handles SSA values that are live *out* of a handler. The existing code only handles values that are live *in* to a handler. It also handles phi nodes in the block where normal control should resume after the end of a catch handler. When EH return points have phi nodes, we need to split the return edge. It is impossible for phi elimination to emit copies in the previous block if that block gets outlined. The indirectbr that we leave in the function is only notional, and is eliminated from the MachineFunction CFG early on. Reviewers: majnemer, andrew.w.kaylor Differential Revision: http://reviews.llvm.org/D9158 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235545 91177308-0d34-0410-b5e6-96231b3b80d8
73 lines
1.9 KiB
LLVM
73 lines
1.9 KiB
LLVM
; RUN: opt -winehprepare -S < %s | FileCheck %s
|
|
|
|
; Notionally based on this C++ source:
|
|
; int liveout_catch(int p) {
|
|
; int val = p + 1;
|
|
; try {
|
|
; might_throw();
|
|
; } catch (int) {
|
|
; val++;
|
|
; }
|
|
; return val;
|
|
; }
|
|
|
|
declare void @llvm.eh.begincatch(i8*, i8*)
|
|
declare void @llvm.eh.endcatch()
|
|
declare void @might_throw()
|
|
declare i32 @__CxxFrameHandler3(...)
|
|
declare i32 @llvm.eh.typeid.for(i8*)
|
|
|
|
@typeinfo.int = external global i32
|
|
|
|
define i32 @liveout_catch(i32 %p) {
|
|
entry:
|
|
%val.entry = add i32 %p, 1
|
|
invoke void @might_throw()
|
|
to label %ret unwind label %lpad
|
|
|
|
lpad:
|
|
%ehvals = landingpad { i8*, i32 } personality i32 (...)* @__CxxFrameHandler3
|
|
cleanup
|
|
catch i32* @typeinfo.int
|
|
%ehptr = extractvalue { i8*, i32 } %ehvals, 0
|
|
%sel = extractvalue { i8*, i32 } %ehvals, 1
|
|
%int_sel = call i32 @llvm.eh.typeid.for(i8* bitcast (i32* @typeinfo.int to i8*))
|
|
%match = icmp eq i32 %sel, %int_sel
|
|
br i1 %match, label %catchit, label %resume
|
|
|
|
catchit:
|
|
call void @llvm.eh.begincatch(i8* %ehptr, i8* null)
|
|
%val.lpad = add i32 %val.entry, 1
|
|
call void @llvm.eh.endcatch()
|
|
br label %ret
|
|
|
|
ret:
|
|
%rv = phi i32 [%val.entry, %entry], [%val.lpad, %catchit]
|
|
ret i32 %rv
|
|
|
|
resume:
|
|
resume {i8*, i32} %ehvals
|
|
}
|
|
|
|
; CHECK-LABEL: define i32 @liveout_catch(i32 %p)
|
|
; CHECK: %val.entry = add i32 %p, 1
|
|
; CHECK-NEXT: store i32 %val.entry, i32* %val.entry.reg2mem
|
|
; CHECK: invoke void @might_throw()
|
|
;
|
|
; CHECK: landingpad
|
|
; CHECK: indirectbr i8* {{.*}}, [label %ehreturn]
|
|
;
|
|
; CHECK: ehreturn:
|
|
; CHECK: load i32, i32* %val.lpad.reg2mem
|
|
; CHECK: br label %ret
|
|
;
|
|
; CHECK: ret:
|
|
; CHECK: %rv = phi i32 [ {{.*}}, %entry ], [ {{.*}}, %ehreturn ]
|
|
; CHECK: ret i32
|
|
|
|
; CHECK-LABEL: define internal i8* @liveout_catch.catch(i8*, i8*)
|
|
; CHECK: %[[val:[^ ]*]] = load i32, i32*
|
|
; CHECK-NEXT: %[[val_lpad:[^ ]*]] = add i32 %[[val]], 1
|
|
; CHECK-NEXT: store i32 %[[val_lpad]], i32*
|
|
; CHECK: ret i8* blockaddress(@liveout_catch, %ehreturn)
|