for review: stack dumps.

Tyson Dowd trd at cs.mu.OZ.AU
Tue Mar 3 19:16:44 AEDT 1998


Hi,

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 = -DMR_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:
	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: 8

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

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

runtime/Mmakefile:
runtime/mercury_imp.h:
runtime/mercury_init.h:
	Add new files. 

runtime/mercury_accurate_gc.h:
	Remove stack_layout stuff, leave this file for accurate
	GC specific definitions.
	Define MR_INSERT_LABELS if doing NATIVE_GC.

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_INSERT_LABELS 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.


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 06:12:41
@@ -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);
+	dump_stack(MR_succip, MR_sp);
 	exit(1);
 #ifndef USE_GCC_NONLOCAL_GOTOS
 	return 0;	/* suppress some dumb warnings */
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/01 03:38:32
@@ -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.4
diff -u -r1.4 mercury_accurate_gc.h
--- mercury_accurate_gc.h	1998/01/06 07:05:56	1.4
+++ mercury_accurate_gc.h	1998/02/19 05:26:36
@@ -15,219 +15,10 @@
 
 /*---------------------------------------------------------------------------*/
 
-/*
-** 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
+ #define MR_INSERT_LABELS
 #endif
-
-/*
-** Definitions for MR_Stack_Specifier
-*/
-
-typedef enum { MR_STACK_DET, MR_STACK_NONDET } MR_Stack_Specifier;
-
-/*
-** 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 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 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 number of stack slots */		\
-	(Integer) -1, 	/* Unknown code model */			\
-        (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 */
-
-
-/*
-** Macros to support stack layouts.
-** XXX ought to use a MR_Entry_Stack_Layout and MR_Cont_Stack_Layout
-** struct to make it easier to access the fields.
-*/
-
-#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), 1))
-
-#define MR_ENTRY_STACK_LAYOUT_GET_CODE_MODEL(s)			\
-		(field(0, (s), 2))
-
-#define MR_ENTRY_STACK_LAYOUT_GET_SUCCIP_LOC(s)			\
-		(field(0, (s), 3))
 
 /*---------------------------------------------------------------------------*/
 #endif /* not MERCURY_ACCURATE_GC_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/02/19 05:21:38
@@ -11,6 +11,7 @@
 
 #include "mercury_types.h"	/* for `Code *' */
 #include "mercury_debug.h"	/* for debuggoto() */
+#include "mercury_stack_trace.h"
 #include "mercury_accurate_gc.h"
 
 #define paste(a,b) a##b
@@ -34,21 +35,21 @@
 ** accurate garbage collection.
 */
 
-#if defined(SPEED) && !defined(DEBUG_GOTOS) && !defined(NATIVE_GC)
+#if defined(SPEED) && !defined(DEBUG_GOTOS) && !defined(MR_INSERT_LABELS)
 #define	make_label(n, a, l)	/* nothing */
 #else
 #define	make_label(n, a, l)	make_entry(n, a, l)
 #endif
 
 #if defined(SPEED) && !defined(DEBUG_GOTOS) && !defined(PROFILE_CALLS) \
-			&& !defined(NATIVE_GC)
+		&& !defined(MR_INSERT_LABELS)
 #define make_local(n, a, l)	/* nothing */
 #else 
 #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)
+		&& !defined(PROFILE_CALLS) && !defined(MR_INSERT_LABELS)
 #define make_entry(n, a, l)	/* nothing */
 #else
 #define make_entry(n, a, l)	insert_entry(n, a, MR_STACK_LAYOUT(l))
@@ -517,7 +518,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_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_init.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_init.h,v
retrieving revision 1.2
diff -u -r1.2 mercury_init.h
--- mercury_init.h	1997/11/23 07:21:25	1.2
+++ mercury_init.h	1998/02/19 03:51:32
@@ -88,6 +88,9 @@
   #include "gc.h"
 #endif
 
+#include "mercury_stack_trace.h"
+#include "mercury_accurate_gc.h"
+
 /*
 ** mercury_main() takes the address of the following predicates/functions,
 ** which are defined elsewhere.
Index: util/mkinit.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/util/mkinit.c,v
retrieving revision 1.25
diff -u -r1.25 mkinit.c
--- mkinit.c	1997/12/03 07:28:15	1.25
+++ mkinit.c	1998/02/19 03:49:27
@@ -174,7 +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(DEBUG_LABELS) || defined(MR_INSERT_LABELS) \\\n"
 	"	|| !defined(SPEED)\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. 
*/

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

/*
** 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.
*/

/*
** Definitions for MR_Stack_Specifier
*/

typedef enum { MR_STACK_DET, MR_STACK_NONDET } MR_Stack_Specifier;

/*
** 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 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 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)

/*
** MR_Determinsim encodes the determinism using properties of the
** determinsim. The bit encoding is done in stack_layout.m, changes
** here will need to be reflected there.
*/
typedef Word MR_Determinsim;

	/* 
	** A det code model is any code model where there is at most one
	** solution. The 1st bit is set is there is more than one
	** solution.
	*/
#define MR_DETERMINSIM_IS_DET_CODE_MODEL(detism)	\
		(!((detism) & 1))

/*
** 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 number of stack slots */		\
	(Integer) -1, 	/* Unknown code model */			\
        (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 */


/*
** Macros to support stack layouts.
** XXX ought to use a MR_Entry_Stack_Layout and MR_Cont_Stack_Layout
** struct to make it easier to access the fields.
*/

#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_DETERMINISM(s)		\
		(field(0, (s), 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 dump_stack(Code *success_pointer, Word *stack_pointer)
{
	Label *label;
	Word layout, entry_layout, location;
	MR_Lval_Type type;
	int number, determinisim;


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

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

		layout = (Word) label->e_layout;
		entry_layout = MR_CONT_STACK_LAYOUT_GET_ENTRY_LAYOUT(layout);
		
		label = lookup_label_addr(
			MR_ENTRY_STACK_LAYOUT_GET_LABEL_ADDRESS(entry_layout));
		if (label == NULL) {
			fatal_error("entry label not found");
		}

		location = MR_ENTRY_STACK_LAYOUT_GET_SUCCIP_LOC(entry_layout);
		type = MR_LIVE_LVAL_TYPE(location);
		number = MR_LIVE_LVAL_NUMBER(location);

		determinisim = MR_ENTRY_STACK_LAYOUT_GET_DETERMINISM(
			entry_layout);

		if (MR_DETERMINSIM_IS_DET_CODE_MODEL(determinisim)) {
			fprintf(stderr, "\t%s\n", label->e_name);
			if (type == MR_LVAL_TYPE_STACKVAR) {
				success_pointer = (Code *) field(0, 
					stack_pointer, -number);
			} else {
				fatal_error("can only handle stackvars");
			}
			stack_pointer = stack_pointer - 
				MR_ENTRY_STACK_LAYOUT_GET_NUM_SLOTS(
					entry_layout);
		}
	} while (MR_DETERMINSIM_IS_DET_CODE_MODEL(determinisim));
#endif /* MR_USE_STACK_LAYOUTS */
}


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.
*/

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

#ifdef MR_STACK_TRACE
 #define MR_USE_STACK_LAYOUTS
 #define MR_INSERT_LABELS
#endif

extern void dump_stack(Code *success_pointer, Word *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