mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-31 10:34:17 +00:00
df4fd4fc4e
This makes it possible to use the same representation of llvm.eh.actions in outlined handlers as we use in the parent function because i32's are just constants that can be copied freely between functions. I had to add a sentinel alloca to the list of child allocas so that we don't try to sink the catch object into the handler. Normally, one would use nullptr for this kind of thing, but TinyPtrVector doesn't support null elements. More than that, it's elements have to have a suitable alignment. Therefore, I settled on this for my sentinel: AllocaInst *getCatchObjectSentinel() { return static_cast<AllocaInst *>(nullptr) + 1; } git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233947 91177308-0d34-0410-b5e6-96231b3b80d8
139 lines
4.0 KiB
LLVM
139 lines
4.0 KiB
LLVM
; RUN: opt -S -winehprepare -sehprepare -mtriple=x86_64-windows-msvc < %s | FileCheck %s
|
|
|
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
|
target triple = "x86_64-pc-windows-msvc"
|
|
|
|
declare void @cleanup()
|
|
declare i32 @filt()
|
|
declare void @might_crash()
|
|
declare i32 @__C_specific_handler(...)
|
|
declare i32 @llvm.eh.typeid.for(i8*)
|
|
|
|
define i32 @simple_except_store() {
|
|
entry:
|
|
%retval = alloca i32
|
|
store i32 0, i32* %retval
|
|
invoke void @might_crash()
|
|
to label %return unwind label %lpad
|
|
|
|
lpad:
|
|
%ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
|
|
catch i32 ()* @filt
|
|
%sel = extractvalue { i8*, i32 } %ehvals, 1
|
|
%filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
|
|
%matches = icmp eq i32 %sel, %filt_sel
|
|
br i1 %matches, label %__except, label %eh.resume
|
|
|
|
__except:
|
|
store i32 1, i32* %retval
|
|
br label %return
|
|
|
|
return:
|
|
%r = load i32, i32* %retval
|
|
ret i32 %r
|
|
|
|
eh.resume:
|
|
resume { i8*, i32 } %ehvals
|
|
}
|
|
|
|
; CHECK-LABEL: define i32 @simple_except_store()
|
|
; CHECK: landingpad { i8*, i32 }
|
|
; CHECK-NEXT: catch i32 ()* @filt
|
|
; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@simple_except_store, %__except))
|
|
; CHECK-NEXT: indirectbr {{.*}} [label %__except]
|
|
|
|
define i32 @catch_all() {
|
|
entry:
|
|
%retval = alloca i32
|
|
store i32 0, i32* %retval
|
|
invoke void @might_crash()
|
|
to label %return unwind label %lpad
|
|
|
|
lpad:
|
|
%ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
|
|
catch i8* null
|
|
store i32 1, i32* %retval
|
|
br label %return
|
|
|
|
return:
|
|
%r = load i32, i32* %retval
|
|
ret i32 %r
|
|
}
|
|
|
|
; CHECK-LABEL: define i32 @catch_all()
|
|
; CHECK: landingpad { i8*, i32 }
|
|
; CHECK-NEXT: catch i8* null
|
|
; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* blockaddress(@catch_all, %catch.all))
|
|
; CHECK-NEXT: indirectbr {{.*}} [label %catch.all]
|
|
;
|
|
; CHECK: catch.all:
|
|
; CHECK: store i32 1, i32* %retval
|
|
|
|
|
|
define i32 @except_phi() {
|
|
entry:
|
|
invoke void @might_crash()
|
|
to label %return unwind label %lpad
|
|
|
|
lpad:
|
|
%ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
|
|
catch i32 ()* @filt
|
|
%sel = extractvalue { i8*, i32 } %ehvals, 1
|
|
%filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
|
|
%matches = icmp eq i32 %sel, %filt_sel
|
|
br i1 %matches, label %return, label %eh.resume
|
|
|
|
return:
|
|
%r = phi i32 [0, %entry], [1, %lpad]
|
|
ret i32 %r
|
|
|
|
eh.resume:
|
|
resume { i8*, i32 } %ehvals
|
|
}
|
|
|
|
; CHECK-LABEL: define i32 @except_phi()
|
|
; CHECK: landingpad { i8*, i32 }
|
|
; CHECK-NEXT: catch i32 ()* @filt
|
|
; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@except_phi, %return))
|
|
; CHECK-NEXT: indirectbr {{.*}} [label %return]
|
|
;
|
|
; CHECK: return:
|
|
; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad1 ]
|
|
; CHECK-NEXT: ret i32 %r
|
|
|
|
define i32 @cleanup_and_except() {
|
|
entry:
|
|
invoke void @might_crash()
|
|
to label %return unwind label %lpad
|
|
|
|
lpad:
|
|
%ehvals = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler
|
|
cleanup
|
|
catch i32 ()* @filt
|
|
call void @cleanup()
|
|
%sel = extractvalue { i8*, i32 } %ehvals, 1
|
|
%filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*))
|
|
%matches = icmp eq i32 %sel, %filt_sel
|
|
br i1 %matches, label %return, label %eh.resume
|
|
|
|
return:
|
|
%r = phi i32 [0, %entry], [1, %lpad]
|
|
ret i32 %r
|
|
|
|
eh.resume:
|
|
resume { i8*, i32 } %ehvals
|
|
}
|
|
|
|
; CHECK-LABEL: define i32 @cleanup_and_except()
|
|
; CHECK: landingpad { i8*, i32 }
|
|
; CHECK-NEXT: cleanup
|
|
; CHECK-NEXT: catch i32 ()* @filt
|
|
; CHECK-NEXT: call i8* (...)* @llvm.eh.actions(
|
|
; CHECK: i32 0, void (i8*, i8*)* @cleanup_and_except.cleanup,
|
|
; CHECK: i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@cleanup_and_except, %return))
|
|
; CHECK-NEXT: indirectbr {{.*}} [label %return]
|
|
;
|
|
; CHECK: return:
|
|
; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad1 ]
|
|
; CHECK-NEXT: ret i32 %r
|