[m-dev.] diff: runtime/engine.h
Simon Taylor
stayl at cs.mu.oz.au
Tue Jul 29 17:28:34 AEST 1997
Hi Fergus,
> I think not saving/restoring r1, r2, ... is potentially dangerous.
> The caller may be assuming that r1, r2, ... are still valid.
>
> Also, you need to call save_registers() and restore_registers(),
> not save/restore_transient_registers(), because longjmp() can
> clobber all of them, not just the "transient" (register window) ones.
>
Is this better?
Simon.
Index: engine.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/engine.h,v
retrieving revision 1.13
diff -u -r1.13 engine.h
--- engine.h 1997/07/27 15:08:14 1.13
+++ engine.h 1997/07/29 07:10:52
@@ -13,6 +13,8 @@
#ifndef ENGINE_H
#define ENGINE_H
+#include <setjmp.h>
+
#include "std.h" /* for `bool' */
#include "mercury_types.h" /* for `Code *' */
#include "goto.h" /* for `Define_entry()' */
@@ -42,6 +44,72 @@
#define sregdebug debugflag[SREGFLAG]
#define tracedebug debugflag[TRACEFLAG]
#define detaildebug debugflag[DETAILFLAG]
+
+ /*
+ ** MR_setjmp and MR_longjmp are wrappers around setjmp and longjmp
+ ** to ensure that
+ ** call C -> setjmp -> call Mercury -> call C -> longjmp
+ ** works correctly. This is used by the exception handling code for
+ ** the ODBC interface.
+ */
+
+typedef struct {
+ jmp_buf *mercury_env; /*
+ ** used to save MR_engine_jmp_buf
+ */
+ jmp_buf env; /*
+ ** used by calls to setjmp and longjmp
+ */
+ Word *saved_succip;
+ Word *saved_hp;
+ Word *saved_sp;
+ Word *saved_curfr;
+ Word *saved_maxfr;
+ Word regs[NUM_REAL_REGS];
+ } MR_jmp_buf;
+
+
+ /*
+ ** MR_setjmp(MR_jmp_buf *env, longjmp_label)
+ **
+ ** Save MR_engine_jmp_buf, save the Mercury state, call setjmp(env),
+ ** then fall through.
+ ** When setjmp returns via a call to longjmp, control will pass to
+ ** longjmp_label.
+ */
+#define MR_setjmp(setjmp_env, longjmp_label) \
+ do { \
+ (setjmp_env)->mercury_env = MR_engine_jmp_buf; \
+ save_regs_to_mem((setjmp_env)->regs); \
+ (setjmp_env)->saved_succip = succip; \
+ (setjmp_env)->saved_hp = hp; \
+ (setjmp_env)->saved_sp = sp; \
+ (setjmp_env)->saved_curfr = curfr; \
+ (setjmp_env)->saved_maxfr = maxfr; \
+ if (setjmp((setjmp_env)->env)) { \
+ MR_engine_jmp_buf = (setjmp_env)->mercury_env; \
+ restore_regs_from_mem((setjmp_env)->regs); \
+ succip = (setjmp_env)->saved_succip; \
+ hp = (setjmp_env)->saved_hp; \
+ sp = (setjmp_env)->saved_sp; \
+ curfr = (setjmp_env)->saved_curfr; \
+ maxfr = (setjmp_env)->saved_maxfr; \
+ goto longjmp_label; \
+ } \
+ } while (0)
+
+ /*
+ ** MR_longjmp(MR_jmp_buf *env, int return)
+ **
+ ** Just call longjmp();
+ */
+#define MR_longjmp(setjmp_env, ret) longjmp((setjmp_env)->env, ret)
+
+ /*
+ ** engine_jmp_buf should only be referred to in engine.c
+ ** and the MR_setjmp and MR_longjmp macros defined above.
+ */
+extern jmp_buf *MR_engine_jmp_buf;
extern bool debugflag[];
More information about the developers
mailing list