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 |