diff options
Diffstat (limited to 'src/grt/config')
-rw-r--r-- | src/grt/config/jumps.c | 18 | ||||
-rw-r--r-- | src/grt/config/win32.c | 141 |
2 files changed, 24 insertions, 135 deletions
diff --git a/src/grt/config/jumps.c b/src/grt/config/jumps.c index 360ea80..775225e 100644 --- a/src/grt/config/jumps.c +++ b/src/grt/config/jumps.c @@ -67,28 +67,24 @@ static int run_env_en; static JMP_BUF run_env; extern void grt_overflow_error (void); +extern void grt_null_access_error (void); #ifdef __APPLE__ #define NEED_SIGFPE_HANDLER #endif -#if defined (__linux__) && defined (__i386__) -#define NEED_SIGSEGV_HANDLER -#endif -#ifdef NEED_SIGFPE_HANDLER static struct sigaction prev_sigfpe_act; -/* Handler for SIGFPE signal, raised in case of overflow (i386). */ +/* Handler for SIGFPE signal. + It is also raised in case of overflow (i386 linux). */ static void grt_overflow_handler (int signo, siginfo_t *info, void *ptr) { grt_overflow_error (); } -#endif -#ifdef NEED_SIGSEGV_HANDLER static struct sigaction prev_sigsegv_act; -/* Linux handler for overflow. This is used only by mcode. */ +/* Posix handler for overflow. This is used only by mcode. */ static void grt_sigsegv_handler (int signo, siginfo_t *info, void *ptr) { #if defined (__linux__) && defined (__i386__) @@ -100,12 +96,11 @@ static void grt_sigsegv_handler (int signo, siginfo_t *info, void *ptr) #endif /* We loose. */ + grt_null_access_error (); } -#endif /* __linux__ && __i386__ */ static void grt_signal_setup (void) { -#ifdef NEED_SIGSEGV_HANDLER { struct sigaction sigsegv_act; @@ -122,7 +117,6 @@ static void grt_signal_setup (void) If the handler is not installed, then some feature are lost. */ sigaction (SIGSEGV, &sigsegv_act, &prev_sigsegv_act); } -#endif #ifdef NEED_SIGFPE_HANDLER { @@ -139,9 +133,7 @@ static void grt_signal_setup (void) static void grt_signal_restore (void) { -#ifdef NEED_SIGSEGV_HANDLER sigaction (SIGSEGV, &prev_sigsegv_act, NULL); -#endif #ifdef NEED_SIGFPE_HANDLER sigaction (SIGFPE, &prev_sigfpe_act, NULL); diff --git a/src/grt/config/win32.c b/src/grt/config/win32.c index 35322ba..f9d669e 100644 --- a/src/grt/config/win32.c +++ b/src/grt/config/win32.c @@ -30,6 +30,12 @@ #include <assert.h> #include <excpt.h> +static int run_env_en; +static jmp_buf run_env; + +extern void grt_overflow_error (void); +extern void grt_null_access_error (void); + static EXCEPTION_DISPOSITION ghdl_SEH_handler (struct _EXCEPTION_RECORD* ExceptionRecord, void *EstablisherFrame, @@ -42,119 +48,6 @@ struct exception_registration void *handler; }; -struct stack_type -{ - LPVOID fiber; // Win fiber. - void (*func)(void *); // Function - void *arg; // Function argument. -}; - -static struct stack_type main_stack_context; -static struct stack_type *current; -extern void grt_set_main_stack (struct stack_type *stack); - -void grt_stack_init(void) -{ - main_stack_context.fiber = ConvertThreadToFiber (NULL); - if (main_stack_context.fiber == NULL) - { - fprintf (stderr, "convertThreadToFiber failed (err=%lu)\n", - GetLastError ()); - abort (); - } - grt_set_main_stack (&main_stack_context); - current = &main_stack_context; -} - -static VOID __stdcall -grt_stack_loop (void *v_stack) -{ - struct stack_type *stack = (struct stack_type *)v_stack; - struct exception_registration er; - struct exception_registration *prev; - - /* Get current handler. */ - asm ("mov %%fs:(0),%0" : "=r" (prev)); - - /* Build regisration. */ - er.prev = prev; - er.handler = ghdl_SEH_handler; - - /* Register. */ - asm ("mov %0,%%fs:(0)" : : "r" (&er)); - - while (1) - { - (*stack->func)(stack->arg); - } -} - -struct stack_type * -grt_stack_create (void (*func)(void *), void *arg) -{ - struct stack_type *res; - - res = malloc (sizeof (struct stack_type)); - if (res == NULL) - return NULL; - res->func = func; - res->arg = arg; - res->fiber = CreateFiber (0, &grt_stack_loop, res); - if (res->fiber == NULL) - { - free (res); - return NULL; - } - return res; -} - -static int run_env_en; -static jmp_buf run_env; -static int need_longjmp; - -void -grt_stack_switch (struct stack_type *to, struct stack_type *from) -{ - assert (current == from); - current = to; - SwitchToFiber (to->fiber); - if (from == &main_stack_context && need_longjmp) - { - /* We returned to do the longjump. */ - current = &main_stack_context; - longjmp (run_env, need_longjmp); - } -} - -void -grt_stack_delete (struct stack_type *stack) -{ - DeleteFiber (stack->fiber); - stack->fiber = NULL; -} - -void -__ghdl_maybe_return_via_longjump (int val) -{ - if (!run_env_en) - return; - - if (current != &main_stack_context) - { - /* We are allowed to jump only in the same stack. - First switch back to the main thread. */ - need_longjmp = val; - SwitchToFiber (main_stack_context.fiber); - } - else - longjmp (run_env, val); -} - -extern void grt_stack_error_grow_failed (void); -extern void grt_stack_error_null_access (void); -extern void grt_stack_error_memory_access (void); -extern void grt_overflow_error (void); - static EXCEPTION_DISPOSITION ghdl_SEH_handler (struct _EXCEPTION_RECORD* ExceptionRecord, void *EstablisherFrame, @@ -166,12 +59,9 @@ ghdl_SEH_handler (struct _EXCEPTION_RECORD* ExceptionRecord, switch (ExceptionRecord->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: - if (ExceptionRecord->ExceptionInformation[1] == 0) - grt_stack_error_null_access (); - else - grt_stack_error_memory_access (); + grt_null_access_error (); break; - + case EXCEPTION_FLT_DENORMAL_OPERAND: case EXCEPTION_FLT_DIVIDE_BY_ZERO: case EXCEPTION_FLT_INVALID_OPERATION: @@ -180,19 +70,19 @@ ghdl_SEH_handler (struct _EXCEPTION_RECORD* ExceptionRecord, case EXCEPTION_FLT_UNDERFLOW: msg = "floating point error"; break; - + case EXCEPTION_INT_DIVIDE_BY_ZERO: msg = "division by 0"; break; - + case EXCEPTION_INT_OVERFLOW: grt_overflow_error (); break; - + case EXCEPTION_STACK_OVERFLOW: msg = "stack overflow"; break; - + default: msg = "unknown reason"; break; @@ -205,6 +95,13 @@ ghdl_SEH_handler (struct _EXCEPTION_RECORD* ExceptionRecord, return 0; /* This is never reached, avoid compiler warning */ } +void +__ghdl_maybe_return_via_longjump (int val) +{ + if (run_env_en) + longjmp (run_env, val); +} + int __ghdl_run_through_longjump (int (*func)(void)) { |