llvm.org GIT mirror llvm / 214191f
initial checkin of SJLJ exception handling runtime git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8235 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 16 years ago
2 changed file(s) with 246 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0
1 #include "SJLJ-Exception.h"
2 #include
3 #include
4
5 inline llvm_sjlj_exception *get_sjlj_exception(llvm_exception *E) {
6 assert(E->ExceptionType == SJLJException);
7 return (llvm_sjlj_exception*)(E+1) - 1;
8 }
9
10 // SetJmpMapEntry - One entry in a linked list of setjmps for the current
11 // function.
12 struct SetJmpMapEntry {
13 void *JmpBuf;
14 unsigned SetJmpID;
15 SetJmpMapEntry *Next;
16 };
17
18 static void SJLJDestructor(llvm_exception *E) {
19 free(get_sjlj_exception(E));
20 }
21
22
23 // __llvm_sjljeh_throw_longjmp - This function creates the longjmp exception and
24 // returns. It takes care of mapping the longjmp value from 0 -> 1 as
25 // appropriate. The caller should immediately call llvm.unwind after this
26 // function call.
27 void __llvm_sjljeh_throw_longjmp(void *JmpBuffer, int Val) throw() {
28 llvm_sjlj_exception *E =
29 (llvm_sjlj_exception *)malloc(sizeof(llvm_sjlj_exception));
30 E->BaseException.ExceptionDestructor = SJLJDestructor;
31 E->BaseException.ExceptionType = SJLJException;
32 E->BaseException.HandlerCount = 0;
33 E->BaseException.isRethrown = 0;
34 E->JmpBuffer = JmpBuffer;
35 E->LongJmpValue = Val ? Val : 1;
36
37 __llvm_eh_add_uncaught_exception(&E->BaseException);
38 }
39
40 // __llvm_sjljeh_init_setjmpmap - This funciton initializes the pointer provided
41 // to an empty setjmp map, and should be called on entry to a function which
42 // calls setjmp.
43 void __llvm_sjljeh_init_setjmpmap(void **SetJmpMap) throw() {
44 *SetJmpMap = 0;
45 }
46
47 // __llvm_sjljeh_destroy_setjmpmap - This function frees all memory associated
48 // with the specified setjmpmap structure. It should be called on all exits
49 // (returns or unwinds) from the function which calls ...init_setjmpmap.
50 void __llvm_sjljeh_destroy_setjmpmap(void **SetJmpMap) throw() {
51 SetJmpMapEntry *Next;
52 for (SetJmpMapEntry *SJE = *(SetJmpMapEntry**)SetJmpMap; SJE; SJE = Next) {
53 Next = SJE->Next;
54 free(SJE);
55 }
56 }
57
58 // __llvm_sjljeh_add_setjmp_to_map - This function adds or updates an entry to
59 // the map, to indicate which setjmp should be returned to if a longjmp happens.
60 void __llvm_sjljeh_add_setjmp_to_map(void **SetJmpMap, void *JmpBuf,
61 unsigned SetJmpID) throw() {
62 SetJmpMapEntry **SJE = (SetJmpMapEntry**)SetJmpMap;
63
64 // Scan for a pre-existing entry...
65 for (; *SJE; SJE = &(*SJE)->Next)
66 if ((*SJE)->JmpBuf == JmpBuf) {
67 (*SJE)->SetJmpID = SetJmpID;
68 return;
69 }
70
71 // No prexisting entry found, append to the end of the list...
72 SetJmpMapEntry *New = (SetJmpMapEntry *)malloc(sizeof(SetJmpMapEntry));
73 *SJE = New;
74 New->JmpBuf = JmpBuf;
75 New->SetJmpID = SetJmpID;
76 New->Next = 0;
77 }
78
79 // __llvm_sjljeh_is_longjmp_exception - This function returns true if the
80 // current uncaught exception is a longjmp exception. This is the first step of
81 // catching a sjlj exception.
82 bool __llvm_sjljeh_is_longjmp_exception() throw() {
83 return __llvm_eh_current_uncaught_exception_type(SJLJException) != 0;
84 }
85
86 // __llvm_sjljeh_get_longjmp_value - This function returns the value that the
87 // setjmp call should "return". This requires that the current uncaught
88 // exception be a sjlj exception, though it does not require the exception to be
89 // caught by this function.
90 int __llvm_sjljeh_get_longjmp_value() throw() {
91 llvm_sjlj_exception *E =
92 get_sjlj_exception(__llvm_eh_get_uncaught_exception());
93 return E->LongJmpValue;
94 }
95
96 // __llvm_sjljeh_try_catching_longjmp_exception - This function checks to see if
97 // the current uncaught longjmp exception matches any of the setjmps collected
98 // in the setjmpmap structure. If so, it catches and destroys the exception,
99 // returning the index of the setjmp which caught the exception. If not, it
100 // leaves the exception uncaught and returns a value of ~0.
101 unsigned __llvm_sjljeh_try_catching_longjmp_exception(void **SetJmpMap) throw(){
102 llvm_sjlj_exception *E =
103 get_sjlj_exception(__llvm_eh_get_uncaught_exception());
104
105 // Scan for a matching entry in the SetJmpMap...
106 SetJmpMapEntry *SJE = *(SetJmpMapEntry**)SetJmpMap;
107 for (; SJE; SJE = SJE->Next)
108 if (SJE->JmpBuf == E->JmpBuffer) {
109 // "Catch" and destroy the exception...
110 __llvm_eh_pop_from_uncaught_stack();
111
112 // We know it's a longjmp exception, so we can just free it instead of
113 // calling the destructor.
114 free(E);
115
116 // Return the setjmp ID which we should branch to...
117 return SJE->SetJmpID;
118 }
119
120 // No setjmp in this function catches the exception!
121 return ~0;
122 }
0
1 #include "SJLJ-Exception.h"
2 #include
3 #include
4
5 inline llvm_sjlj_exception *get_sjlj_exception(llvm_exception *E) {
6 assert(E->ExceptionType == SJLJException);
7 return (llvm_sjlj_exception*)(E+1) - 1;
8 }
9
10 // SetJmpMapEntry - One entry in a linked list of setjmps for the current
11 // function.
12 struct SetJmpMapEntry {
13 void *JmpBuf;
14 unsigned SetJmpID;
15 SetJmpMapEntry *Next;
16 };
17
18 static void SJLJDestructor(llvm_exception *E) {
19 free(get_sjlj_exception(E));
20 }
21
22
23 // __llvm_sjljeh_throw_longjmp - This function creates the longjmp exception and
24 // returns. It takes care of mapping the longjmp value from 0 -> 1 as
25 // appropriate. The caller should immediately call llvm.unwind after this
26 // function call.
27 void __llvm_sjljeh_throw_longjmp(void *JmpBuffer, int Val) throw() {
28 llvm_sjlj_exception *E =
29 (llvm_sjlj_exception *)malloc(sizeof(llvm_sjlj_exception));
30 E->BaseException.ExceptionDestructor = SJLJDestructor;
31 E->BaseException.ExceptionType = SJLJException;
32 E->BaseException.HandlerCount = 0;
33 E->BaseException.isRethrown = 0;
34 E->JmpBuffer = JmpBuffer;
35 E->LongJmpValue = Val ? Val : 1;
36
37 __llvm_eh_add_uncaught_exception(&E->BaseException);
38 }
39
40 // __llvm_sjljeh_init_setjmpmap - This funciton initializes the pointer provided
41 // to an empty setjmp map, and should be called on entry to a function which
42 // calls setjmp.
43 void __llvm_sjljeh_init_setjmpmap(void **SetJmpMap) throw() {
44 *SetJmpMap = 0;
45 }
46
47 // __llvm_sjljeh_destroy_setjmpmap - This function frees all memory associated
48 // with the specified setjmpmap structure. It should be called on all exits
49 // (returns or unwinds) from the function which calls ...init_setjmpmap.
50 void __llvm_sjljeh_destroy_setjmpmap(void **SetJmpMap) throw() {
51 SetJmpMapEntry *Next;
52 for (SetJmpMapEntry *SJE = *(SetJmpMapEntry**)SetJmpMap; SJE; SJE = Next) {
53 Next = SJE->Next;
54 free(SJE);
55 }
56 }
57
58 // __llvm_sjljeh_add_setjmp_to_map - This function adds or updates an entry to
59 // the map, to indicate which setjmp should be returned to if a longjmp happens.
60 void __llvm_sjljeh_add_setjmp_to_map(void **SetJmpMap, void *JmpBuf,
61 unsigned SetJmpID) throw() {
62 SetJmpMapEntry **SJE = (SetJmpMapEntry**)SetJmpMap;
63
64 // Scan for a pre-existing entry...
65 for (; *SJE; SJE = &(*SJE)->Next)
66 if ((*SJE)->JmpBuf == JmpBuf) {
67 (*SJE)->SetJmpID = SetJmpID;
68 return;
69 }
70
71 // No prexisting entry found, append to the end of the list...
72 SetJmpMapEntry *New = (SetJmpMapEntry *)malloc(sizeof(SetJmpMapEntry));
73 *SJE = New;
74 New->JmpBuf = JmpBuf;
75 New->SetJmpID = SetJmpID;
76 New->Next = 0;
77 }
78
79 // __llvm_sjljeh_is_longjmp_exception - This function returns true if the
80 // current uncaught exception is a longjmp exception. This is the first step of
81 // catching a sjlj exception.
82 bool __llvm_sjljeh_is_longjmp_exception() throw() {
83 return __llvm_eh_current_uncaught_exception_type(SJLJException) != 0;
84 }
85
86 // __llvm_sjljeh_get_longjmp_value - This function returns the value that the
87 // setjmp call should "return". This requires that the current uncaught
88 // exception be a sjlj exception, though it does not require the exception to be
89 // caught by this function.
90 int __llvm_sjljeh_get_longjmp_value() throw() {
91 llvm_sjlj_exception *E =
92 get_sjlj_exception(__llvm_eh_get_uncaught_exception());
93 return E->LongJmpValue;
94 }
95
96 // __llvm_sjljeh_try_catching_longjmp_exception - This function checks to see if
97 // the current uncaught longjmp exception matches any of the setjmps collected
98 // in the setjmpmap structure. If so, it catches and destroys the exception,
99 // returning the index of the setjmp which caught the exception. If not, it
100 // leaves the exception uncaught and returns a value of ~0.
101 unsigned __llvm_sjljeh_try_catching_longjmp_exception(void **SetJmpMap) throw(){
102 llvm_sjlj_exception *E =
103 get_sjlj_exception(__llvm_eh_get_uncaught_exception());
104
105 // Scan for a matching entry in the SetJmpMap...
106 SetJmpMapEntry *SJE = *(SetJmpMapEntry**)SetJmpMap;
107 for (; SJE; SJE = SJE->Next)
108 if (SJE->JmpBuf == E->JmpBuffer) {
109 // "Catch" and destroy the exception...
110 __llvm_eh_pop_from_uncaught_stack();
111
112 // We know it's a longjmp exception, so we can just free it instead of
113 // calling the destructor.
114 free(E);
115
116 // Return the setjmp ID which we should branch to...
117 return SJE->SetJmpID;
118 }
119
120 // No setjmp in this function catches the exception!
121 return ~0;
122 }