| Index: test/Transforms/NaCl/pnacl-eh-exception-info.ll
|
| diff --git a/test/Transforms/NaCl/pnacl-eh-exception-info.ll b/test/Transforms/NaCl/pnacl-eh-exception-info.ll
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a330f6f5ac4358a5bbc05387082e8390ba1a81d7
|
| --- /dev/null
|
| +++ b/test/Transforms/NaCl/pnacl-eh-exception-info.ll
|
| @@ -0,0 +1,128 @@
|
| +; 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 [6 x %action_table_entry] [%action_table_entry { i32 2, i32 0 }, %action_table_entry { i32 1, i32 1 }, %action_table_entry { i32 0, i32 2 }, %action_table_entry { i32 -1, i32 0 }, %action_table_entry { i32 -2, i32 0 }, %action_table_entry { i32 3, i32 0 }]
|
| +
|
| +; CHECK: @__pnacl_eh_filter_table = internal constant [5 x i32] [i32 -1, i32 1, i32 2, i32 0, i32 -1]
|
| +
|
| +
|
| +; 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, 0
|
| +; CHECK-NEXT: %cmp2 = icmp eq i32 %arg, 1
|
| +; CHECK-NEXT: %cmp3 = icmp eq i32 %arg, 2
|
| +; 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
|
| +
|
| +
|
| +; "cleanup" is treated the same as "catch i8* null".
|
| +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 6, i32* %exc_info_ptr
|
|
|