for review: Stack dumps -- the main course (round 2)

Tyson Dowd trd at cs.mu.OZ.AU
Fri Mar 6 16:56:07 AEDT 1998


Hi,

Here's an update of my diff.  There are quite a few changes, and
a major merge, so I've re-posted the whole thing.

---

This adds stack traces (well, at the moment, just a "stack dump") to
the library and runtime system.

You need to compile with MCFLAGS = --stack-trace and
MGNUCFLAGS = --stack-trace (or EXTRA_MCFLAGS and EXTRA_MGNUCFLAGS)
to obtain an executable capable of displaying a stack dump.  This isn't
intended to be the final mechanism -- probably a new grade or debugging
grade would be the best solution.

Presently, any call to error/1 attempts to do a stack dump. 

The results look like this:

Software error: map__det_insert: key already present
Stack dump follows (determinisitic stack only):
	mercury__map__det_insert_from_corresponding_lists_4_0
	mercury__map_error__create_map_error_2_0
	mercury__map_error__do_call_this_2_0
	mercury__main_2_0


===================================================================


Estimated hours taken: 12 

Add support for stack dumps, do a stack dump from error/1.


compiler/Mmakefile:
library/Mmakefile:
profiler/Mmakefile:
runtime/Mmakefile:
	Insert EXTRA_MGNUCFLAGS before CFLAGS or EXTRA_CFLAGS
	becasue mgnuc stops processing its options when it
	encounters a non-mgnuc option.

library/require.m:
	Call MR_dump_stack if error is called.

runtime/Mmakefile:
runtime/mercury_imp.h:
	Add #includes of new files. 

runtime/mercury_type_info.h:
	Remove conditional definition of MR_STATIC_CODE_ADDRESSES
	(moved into mercury_conf.h.in).

runtime/mercury_accurate_gc.h:
	Remove stack_layout stuff, leave this file for accurate
	GC specific definitions.

runtime/mercury_conf.h.in:
	Add conditional definitions of MR_INSERT_LABELS,
	MR_USE_STACK_LAYOUTS, MR_NEED_INITIALIZATION_CODE and
	MR_STATIC_CODE_ADDRESSES, depending on various other options.

runtime/mercury_goto.h:
	Insert labels into label table if MR_INSERT_LABELS is defined,
	rather than NATIVE_GC.

util/mkinit.c:
	Initialize if MR_NEED_INITIALIZATION_CODE is defined, rather than
	NATIVE_GC.

runtime/mercury_stack_layout.h:
	All the old stack layout definitions from mercury_accurate_gc.h.
	Add code for MR_DETERMINSIM_IS_DET_CODE_MODEL.

runtime/mercury_stack_trace.c:
runtime/mercury_stack_trace.h:
	Implement MR_dump_stack which just provides a dump of the stack
	as far as possible.
	Set MR_INSERT_LABELS and MR_USE_STACK_LAYOUTS if MR_STACK_TRACE
	is set.

runtime/mercury_grade.h:
	Add _strce if stack tracing is enabled in the grade.  This
	might not be a permanent change.

runtime/mercury_ho_call.c:
	Remove unused label declarations.

scripts/mgnuc.in:
	Add --stack-trace and --no-stack-trace options.
	Consolidate some duplicate code.

Index: compiler/Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/Mmakefile,v
retrieving revision 1.8
diff -u -r1.8 Mmakefile
--- Mmakefile	1998/02/18 23:41:50	1.8
+++ Mmakefile	1998/03/05 07:06:28
@@ -32,7 +32,7 @@
 		MERCURY_INT_DIR=$(LIBRARY_DIR) \
 		$(MC) --cflags -I$(BOEHM_GC_DIR) --split-c-files -c 
 MGNUC	=	MERCURY_C_INCL_DIR=$(RUNTIME_DIR) $(SCRIPTS_DIR)/mgnuc
-MGNUCFLAGS =	-I$(BOEHM_GC_DIR) $(EXTRA_CFLAGS)
+MGNUCFLAGS =	$(EXTRA_MGNUCFLAGS) -I$(BOEHM_GC_DIR) $(EXTRA_CFLAGS)
 C2INIT =	\
 MERCURY_MOD_LIB_MODS="$(RUNTIME_DIR)/runtime.init $(LIBRARY_DIR)/libmercury.init" \
 		MERCURY_MKINIT=$(UTIL_DIR)/mkinit $(SCRIPTS_DIR)/c2init
Index: library/Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/Mmakefile,v
retrieving revision 1.23
diff -u -r1.23 Mmakefile
--- Mmakefile	1998/03/04 05:10:14	1.23
+++ Mmakefile	1998/03/05 07:05:36
@@ -80,7 +80,7 @@
 		--cflags "-I$(RUNTIME_DIR) -I$(BOEHM_GC_DIR) $(EXTRA_CFLAGS)" \
 		$(INTERMODULE_OPTS) $(CHECK_TERM_OPTS)
 MGNUC	=	MERCURY_C_INCL_DIR=$(RUNTIME_DIR) $(SCRIPTS_DIR)/mgnuc
-MGNUCFLAGS =	-I$(RUNTIME_DIR) -I$(BOEHM_GC_DIR) \
+MGNUCFLAGS =	$(EXTRA_MGNUCFLAGS) -I$(RUNTIME_DIR) -I$(BOEHM_GC_DIR)  \
 		$(DLL_CFLAGS) $(EXTRA_CFLAGS)
 LDFLAGS	=	-L$(BOEHM_GC_DIR) -L$(RUNTIME_DIR)
 LDLIBS	=	-lmer							\
Index: library/require.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/require.m,v
retrieving revision 1.17
diff -u -r1.17 require.m
--- require.m	1998/01/23 12:33:31	1.17
+++ require.m	1998/03/03 07:58:21
@@ -47,7 +47,10 @@
 
 /* error/1, from require.m */
 
-:- pragma c_header_code("#include <stdio.h>").
+:- pragma c_header_code("
+#include <stdio.h>
+#include ""mercury_stack_trace.h""
+").
 
 % Hopefully error/1 won't be called often (!), so no point inlining it.
 :- pragma no_inline(error/1). 
@@ -55,6 +58,7 @@
 :- pragma c_code(error(Message::in), "
 	fflush(stdout);
 	fprintf(stderr, ""Software error: %s\\n"", Message);
+	MR_dump_stack(MR_succip, MR_sp);
 	exit(1);
 #ifndef USE_GCC_NONLOCAL_GOTOS
 	return 0;	/* suppress some dumb warnings */
Index: profiler/Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/mercury/profiler/Mmakefile,v
retrieving revision 1.5
diff -u -r1.5 Mmakefile
--- Mmakefile	1997/11/06 06:19:29	1.5
+++ Mmakefile	1998/03/05 07:07:05
@@ -26,7 +26,7 @@
 MCS	=	MERCURY_C_INCL_DIR=$(RUNTIME_DIR) \
 		MERCURY_INT_DIR=$(LIBRARY_DIR) $(MC) --split-c-files -c
 MGNUC	=	MERCURY_C_INCL_DIR=$(RUNTIME_DIR) $(SCRIPTS_DIR)/mgnuc
-MGNUCFLAGS =	-I$(BOEHM_GC_DIR) $(EXTRA_CFLAGS)
+MGNUCFLAGS =	$(EXTRA_MGNUCFLAGS) -I$(BOEHM_GC_DIR) $(EXTRA_CFLAGS)
 C2INIT =	\
 MERCURY_MOD_LIB_MODS="$(RUNTIME_DIR)/runtime.init $(LIBRARY_DIR)/libmercury.init" \
 		MERCURY_MKINIT=$(UTIL_DIR)/mkinit $(SCRIPTS_DIR)/c2init
Index: runtime/Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/Mmakefile,v
retrieving revision 1.21
diff -u -r1.21 Mmakefile
--- Mmakefile	1997/12/05 15:56:25	1.21
+++ Mmakefile	1998/03/05 06:48:35
@@ -16,7 +16,7 @@
 CFLAGS		= -I$(MERCURY_DIR)/runtime -I$(MERCURY_DIR)/boehm_gc -g \
 		  $(DLL_CFLAGS) $(EXTRA_CFLAGS)
 MGNUC		= MERCURY_C_INCL_DIR=. $(SCRIPTS_DIR)/mgnuc
-MGNUCFLAGS	= --no-ansi $(CFLAGS)
+MGNUCFLAGS	= --no-ansi $(EXTRA_MGNUCFLAGS) $(CFLAGS)
 MOD2C		= $(SCRIPTS_DIR)/mod2c
 
 #-----------------------------------------------------------------------------#
@@ -41,6 +41,7 @@
 			mercury_imp.h		\
 			mercury_init.h		\
 			mercury_label.h		\
+			mercury_stack_layout.h	\
 			mercury_memory.h	\
 			mercury_misc.h		\
 			mercury_overflow.h	\
@@ -51,6 +52,7 @@
 			mercury_spinlock.h	\
 			mercury_std.h		\
 			mercury_stacks.h	\
+			mercury_stack_trace.h	\
 			mercury_string.h	\
 			mercury_table.h		\
 			mercury_tags.h		\
@@ -93,6 +95,7 @@
 			mercury_prof_mem.c	\
 			mercury_regs.c		\
 			mercury_spinlock.c	\
+			mercury_stack_trace.c	\
 			mercury_table.c		\
 			mercury_timing.c	\
 			mercury_trace.c		\
Index: runtime/mercury_accurate_gc.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_accurate_gc.h,v
retrieving revision 1.6
diff -u -r1.6 mercury_accurate_gc.h
--- mercury_accurate_gc.h	1998/02/03 08:17:17	1.6
+++ mercury_accurate_gc.h	1998/03/05 02:40:35
@@ -15,289 +15,5 @@
 
 /*---------------------------------------------------------------------------*/
 
-/*
-** Defintions used for accessing and creating stack_layouts.
-**
-** NOTE: The constants and data-structures used here need to be kept in
-** 	 sync with the ones generated in the compiler. If you change
-** 	 anything here, you may need to change compiler/stack_layout.m
-** 	 as well.
-*/
-
-#ifdef NATIVE_GC
- #define MR_USE_STACK_LAYOUTS
-#endif
-
-/*
-** Definitions for MR_PredFunc
-*/
-
-typedef	enum { MR_PREDICATE, MR_FUNCTION } MR_PredFunc;
-
-/*
-** Definitions for MR_Determinism
-**
-** The max_soln component of the determinism is encoded in the 1 and 2 bits.
-** The can_fail component of the determinism is encoded in the 4 bit.
-** The first_solution component of the determinism is encoded in the 8 bit.
-**
-** MR_DETISM_AT_MOST_MANY could also be defined as ((d) & 3) == 3),
-** but this would be less efficient, since the C compiler does not know
-** that we do not set the 1 bit unless we also set the 2 bit.
-*/
-
-typedef	Word MR_Determinism;
-
-#define	MR_DETISM_DET		6
-#define	MR_DETISM_SEMI		2
-#define	MR_DETISM_NON		3
-#define	MR_DETISM_MULTI		7
-#define	MR_DETISM_ERRONEOUS	4
-#define	MR_DETISM_FAILURE	0
-#define	MR_DETISM_CCNON		10
-#define	MR_DETISM_CCMULTI	14
-
-#define MR_DETISM_AT_MOST_ZERO(d)	((d) & 3) == 0)
-#define MR_DETISM_AT_MOST_ONE(d)	((d) & 3) == 2)
-#define MR_DETISM_AT_MOST_MANY(d)	((d) & 1) != 0)
-
-#define MR_DETISM_CAN_FAIL(d)		((d) & 4) != 0)
-
-#define MR_DETISM_FIRST_SOLN(d)		((d) & 8) != 0)
-
-/*
-** Definitions for "MR_Live_Lval"
-**
-** MR_Live_Lval is a Word which describes an lval. This includes:
-** 	- stack slots, registers, and special lvals such as succip, hp,
-** 	  etc.
-**
-** MR_Live_Lval is encoded using an 8 bit low tag, the rest of the word is a 
-** data field describing which stack slot number or register number.
-**
-**  Lval		Tag	Rest
-**  r(Num)		 0	Num
-**  f(Num)		 1	Num
-**  stackvar(Num)	 2	Num
-**  framevar(Num)	 3	Num
-**  succip		 4
-**  maxfr		 5
-**  curfr		 6
-**  hp			 7
-**  sp			 8
-**  unknown		 9		(The location is not known)
-**
-** The type MR_Lval_Type describes the different tag values.
-**
-** This data is generated in compiler/stack_layout.m, which must be kept
-** in sync with the constants defined here.
-*/
-
-typedef Word MR_Live_Lval;
-
-typedef enum { 
-	MR_LVAL_TYPE_R,
-	MR_LVAL_TYPE_F,
-	MR_LVAL_TYPE_STACKVAR,
-	MR_LVAL_TYPE_FRAMEVAR,
-	MR_LVAL_TYPE_SUCCIP,
-	MR_LVAL_TYPE_MAXFR,
-	MR_LVAL_TYPE_CURFR,
-	MR_LVAL_TYPE_HP,
-	MR_LVAL_TYPE_SP,
-	MR_LVAL_TYPE_UNKNOWN 
-} MR_Lval_Type;
-
-#define MR_LIVE_LVAL_TAGBITS	8
-
-#define MR_LIVE_LVAL_TYPE(Lval) 			\
-	((MR_Lval_Type) ((Lval) & ((1 << MR_LIVE_LVAL_TAGBITS) - 1)))
-
-#define MR_LIVE_LVAL_NUMBER(Lval) 			\
-	((Word) (Lval) >> MR_LIVE_LVAL_TAGBITS)
-
-/*
-** Definitions for MR_Live_Type
-**
-** MR_Live_Type describes live data. This includes:
-** 	- succip, hp, curfr, maxfr, redoip, and
-** 	  mercury data values (vars).
-**
-** The data is encoded such that low values (less than
-** TYPELAYOUT_MAX_VARINT) represent succip, hp, etc.  Higher values
-** represent data variables, and are pointers to a 2 word cell, 
-** containing a type_info and an instantiation represention.
-**
-** This data is generated in compiler/stack_layout.m, which must be kept
-** in sync with the constants defined here.
-*/
-
-typedef Word MR_Live_Type;
-
-typedef enum { 
-	MR_LIVE_TYPE_SUCCIP,
-	MR_LIVE_TYPE_HP,
-	MR_LIVE_TYPE_CURFR,
-	MR_LIVE_TYPE_MAXFR,
-	MR_LIVE_TYPE_REDOIP,
-	MR_LIVE_TYPE_UNWANTED 
-} MR_Lval_NonVar;
-
-typedef struct { 
-	Word	type;
-	Word	inst;
-} MR_Var_Shape_Info;
-
-#define MR_LIVE_TYPE_IS_VAR(T)         ( (Word) T > TYPELAYOUT_MAX_VARINT )
-
-#define MR_LIVE_TYPE_GET_NONVAR(T)			\
-		((MR_Lval_NonVar) T)
-
-#define MR_LIVE_TYPE_GET_VAR_TYPE(T)   			\
-		((Word) ((MR_Var_Shape_Info *) T)->type)
-
-#define MR_LIVE_TYPE_GET_VAR_INST(T)   			\
-		((Word) ((MR_Var_Shape_Info *) T)->inst)
-
-/*
-** Macros to support hand-written C code.
-*/
-
-/*
-** Define a stack layout for a label that you know very little about.
-** It's just a generic entry label, no useful information, except
-** the code address for the label.
-*/ 
-#ifdef MR_USE_STACK_LAYOUTS
- #define MR_MAKE_STACK_LAYOUT_ENTRY(l) 					\
- const struct mercury_data__stack_layout__##l##_struct {		\
-	Code * f1;							\
-	Integer f2;							\
-	Integer f3;							\
-	Integer f4;							\
- } mercury_data__stack_layout__##l = {					\
-	STATIC(l),							\
-	(Integer) -1, 	/* Unknown determinism */			\
-	(Integer) -1,	/* Unknown number of stack slots */		\
-        (Integer) MR_LVAL_TYPE_UNKNOWN 	/* Unknown succip location */	\
- };
-#else
- #define MR_MAKE_STACK_LAYOUT_ENTRY(l)        
-#endif	/* MR_USE_STACK_LAYOUTS */
-
-/*
-** Define a stack layout for an internal label. Need to supply the
-** label name (l) and the entry label name (e).
-**
-** The only useful information in this structure is the code address
-** and the reference to the entry for this label.
-*/ 
-#ifdef MR_USE_STACK_LAYOUTS
- #define MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e)			\
- const struct mercury_data__stack_layout__##l##_struct {		\
-	const Word * f1;						\
-	Integer f2;							\
-	const Word * f3;						\
- } mercury_data__stack_layout__##l = {					\
-	(const Word *) &mercury_data__stack_layout__##e,		\
-	(Integer) -1,		/* Unknown number of live values */	\
-	(const Word *) NULL	/* No list of live valeus */		\
- };
-#else
- #define MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e)        
-#endif	/* MR_USE_STACK_LAYOUTS */
-
-/*
-** Define a stack layout for an internal label.
-** Need to supply the label name (l) and the number (x), eg for
-** label_name_i3, x is 3. It is assumed the entry label for that
-** corresponds to this label is the label name without the _iX suffix.
-**
-** (MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY, above, is a little
-** more general than MR_MAKE_STACK_LAYOUT_INTERNAL. This macro can
-** only describe relationships between labels that have the same
-** base -- MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY can create layouts
-** for internal labels no matter what the name of the entry layout is).
-**
-** The only useful information in this structure is the code address
-** and the reference to the entry for this label.
-*/ 
-#ifdef MR_USE_STACK_LAYOUTS
- #define MR_MAKE_STACK_LAYOUT_INTERNAL(e, x)				\
- const struct mercury_data__stack_layout__##e##_i##x##_struct {		\
-	const Word * f1;						\
-	Integer f2;							\
-	const Word * f3;						\
- } mercury_data__stack_layout__##e##_i##x = {				\
-	(const Word *) &mercury_data__stack_layout__##e,		\
-	(Integer) -1,		/* Unknown number of live values */	\
-	(const Word *) NULL	/* No list of live valeus */		\
- };
-#else
- #define MR_MAKE_STACK_LAYOUT_INTERNAL(l, x)        
-#endif	/* MR_USE_STACK_LAYOUTS */
-
-/*
-** Structs and macros to support stack layouts.
-*/
-
-typedef	struct MR_stack_layout_shape_struct {
-	Word			*MR_sls_type;
-	Word			MR_sls_inst;
-} MR_stack_layout_shape;
-
-typedef	struct MR_stack_layout_var_struct {
-	Integer			MR_slv_locn;
-	MR_stack_layout_shape	*MR_slv_shape;
-} MR_stack_layout_var;
-
-typedef	struct MR_stack_layout_vars_struct {
-	MR_stack_layout_var	*MR_slvs_pairs;
-	String			*MR_slvs_names;
-	Word			*MR_slvs_tvars;
-} MR_stack_layout_vars;
-
-typedef	struct MR_stack_layout_entry_struct {
-	Code			*MR_sle_code_addr;
-	MR_Determinism		MR_sle_detism;
-	Integer			MR_sle_stack_slots;
-	MR_Live_Lval		MR_sle_succip_locn;
-	/* the fields from here onwards are present only with procid layouts */
-	MR_PredFunc		MR_sle_pred_or_func;
-	String			MR_sle_decl_module;
-	String			MR_sle_def_module;
-	String			MR_sle_name;
-	Integer			MR_sle_arity;
-	Integer			MR_sle_mode;
-	/* the fields from here onwards are present only with trace layouts */
-	Integer			MR_sle_in_arg_count;
-	MR_stack_layout_vars	MR_sle_in_arg_info;
-	Integer			MR_sle_out_arg_count;
-	MR_stack_layout_vars	MR_sle_out_arg_info;
-} MR_stack_layout_entry;
-
-typedef	struct MR_stack_layout_label_struct {
-	MR_stack_layout_entry	*MR_sll_entry;
-	Integer			MR_sll_var_count;
-	/* the last field is present only if MR_sll_var_count > 0 */
-	MR_stack_layout_vars	MR_sll_var_info;
-} MR_stack_layout_label;
-
-/* The following macros support obsolete code. */
-#define MR_ENTRY_STACK_LAYOUT_GET_LABEL_ADDRESS(s)		\
-		((Code *) field(0, (s), 0))
-
-#define MR_CONT_STACK_LAYOUT_GET_ENTRY_LAYOUT(s)		\
-		(field(0, (s), 0))
-
-#define MR_ENTRY_STACK_LAYOUT_GET_NUM_SLOTS(s)			\
-		(field(0, (s), 2))
-
-#define MR_ENTRY_STACK_LAYOUT_GET_CODE_MODEL(s)			\
-		(field(0, (s), 1) & 1)
-
-#define MR_ENTRY_STACK_LAYOUT_GET_SUCCIP_LOC(s)			\
-		(field(0, (s), 3))
-
 /*---------------------------------------------------------------------------*/
 #endif /* not MERCURY_ACCURATE_GC_H */
Index: runtime/mercury_conf.h.in
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_conf.h.in,v
retrieving revision 1.3
diff -u -r1.3 mercury_conf.h.in
--- mercury_conf.h.in	1997/11/23 09:31:48	1.3
+++ mercury_conf.h.in	1998/03/05 06:28:29
@@ -7,7 +7,8 @@
 /*
 ** mercury_conf.h.in -
 **	Various configuration parameters, determined automatically by
-**	the auto-configuration script.
+**	the auto-configuration script.  Implications of configuration 
+**	parameters, and combinations of paramters.
 */
 
 /*
@@ -197,5 +198,50 @@
 ** (True for SunOS 4.x.)
 */
 #undef MR_CANNOT_GROK_ASM_TYPE_DIRECTIVE
+
+/*
+** Implications of configuration parameters.
+**
+** Meaning of parameters:
+**
+** MR_USE_STACK_LAYOUTS -- stack layouts are in use, generate stack
+**                         layout structures.
+** MR_INSERT_LABELS     -- labels need to be inserted into the label table. 
+**			   (this also means the initialization code needs
+**			   to be run).
+** MR_NEED_INITIALIZATION_CODE -- the module specific initialization code
+**				  is needed (doesn't actually run the code,
+**				  however).
+*/
+
+#if defined(MR_STACK_TRACE) || defined(NATIVE_GC)
+  #define MR_USE_STACK_LAYOUTS
+  #define MR_INSERT_LABELS
+#endif
+
+#if defined(SPEED) && !defined(DEBUG_GOTOS) 
+  #define MR_INSERT_LABELS
+#endif
+
+/*
+** Static code addresses are available unless using gcc non-local gotos,
+** without assembler labels.
+*/
+#if	(defined(USE_GCC_NONLOCAL_GOTOS) && !defined(USE_ASM_LABELS))
+	#undef MR_STATIC_CODE_ADDRESSES
+#else
+	#define MR_STATIC_CODE_ADDRESSES
+#endif
+
+/*
+** You need to run initialization code for grades without static
+** code addresses, for profiling, and any time you need to insert
+** labels into the label table.
+*/
+#if defined(MR_STATIC_CODE_ADDRESSES) || defined(PROFILE_CALLS) \
+	|| defined(DEBUG_LABELS) || defined(MR_INSERT_LABELS)
+  #define MR_NEED_INITIALIZATION_CODE
+#endif
+
 
 #endif /* MERCURY_CONF_H */
Index: runtime/mercury_goto.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_goto.h,v
retrieving revision 1.5
diff -u -r1.5 mercury_goto.h
--- mercury_goto.h	1998/01/06 07:05:59	1.5
+++ mercury_goto.h	1998/03/05 06:09:35
@@ -9,9 +9,9 @@
 #ifndef MERCURY_GOTO_H
 #define MERCURY_GOTO_H
 
+#include "mercury_conf.h"
 #include "mercury_types.h"	/* for `Code *' */
 #include "mercury_debug.h"	/* for debuggoto() */
-#include "mercury_accurate_gc.h"
 
 #define paste(a,b) a##b
 #define stringify(string) #string
@@ -19,10 +19,10 @@
 #define skip(label) paste(skip_,label)
 
 #ifdef MR_USE_STACK_LAYOUTS
- #define MR_STACK_LAYOUT(label)        (Word *) (Word) \
+  #define MR_STACK_LAYOUT(label)        (Word *) (Word) \
 	&(paste(mercury_data__stack_layout__,label))
 #else
- #define MR_STACK_LAYOUT(label) (Word *) NULL
+  #define MR_STACK_LAYOUT(label) (Word *) NULL
 #endif /* MR_USE_STACK_LAYOUTS */
 
 
@@ -34,24 +34,23 @@
 ** accurate garbage collection.
 */
 
-#if defined(SPEED) && !defined(DEBUG_GOTOS) && !defined(NATIVE_GC)
-#define	make_label(n, a, l)	/* nothing */
+#if !defined(MR_INSERT_LABELS)
+  #define	make_label(n, a, l)	/* nothing */
 #else
-#define	make_label(n, a, l)	make_entry(n, a, l)
+  #define	make_label(n, a, l)	make_entry(n, a, l)
 #endif
 
-#if defined(SPEED) && !defined(DEBUG_GOTOS) && !defined(PROFILE_CALLS) \
-			&& !defined(NATIVE_GC)
-#define make_local(n, a, l)	/* nothing */
+#if !defined(MR_INSERT_LABELS) && !defined(PROFILE_CALLS)
+  #define make_local(n, a, l)	/* nothing */
 #else 
-#define make_local(n, a, l)	make_entry(n, a, l)
+  #define make_local(n, a, l)	make_entry(n, a, l)
 #endif
 
-#if defined(SPEED) && !defined(DEBUG_LABELS) && !defined(DEBUG_GOTOS) \
-			&& !defined(PROFILE_CALLS) && !defined(NATIVE_GC)
-#define make_entry(n, a, l)	/* nothing */
+#if !defined(MR_INSERT_LABELS) && !defined(PROFILE_CALLS) \
+		&& !defined(DEBUG_LABELS)
+  #define make_entry(n, a, l)	/* nothing */
 #else
-#define make_entry(n, a, l)	insert_entry(n, a, MR_STACK_LAYOUT(l))
+  #define make_entry(n, a, l)	insert_entry(n, a, MR_STACK_LAYOUT(l))
 #endif
 
 
@@ -517,7 +516,7 @@
   #define init_local(label)	make_local(stringify(label), &&label, label)
   #define Define_label(label)	Define_local(label)
   #define Declare_label(label)	/* no declaration required */
-  #ifdef NATIVE_GC
+  #ifdef MR_INSERT_LABELS
    #define init_label(label)	\
 	make_label(stringify(label), &&entry(label), label)
   #else
Index: runtime/mercury_grade.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_grade.h,v
retrieving revision 1.5
diff -u -r1.5 mercury_grade.h
--- mercury_grade.h	1997/12/05 15:56:31	1.5
+++ mercury_grade.h	1998/03/04 06:09:49
@@ -31,11 +31,11 @@
 #define MR_PASTE2(p1,p2)	MR_PASTE2_2(p1,p2)
 #define MR_PASTE2_2(p1,p2)	p1##p2
 
-/* paste 9 macros together */
-#define MR_PASTE10(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10) \
-				MR_PASTE10_2(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10)
-#define MR_PASTE10_2(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10) \
-				p1##p2##p3##p4##p5##p6##p7##p8##p9##p10
+/* paste 10 macros together */
+#define MR_PASTE11(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11) \
+				MR_PASTE11_2(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11)
+#define MR_PASTE11_2(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11) \
+				p1##p2##p3##p4##p5##p6##p7##p8##p9##p10##p11
 
 /*
 ** Here we build up the MR_GRADE macro part at a time,
@@ -151,7 +151,19 @@
   #define MR_GRADE_PART_10
 #endif
 
-#define MR_GRADE		MR_PASTE10(			\
+/*
+** Stack traces aren't strictly binary incompatible - but if you
+** try to do a stack trace you might find it doesn't work very
+** well unless all modules are compiled in with --stack-trace.
+** Hence we consider it effectively binary incompatible.
+*/
+#if defined(MR_STACK_TRACE)
+  #define MR_GRADE_PART_11	_strce
+#else
+  #define MR_GRADE_PART_11
+#endif
+
+#define MR_GRADE		MR_PASTE11(			\
 					MR_GRADE_PART_1,	\
 					MR_GRADE_PART_2,	\
 					MR_GRADE_PART_3,	\
@@ -161,7 +173,8 @@
 					MR_GRADE_PART_7,	\
 					MR_GRADE_PART_8,	\
 					MR_GRADE_PART_9,	\
-					MR_GRADE_PART_10	\
+					MR_GRADE_PART_10,	\
+					MR_GRADE_PART_11	\
 				)
 
 #define MR_GRADE_VAR		MR_PASTE2(MR_grade_,MR_GRADE)
Index: runtime/mercury_ho_call.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_ho_call.c,v
retrieving revision 1.6
diff -u -r1.6 mercury_ho_call.c
--- mercury_ho_call.c	1998/02/12 01:25:54	1.6
+++ mercury_ho_call.c	1998/03/04 07:52:31
@@ -51,11 +51,8 @@
 #define MR_CLASS_METHOD_CALL_INPUTS	4
 
 Define_extern_entry(do_call_det_closure);
-Declare_label(det_closure_return);
 Define_extern_entry(do_call_semidet_closure);
-Declare_label(semidet_closure_return);
 Define_extern_entry(do_call_nondet_closure);
-Declare_label(nondet_closure_return);
 
 Define_extern_entry(do_call_det_class_method);
 Define_extern_entry(do_call_semidet_class_method);
@@ -71,14 +68,8 @@
 Declare_label(mercury__compare_3_0_i1);
 
 MR_MAKE_STACK_LAYOUT_ENTRY(do_call_det_closure);
-MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(det_closure_return, 
-	do_call_det_closure);
 MR_MAKE_STACK_LAYOUT_ENTRY(do_call_semidet_closure);
-MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(semidet_closure_return,
-	do_call_semidet_closure);
 MR_MAKE_STACK_LAYOUT_ENTRY(do_call_nondet_closure);
-MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(nondet_closure_return,
-	do_call_nondet_closure);
 
 MR_MAKE_STACK_LAYOUT_ENTRY(do_call_det_class_method);
 MR_MAKE_STACK_LAYOUT_ENTRY(do_call_semidet_class_method);
@@ -96,11 +87,8 @@
 
 BEGIN_MODULE(call_module)
 	init_entry(do_call_det_closure);
-	init_label(det_closure_return);
 	init_entry(do_call_semidet_closure);
-	init_label(semidet_closure_return);
 	init_entry(do_call_nondet_closure);
-	init_label(nondet_closure_return);
 
 	init_entry(do_call_det_class_method);
 	init_entry(do_call_semidet_class_method);
Index: runtime/mercury_imp.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_imp.h,v
retrieving revision 1.4
diff -u -r1.4 mercury_imp.h
--- mercury_imp.h	1997/12/05 15:56:38	1.4
+++ mercury_imp.h	1998/02/19 05:22:03
@@ -41,7 +41,9 @@
 #include	"mercury_types.h"
 #include	"mercury_string.h"
 #include	"mercury_float.h"
+#include	"mercury_stack_trace.h"
 #include	"mercury_accurate_gc.h"
+#include	"mercury_stack_layout.h"
 
 #include	"mercury_tags.h"
 #include	"mercury_goto.h"
Index: runtime/mercury_type_info.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_type_info.h,v
retrieving revision 1.4
diff -u -r1.4 mercury_type_info.h
--- mercury_type_info.h	1998/01/23 12:12:05	1.4
+++ mercury_type_info.h	1998/03/05 06:22:27
@@ -326,17 +326,6 @@
 */
 
 /*
-** Static code addresses are available, unless using gcc non-local gotos,
-** without assembler labels.
-*/
-
-#if	(defined(USE_GCC_NONLOCAL_GOTOS) && !defined(USE_ASM_LABELS))
-	#undef MR_STATIC_CODE_ADDRESSES
-#else
-	#define MR_STATIC_CODE_ADDRESSES
-#endif
-
-/*
 ** Definitions for initialization of base_type_infos. If
 ** MR_STATIC_CODE_ADDRESSES are not available, we need to initialize
 ** the special predicates in the base_type_infos.
Index: scripts/mgnuc.in
===================================================================
RCS file: /home/staff/zs/imp/mercury/scripts/mgnuc.in,v
retrieving revision 1.47
diff -u -r1.47 mgnuc.in
--- mgnuc.in	1998/03/03 06:12:28	1.47
+++ mgnuc.in	1998/03/04 07:50:03
@@ -33,6 +33,7 @@
 	--pic-reg
 	--inline-alloc
 	--split-c-files
+	--stack-trace
 		See the documentation in the \"Invocation\" section
 		of the Mercury User's Guide.
 		
@@ -140,6 +141,13 @@
 		SPLIT_OPTS=
 		;;
 
+	--stack-trace)
+		STACK_TRACE_OPTS=-DMR_STACK_TRACE
+		;;
+	--no-stack-trace)
+		STACK_TRACE_OPTS=
+		;;
+
 	--inline-alloc)
 		INLINE_ALLOC_OPTS="-DINLINE_ALLOC -DSILENT"
 		;;
@@ -343,26 +351,19 @@
 	exec $AS $AS_OPTS "$@" ;;
 esac
 
-# please keep the three long lines below in sync
-case $verbose in true)
-	echo $CC $ALL_C_INCL_DIRS $ANSI_OPTS $CHECK_OPTS \
-		$GRADE_OPTS $GC_OPTS \
+
+ALL_CC_OPTS="$ANSI_OPTS $CHECK_OPTS $GRADE_OPTS $GC_OPTS	\
 		$PROF_TIME_OPTS $PROF_CALLS_OPTS $PROF_MEMORY_OPTS \
 		$INLINE_ALLOC_OPTS $TRAIL_OPTS $SPLIT_OPTS \
-		$PICREG_OPTS $ARCH_OPTS $ARG_OPTS \
-		"$@" $OVERRIDE_OPTS ;;
+		$STACK_TRACE_OPTS $PICREG_OPTS $ARCH_OPTS $ARG_OPTS"
+
+case $verbose in true)
+	echo $CC -I$C_INCL_DIR -I$GC_INCL_DIR \
+		$ALL_CC_OPTS "$@" $OVERRIDE_OPTS ;;
 esac
 case $# in
-	0) exec $CC $ALL_C_INCL_DIRS $ANSI_OPTS $CHECK_OPTS \
-		$GRADE_OPTS $GC_OPTS \
-		$PROF_TIME_OPTS $PROF_CALLS_OPTS $PROF_MEMORY_OPTS \
-		$INLINE_ALLOC_OPTS $TRAIL_OPTS $SPLIT_OPTS \
-		$PICREG_OPTS $ARCH_OPTS $ARG_OPTS \
-		$OVERRIDE_OPTS ;;
-	*) exec $CC $ALL_C_INCL_DIRS $ANSI_OPTS $CHECK_OPTS \
-		$GRADE_OPTS $GC_OPTS \
-		$PROF_TIME_OPTS $PROF_CALLS_OPTS $PROF_MEMORY_OPTS \
-		$INLINE_ALLOC_OPTS $TRAIL_OPTS $SPLIT_OPTS \
-		$PICREG_OPTS $ARCH_OPTS $ARG_OPTS \
-		"$@" $OVERRIDE_OPTS ;;
+	0) exec $CC -I$C_INCL_DIR -I$GC_INCL_DIR \
+		$ALL_CC_OPTS $OVERRIDE_OPTS ;;
+	*) exec $CC -I$C_INCL_DIR -I$GC_INCL_DIR \
+		$ALL_CC_OPTS "$@" $OVERRIDE_OPTS ;;
 esac
Index: util/mkinit.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/util/mkinit.c,v
retrieving revision 1.26
diff -u -r1.26 mkinit.c
--- mkinit.c	1998/02/03 08:20:12	1.26
+++ mkinit.c	1998/03/05 06:32:17
@@ -174,10 +174,7 @@
 
 
 static const char if_need_to_init[] = 
-	"#if (defined(USE_GCC_NONLOCAL_GOTOS) && !defined(USE_ASM_LABELS)) \\\n"
-	"	|| defined(PROFILE_CALLS) || defined(DEBUG_GOTOS) \\\n"
-	"	|| defined(DEBUG_LABELS) || defined(NATIVE_GC) \\\n"
-	"	|| !defined(SPEED)\n\n"
+	"#if defined(MR_NEED_INITIALIZATION_CODE)\n\n"
 	;
 
 

New File: runtime/mercury_stack_layout.h
===================================================================
/*
** Copyright (C) 1998 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/

#ifndef MERCURY_STACK_LAYOUT_H
#define MERCURY_STACK_LAYOUT_H

/*
** mercury_stack_layout.h -
**	Definitions for the stack layout data structures. 
*/

/*
** Definitions for MR_PredFunc
*/

typedef	enum { MR_PREDICATE, MR_FUNCTION } MR_PredFunc;

/*
** Definitions for MR_Determinism
**
** The max_soln component of the determinism is encoded in the 1 and 2 bits.
** The can_fail component of the determinism is encoded in the 4 bit.
** The first_solution component of the determinism is encoded in the 8 bit.
**
** MR_DETISM_AT_MOST_MANY could also be defined as ((d) & 3) == 3),
** but this would be less efficient, since the C compiler does not know
** that we do not set the 1 bit unless we also set the 2 bit.
*/

typedef	Word MR_Determinism;

#define	MR_DETISM_DET		6
#define	MR_DETISM_SEMI		2
#define	MR_DETISM_NON		3
#define	MR_DETISM_MULTI		7
#define	MR_DETISM_ERRONEOUS	4
#define	MR_DETISM_FAILURE	0
#define	MR_DETISM_CCNON		10
#define	MR_DETISM_CCMULTI	14

#define MR_DETISM_AT_MOST_ZERO(d)	(((d) & 3) == 0)
#define MR_DETISM_AT_MOST_ONE(d)	(((d) & 3) == 2)
#define MR_DETISM_AT_MOST_MANY(d)	(((d) & 1) != 0)

#define MR_DETISM_CAN_FAIL(d)		(((d) & 4) != 0)

#define MR_DETISM_FIRST_SOLN(d)		(((d) & 8) != 0)

#define MR_DETISM_DET_CODE_MODEL(d)	(((d) & 1) == 0)

/*
** Definitions for "MR_Live_Lval"
**
** MR_Live_Lval is a Word which describes an lval. This includes:
** 	- stack slots, registers, and special lvals such as succip, hp,
** 	  etc.
**
** MR_Live_Lval is encoded using an 8 bit low tag, the rest of the word is a 
** data field describing which stack slot number or register number.
**
**  Lval		Tag	Rest
**  r(Num)		 0	Num
**  f(Num)		 1	Num
**  stackvar(Num)	 2	Num
**  framevar(Num)	 3	Num
**  succip		 4
**  maxfr		 5
**  curfr		 6
**  hp			 7
**  sp			 8
**  unknown		 9		(The location is not known)
**
** The type MR_Lval_Type describes the different tag values.
**
** This data is generated in compiler/stack_layout.m, which must be kept
** in sync with the constants defined here.
*/

typedef Word MR_Live_Lval;

typedef enum { 
	MR_LVAL_TYPE_R,
	MR_LVAL_TYPE_F,
	MR_LVAL_TYPE_STACKVAR,
	MR_LVAL_TYPE_FRAMEVAR,
	MR_LVAL_TYPE_SUCCIP,
	MR_LVAL_TYPE_MAXFR,
	MR_LVAL_TYPE_CURFR,
	MR_LVAL_TYPE_HP,
	MR_LVAL_TYPE_SP,
	MR_LVAL_TYPE_UNKNOWN 
} MR_Lval_Type;

#define MR_LIVE_LVAL_TAGBITS	8

#define MR_LIVE_LVAL_TYPE(Lval) 			\
	((MR_Lval_Type) (((Word) Lval) & ((1 << MR_LIVE_LVAL_TAGBITS) - 1)))

#define MR_LIVE_LVAL_NUMBER(Lval) 			\
	((int) ((Word) Lval) >> MR_LIVE_LVAL_TAGBITS)

/*
** Definitions for MR_Live_Type
**
** MR_Live_Type describes live data. This includes:
** 	- succip, hp, curfr, maxfr, redoip, and
** 	  mercury data values (vars).
**
** The data is encoded such that low values (less than
** TYPELAYOUT_MAX_VARINT) represent succip, hp, etc.  Higher values
** represent data variables, and are pointers to a 2 word cell, 
** containing a type_info and an instantiation represention.
**
** This data is generated in compiler/stack_layout.m, which must be kept
** in sync with the constants defined here.
*/

typedef Word MR_Live_Type;

typedef enum { 
	MR_LIVE_TYPE_SUCCIP,
	MR_LIVE_TYPE_HP,
	MR_LIVE_TYPE_CURFR,
	MR_LIVE_TYPE_MAXFR,
	MR_LIVE_TYPE_REDOIP,
	MR_LIVE_TYPE_UNWANTED 
} MR_Lval_NonVar;

typedef struct { 
	Word	type;
	Word	inst;
} MR_Var_Shape_Info;

#define MR_LIVE_TYPE_IS_VAR(T)         ( (Word) T > TYPELAYOUT_MAX_VARINT )

#define MR_LIVE_TYPE_GET_NONVAR(T)			\
		((MR_Lval_NonVar) T)

#define MR_LIVE_TYPE_GET_VAR_TYPE(T)   			\
		((Word) ((MR_Var_Shape_Info *) T)->type)

#define MR_LIVE_TYPE_GET_VAR_INST(T)   			\
		((Word) ((MR_Var_Shape_Info *) T)->inst)

/*
** Macros to support hand-written C code.
*/

/*
** Define a stack layout for a label that you know very little about.
** It's just a generic entry label, no useful information, except
** the code address for the label.
*/ 
#ifdef MR_USE_STACK_LAYOUTS
 #define MR_MAKE_STACK_LAYOUT_ENTRY(l) 					\
 const struct mercury_data__stack_layout__##l##_struct {		\
	Code * f1;							\
	Integer f2;							\
	Integer f3;							\
	Integer f4;							\
 } mercury_data__stack_layout__##l = {					\
	STATIC(l),							\
	(Integer) -1, 	/* Unknown determinism */			\
	(Integer) -1,	/* Unknown number of stack slots */		\
        (Integer) MR_LVAL_TYPE_UNKNOWN 	/* Unknown succip location */	\
 };
#else
 #define MR_MAKE_STACK_LAYOUT_ENTRY(l)        
#endif	/* MR_USE_STACK_LAYOUTS */

/*
** Define a stack layout for an internal label. Need to supply the
** label name (l) and the entry label name (e).
**
** The only useful information in this structure is the code address
** and the reference to the entry for this label.
*/ 
#ifdef MR_USE_STACK_LAYOUTS
 #define MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e)			\
 const struct mercury_data__stack_layout__##l##_struct {		\
	const Word * f1;						\
	Integer f2;							\
	const Word * f3;						\
 } mercury_data__stack_layout__##l = {					\
	(const Word *) &mercury_data__stack_layout__##e,		\
	(Integer) -1,		/* Unknown number of live values */	\
	(const Word *) NULL	/* No list of live valeus */		\
 };
#else
 #define MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e)        
#endif	/* MR_USE_STACK_LAYOUTS */

/*
** Define a stack layout for an internal label.
** Need to supply the label name (l) and the number (x), eg for
** label_name_i3, x is 3. It is assumed the entry label for that
** corresponds to this label is the label name without the _iX suffix.
**
** (MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY, above, is a little
** more general than MR_MAKE_STACK_LAYOUT_INTERNAL. This macro can
** only describe relationships between labels that have the same
** base -- MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY can create layouts
** for internal labels no matter what the name of the entry layout is).
**
** The only useful information in this structure is the code address
** and the reference to the entry for this label.
*/ 
#ifdef MR_USE_STACK_LAYOUTS
 #define MR_MAKE_STACK_LAYOUT_INTERNAL(e, x)				\
 const struct mercury_data__stack_layout__##e##_i##x##_struct {		\
	const Word * f1;						\
	Integer f2;							\
	const Word * f3;						\
 } mercury_data__stack_layout__##e##_i##x = {				\
	(const Word *) &mercury_data__stack_layout__##e,		\
	(Integer) -1,		/* Unknown number of live values */	\
	(const Word *) NULL	/* No list of live valeus */		\
 };
#else
 #define MR_MAKE_STACK_LAYOUT_INTERNAL(l, x)        
#endif	/* MR_USE_STACK_LAYOUTS */

/*
** Structs and macros to support stack layouts.
*/

typedef	struct MR_stack_layout_shape_struct {
	Word			*MR_sls_type;
	Word			MR_sls_inst;
} MR_stack_layout_shape;

typedef	struct MR_stack_layout_var_struct {
	Integer			MR_slv_locn;
	MR_stack_layout_shape	*MR_slv_shape;
} MR_stack_layout_var;

typedef	struct MR_stack_layout_vars_struct {
	MR_stack_layout_var	*MR_slvs_pairs;
	String			*MR_slvs_names;
	Word			*MR_slvs_tvars;
} MR_stack_layout_vars;

typedef	struct MR_stack_layout_entry_struct {
	Code			*MR_sle_code_addr;
	MR_Determinism		MR_sle_detism;
	Integer			MR_sle_stack_slots;
	MR_Live_Lval		MR_sle_succip_locn;
	/* the fields from here onwards are present only with procid layouts */
	MR_PredFunc		MR_sle_pred_or_func;
	String			MR_sle_decl_module;
	String			MR_sle_def_module;
	String			MR_sle_name;
	Integer			MR_sle_arity;
	Integer			MR_sle_mode;
	/* the fields from here onwards are present only with trace layouts */
	Integer			MR_sle_in_arg_count;
	MR_stack_layout_vars	MR_sle_in_arg_info;
	Integer			MR_sle_out_arg_count;
	MR_stack_layout_vars	MR_sle_out_arg_info;
} MR_stack_layout_entry;

typedef	struct MR_stack_layout_label_struct {
	MR_stack_layout_entry	*MR_sll_entry;
	Integer			MR_sll_var_count;
	/* the last field is present only if MR_sll_var_count > 0 */
	MR_stack_layout_vars	MR_sll_var_info;
} MR_stack_layout_label;

/* The following macros support obsolete code. */
#define MR_ENTRY_STACK_LAYOUT_GET_LABEL_ADDRESS(s)		\
		((Code *) field(0, (s), 0))

#define MR_CONT_STACK_LAYOUT_GET_ENTRY_LAYOUT(s)		\
		(field(0, (s), 0))

#define MR_ENTRY_STACK_LAYOUT_GET_NUM_SLOTS(s)			\
		(field(0, (s), 2))

#define MR_ENTRY_STACK_LAYOUT_GET_CODE_MODEL(s)			\
		(field(0, (s), 1) & 1)

#define MR_ENTRY_STACK_LAYOUT_GET_SUCCIP_LOC(s)			\
		(field(0, (s), 3))

/*---------------------------------------------------------------------------*/
#endif /* not MERCURY_STACK_LAYOUT_H */


New File: runtime/mercury_stack_trace.c
===================================================================
/*
** Copyright (C) 1998 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/

/*
** mercury_stack_trace.c - implements stack traces.
**
** Main author: Tyson Dowd <trd at cs.mu.oz.au>.
*/

#include "mercury_imp.h"
#include "mercury_stack_trace.h"
#include <stdio.h>

void
MR_dump_stack(Code *success_pointer, Word *det_stack_pointer)
{
	Label *label;
	MR_Live_Lval location;
	MR_stack_layout_label *layout;
	MR_stack_layout_entry *entry_layout;
	MR_Lval_Type type;
	int number, determinism;


#ifndef MR_STACK_TRACE
	fprintf(stderr, "Stack dump not available in this grade.\n");
#else
	fprintf(stderr, "Stack dump follows (determinisitic stack only):\n");

	do {
		label = lookup_label_addr(success_pointer);
		if (label == NULL) {
			fatal_error("internal label not found");
		}

		layout = (MR_stack_layout_label *) label->e_layout;
		entry_layout = layout->MR_sll_entry;
		
		label = lookup_label_addr(
			entry_layout->MR_sle_code_addr);
		if (label == NULL) {
			fatal_error("entry label not found");
		}

		location = entry_layout->MR_sle_succip_locn;
		type = MR_LIVE_LVAL_TYPE(location);
		number = MR_LIVE_LVAL_NUMBER(location);

		determinism = entry_layout->MR_sle_detism;

		if (MR_DETISM_DET_CODE_MODEL(determinism)) {
			fprintf(stderr, "\t%s\n", label->e_name);
			if (type == MR_LVAL_TYPE_STACKVAR) {
				success_pointer = (Code *) field(0, 
					det_stack_pointer, -number);
			} else {
				fatal_error("can only handle stackvars");
			}
			det_stack_pointer = det_stack_pointer - 
				entry_layout->MR_sle_stack_slots;
		}
	} while (MR_DETISM_DET_CODE_MODEL(determinism));
#endif /* MR_STACK_TRACE */
}


New File: runtime/mercury_stack_trace.h
===================================================================
/*
** Copyright (C) 1998 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/

#ifndef MERCURY_STACK_TRACE_H
#define MERCURY_STACK_TRACE_H

/*
** mercury_stack_trace.h -
**	Definitions for use by the stack tracing.
*/

/*---------------------------------------------------------------------------*/

/*
** MR_dump_stack:
** 	Given the succip and det stack pointer, generate a stack dump
** 	showing then name of each procedure on the stack.
** 	XXX 
** 	Currently only deterministic stack frames are handled, if a
** 	nondeterministic stack frame is found while tracing down the
** 	stack, the stack dump ends.
*/

extern void MR_dump_stack(Code *success_pointer, Word *det_stack_pointer);

#endif /* MERCURY_STACK_TRACE_H */


-- 
       Tyson Dowd           # There isn't any reason why Linux can't be
                            # implemented as an enterprise computing solution.
     trd at cs.mu.oz.au        # Find out what you've been missing while you've
http://www.cs.mu.oz.au/~trd # been rebooting Windows NT. -- InfoWorld, 1998.



More information about the developers mailing list