1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
; RUN: opt %s -pnacl-sjlj-eh -S | FileCheck %s
; Example std::type_info objects.
@exc_typeid1 = external global i8
@exc_typeid2 = external global i8
@exc_typeid3 = external global i8
; This must be declared for "-pnacl-sjlj-eh" to work.
@__pnacl_eh_stack = external thread_local global i8*
declare i32 @llvm.eh.typeid.for(i8*)
declare void @external_func()
@__pnacl_eh_type_table = external global i8*
@__pnacl_eh_action_table = external global i8*
@__pnacl_eh_filter_table = external global i8*
; CHECK: %action_table_entry = type { i32, i32 }
; CHECK: @__pnacl_eh_type_table = internal constant [4 x i8*] [i8* @exc_typeid1, i8* @exc_typeid2, i8* @exc_typeid3, i8* null]
; CHECK: @__pnacl_eh_action_table = internal constant [7 x %action_table_entry] [%action_table_entry { i32 3, i32 0 }, %action_table_entry { i32 2, i32 1 }, %action_table_entry { i32 1, i32 2 }, %action_table_entry { i32 -1, i32 0 }, %action_table_entry { i32 -2, i32 0 }, %action_table_entry { i32 4, i32 0 }, %action_table_entry zeroinitializer]
; CHECK: @__pnacl_eh_filter_table = internal constant [5 x i32] [i32 0, i32 2, i32 3, i32 1, i32 0]
; Exception type pointers are allocated IDs which specify the index
; into __pnacl_eh_type_table where the type may be found.
define void @test_eh_typeid(i32 %arg) {
%id1 = call i32 @llvm.eh.typeid.for(i8* @exc_typeid1)
%id2 = call i32 @llvm.eh.typeid.for(i8* @exc_typeid2)
%id3 = call i32 @llvm.eh.typeid.for(i8* @exc_typeid3)
%cmp1 = icmp eq i32 %arg, %id1
%cmp2 = icmp eq i32 %arg, %id2
%cmp3 = icmp eq i32 %arg, %id3
ret void
}
; CHECK: define void @test_eh_typeid
; CHECK-NEXT: %cmp1 = icmp eq i32 %arg, 1
; CHECK-NEXT: %cmp2 = icmp eq i32 %arg, 2
; CHECK-NEXT: %cmp3 = icmp eq i32 %arg, 3
; CHECK-NEXT: ret void
define void @test_single_catch_clause() {
invoke void @external_func() to label %cont unwind label %lpad
cont:
ret void
lpad:
landingpad i32 personality i8* null
catch i8* @exc_typeid3
ret void
}
; CHECK: define void @test_single_catch_clause
; CHECK: store i32 1, i32* %exc_info_ptr
define void @test_multiple_catch_clauses() {
invoke void @external_func() to label %cont unwind label %lpad
cont:
ret void
lpad:
landingpad i32 personality i8* null
catch i8* @exc_typeid1
catch i8* @exc_typeid2
catch i8* @exc_typeid3
ret void
}
; CHECK: define void @test_multiple_catch_clauses
; CHECK: store i32 3, i32* %exc_info_ptr
define void @test_empty_filter_clause() {
invoke void @external_func() to label %cont unwind label %lpad
cont:
ret void
lpad:
landingpad i32 personality i8* null
filter [0 x i8*] []
ret void
}
; CHECK: define void @test_empty_filter_clause
; CHECK: store i32 4, i32* %exc_info_ptr
define void @test_filter_clause() {
invoke void @external_func() to label %cont unwind label %lpad
cont:
ret void
lpad:
landingpad i32 personality i8* null
filter [3 x i8*] [i8* @exc_typeid2,
i8* @exc_typeid3,
i8* @exc_typeid1]
ret void
}
; CHECK: define void @test_filter_clause
; CHECK: store i32 5, i32* %exc_info_ptr
; "catch i8* null" means that any C++ exception matches.
define void @test_catch_all_clause() {
invoke void @external_func() to label %cont unwind label %lpad
cont:
ret void
lpad:
landingpad i32 personality i8* null
catch i8* null
ret void
}
; CHECK: define void @test_catch_all_clause
; CHECK: store i32 6, i32* %exc_info_ptr
define void @test_cleanup_clause() {
invoke void @external_func() to label %cont unwind label %lpad
cont:
ret void
lpad:
landingpad i32 personality i8* null
cleanup
ret void
}
; CHECK: define void @test_cleanup_clause
; CHECK: store i32 7, i32* %exc_info_ptr
|