source: doc/working/exception/main.c@ 0c78741

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since 0c78741 was ae6f1ec, checked in by Thierry Delisle <tdelisle@…>, 8 years ago

Some work on an exception prototype

  • Property mode set to 100644
File size: 3.9 KB
Line 
1#include <stdio.h>
2#include "except.h"
3
4#define EXCEPTION 2
5
6struct type_raii_t {
7 char * msg;
8};
9
10//Dtor function to test clean up routines
11void dtor( struct type_raii_t * this ) {
12 printf("%s\n", this->msg);
13}
14
15//Type macro use to make scope unwinding easier to see.
16#define raii_t __attribute__(( cleanup(dtor) )) struct type_raii_t
17
18//Leaf functions that raises exception
19void bar() {
20 raii_t a = { "Bar dtor" };
21
22 throw( EXCEPTION );
23}
24
25//Matcher function which will check if the exception was correctly caught
26extern int this_exception;
27_Unwind_Reason_Code foo_try_match() {
28 return this_exception == 2 ? _URC_HANDLER_FOUND : _URC_CONTINUE_UNWIND;
29}
30
31//Try statements are hoisted out see comments for details
32//With this could probably be unique and simply linked from
33//libcfa but there is one problem left, see the exception table
34//for details
35void try( void (*try_block)(), void (*catch_block)() )
36{
37 //Setup statments
38 //These 2 statments won't actually result in any code,
39 //they only setup global tables.
40 //However, they clobber gcc cancellation support from gcc.
41 //We can replace the personality routine but replacing the exception
42 //table gcc generates is not really doable, it generates labels based
43 //on how the assembly works.
44 //Setup the personality routine
45 asm volatile (".cfi_personality 0x3,__gcfa_personality_v0");
46 //Setup the exception table
47 asm volatile (".cfi_lsda 0x3, .LLSDACFA2");
48
49 //Label which defines the start of the area for which the handler is setup
50 asm volatile (".TRYSTART:");
51
52 //The actual statements of the try blocks
53 try_block();
54
55 //asm statement to prevent deadcode removal
56 asm volatile goto ("" : : : : CATCH );
57
58 //Normal return
59 return;
60
61 //Exceptionnal path
62 CATCH : __attribute__(( unused ));
63 //Label which defines the end of the area for which the handler is setup
64 asm volatile (".TRYEND:");
65 //Label which defines the start of the exception landing pad
66 //basically what will be called when the exception is caught
67 //Note, if multiple handlers are given, the multiplexing should be done
68 //by the generated code, not the exception runtime
69 asm volatile (".CATCH:");
70
71 //Exception handler
72 catch_block();
73}
74
75//Exception table data we need to generate
76//While this is almost generic, the custom data refers to
77//foo_try_match try match, which is no way generic
78//Some more works need to be done if we want to have a single
79//call to the try routine
80asm (
81 //HEADER
82 ".LFECFA1:\n"
83 " .globl __gcfa_personality_v0\n"
84 " .section .gcc_except_table,\"a\",@progbits\n"
85 ".LLSDACFA2:\n" //TABLE header
86 " .byte 0xff\n"
87 " .byte 0xff\n"
88 " .byte 0x1\n"
89 " .uleb128 .LLSDACSECFA2-.LLSDACSBCFA2\n" //BODY length
90 //Body uses language specific data and therefore could be modified arbitrarily
91 ".LLSDACSBCFA2:\n" //BODY start
92 " .uleb128 .TRYSTART-try\n" //Handled area start (relative to start of function)
93 " .uleb128 .TRYEND-.TRYSTART\n" //Handled area length
94 " .uleb128 .CATCH-try\n" //Hanlder landing pad adress (relative to start of function)
95 " .uleb128 1\n" //Action code, gcc seems to use always 0
96 //Beyond this point we don't match gcc data'
97 " .uleb128 foo_try_match-try\n" //Handler routine to check if the exception is matched
98 ".LLSDACSECFA2:\n" //BODY end
99 " .text\n" //TABLE footer
100 " .size try, .-try\n"
101 " .ident \"GCC: (Ubuntu 6.2.0-3ubuntu11~16.04) 6.2.0 20160901\"\n"
102 " .section .note.GNU-stack,\"x\",@progbits\n"
103);
104
105void foo() {
106 raii_t a = { "Foo dtor" };
107
108 //Since try will clobber the gcc exception table assembly,
109 //We need to nest this to have gcc regenerate the data
110 void foo_try_block() {
111 raii_t b = { "Foo try dtor" };
112
113 bar();
114
115 printf("Called bar successfully\n");
116 }
117
118 void foo_catch_block() {
119 printf("Exception caught\n");
120 }
121
122 //Actual call to the try block
123 try( foo_try_block, foo_catch_block );
124
125 printf( "Foo exited normally\n" );
126}
127
128int main() {
129 raii_t a = { "Main dtor" };
130
131 foo();
132
133 printf("End of program reached\n");
134}
Note: See TracBrowser for help on using the repository browser.