[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