summaryrefslogtreecommitdiff
path: root/gcc/libgcc2.c
diff options
context:
space:
mode:
authormrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>1997-04-23 20:04:25 +0000
committermrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>1997-04-23 20:04:25 +0000
commit694ec51983be9bfc22d051e98e22e185c6b00651 (patch)
treeed1bd25525ef36f94c97fb911c74203e02095a25 /gcc/libgcc2.c
parentc446d93c756b52b25588a6816d1728f4852d2068 (diff)
downloadgcc-694ec51983be9bfc22d051e98e22e185c6b00651.tar.gz
Add setjmp/longjmp exception handling.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@13968 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/libgcc2.c')
-rw-r--r--gcc/libgcc2.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c
index 338707029ce..725161865dd 100644
--- a/gcc/libgcc2.c
+++ b/gcc/libgcc2.c
@@ -3102,6 +3102,172 @@ EH_TABLE_LOOKUP
#else
+void
+__default_terminate ()
+{
+ abort ();
+}
+
+void (*__terminate_func)() = __default_terminate;
+
+void
+__terminate ()
+{
+ (*__terminate_func)();
+}
+
+/* Calls to __sjthrow are generated by the compiler when an exception
+ is raised when using the setjmp/longjmp exception handling codegen
+ method. */
+
+extern longjmp (void *, int);
+
+extern void *__eh_type;
+
+static void *top_elt[2];
+void **__dynamic_handler_chain = top_elt;
+
+/* Routine to get the head of the current thread's dynamic handler chain
+ use for exception handling.
+
+ TODO: make thread safe. */
+
+void ***
+__get_dynamic_handler_chain ()
+{
+ return &__dynamic_handler_chain;
+}
+
+/* This is used to throw an exception when the setjmp/longjmp codegen
+ method is used for exception handling.
+
+ We call __terminate if there are no handlers left (we know this
+ when the dynamic handler chain is top_elt). Otherwise we run the
+ cleanup actions off the dynamic cleanup stack, and pop the top of
+ the dynamic handler chain, and use longjmp to transfer back to the
+ associated handler. */
+
+void
+__sjthrow ()
+{
+ void ***dhc = __get_dynamic_handler_chain ();
+ void *jmpbuf;
+ void (*func)(void *, int);
+ void *arg;
+ void ***cleanup;
+
+ /* The cleanup chain is one word into the buffer. Get the cleanup
+ chain. */
+ cleanup = (void***)&(*dhc)[1];
+
+ /* If there are any cleanups in the chain, run them now. */
+ if (cleanup[0])
+ {
+ double store[200];
+ void **buf = (void**)store;
+ buf[1] = 0;
+ buf[0] = (*dhc);
+
+ /* try { */
+ if (! setjmp (&buf[2]))
+ {
+ *dhc = buf;
+ while (cleanup[0])
+ {
+ func = (void(*)(void*, int))cleanup[0][1];
+ arg = (void*)cleanup[0][2];
+
+ /* Update this before running the cleanup. */
+ cleanup[0] = (void **)cleanup[0][0];
+
+ (*func)(arg, 2);
+ }
+ *dhc = buf[0];
+ }
+ /* catch (...) */
+ else
+ {
+ __terminate ();
+ }
+ }
+
+ /* We must call terminate if we try and rethrow an exception, when
+ there is no exception currently active and when there are no
+ handlers left. */
+ if (! __eh_type || (*dhc) == top_elt)
+ __terminate ();
+
+ /* Find the jmpbuf associated with the top element of the dynamic
+ handler chain. The jumpbuf starts two words into the buffer. */
+ jmpbuf = &(*dhc)[2];
+
+ /* Then we pop the top element off the dynamic handler chain. */
+ *dhc = (void**)(*dhc)[0];
+
+ /* And then we jump to the handler. */
+
+#ifdef USE_BUILTIN_SETJMP
+ __builtin_longjmp (jmpbuf, 1);
+#else
+ longjmp (jmpbuf, 1);
+#endif
+}
+
+/* Run cleanups on the dynamic cleanup stack for the current dynamic
+ handler, then pop the handler off the dynamic handler stack, and
+ then throw. This is used to skip the first handler, and transfer
+ control to the next handler in the dynamic handler stack. */
+
+void
+__sjpopnthrow ()
+{
+ void ***dhc = __get_dynamic_handler_chain ();
+ void *jmpbuf;
+ void (*func)(void *, int);
+ void *arg;
+ void ***cleanup;
+
+ /* The cleanup chain is one word into the buffer. Get the cleanup
+ chain. */
+ cleanup = (void***)&(*dhc)[1];
+
+ /* If there are any cleanups in the chain, run them now. */
+ if (cleanup[0])
+ {
+ double store[200];
+ void **buf = (void**)store;
+ buf[1] = 0;
+ buf[0] = (*dhc);
+
+ /* try { */
+ if (! setjmp (&buf[2]))
+ {
+ *dhc = buf;
+ while (cleanup[0])
+ {
+ func = (void(*)(void*, int))cleanup[0][1];
+ arg = (void*)cleanup[0][2];
+
+ /* Update this before running the cleanup. */
+ cleanup[0] = (void **)cleanup[0][0];
+
+ (*func)(arg, 2);
+ }
+ *dhc = buf[0];
+ }
+ /* catch (...) */
+ else
+ {
+ __terminate ();
+ }
+ }
+
+ /* Then we pop the top element off the dynamic handler chain. */
+ *dhc = (void**)(*dhc)[0];
+
+ __sjthrow ();
+}
+
typedef struct {
void *start;
void *end;