summaryrefslogtreecommitdiff
path: root/translate/grt/config/win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'translate/grt/config/win32.c')
-rw-r--r--translate/grt/config/win32.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/translate/grt/config/win32.c b/translate/grt/config/win32.c
index 465f929..de09400 100644
--- a/translate/grt/config/win32.c
+++ b/translate/grt/config/win32.c
@@ -21,6 +21,19 @@
#include <stdio.h>
#include <setjmp.h>
#include <assert.h>
+#include <excpt.h>
+
+static EXCEPTION_DISPOSITION
+ghdl_SEH_handler (struct _EXCEPTION_RECORD* ExceptionRecord,
+ void *EstablisherFrame,
+ struct _CONTEXT* ContextRecord,
+ void *DispatcherContext);
+
+struct exception_registration
+{
+ struct exception_registration *prev;
+ void *handler;
+};
struct stack_type
{
@@ -50,6 +63,19 @@ 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);
@@ -117,16 +143,87 @@ __ghdl_maybe_return_via_longjump (int val)
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,
+ struct _CONTEXT* ContextRecord,
+ void *DispatcherContext)
+{
+ const char *msg = "";
+
+ switch (ExceptionRecord->ExceptionCode)
+ {
+ case EXCEPTION_ACCESS_VIOLATION:
+ if (ExceptionRecord->ExceptionInformation[1] == 0)
+ grt_stack_error_null_access ();
+ else
+ grt_stack_error_memory_access ();
+ break;
+
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ case EXCEPTION_FLT_OVERFLOW:
+ case EXCEPTION_FLT_STACK_CHECK:
+ 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;
+ }
+
+ /* FIXME: is it correct? */
+ fprintf (stderr, "exception raised: %s\n", msg);
+
+ __ghdl_maybe_return_via_longjump (1);
+ return 0; /* This is never reached, avoid compiler warning */
+}
+
int
__ghdl_run_through_longjump (int (*func)(void))
{
int res;
+ 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));
run_env_en = 1;
res = setjmp (run_env);
if (res == 0)
res = (*func)();
run_env_en = 0;
+
+ /* Restore. */
+ asm ("mov %0,%%fs:(0)" : : "r" (prev));
+
return res;
}