for review: changes to stack tracing

Zoltan Somogyi zs at cs.mu.OZ.AU
Wed Jun 10 19:21:18 AEST 1998


Tyson, please review this.

runtime/mercury_stack_trace.c:
	Separate out the part of the stack walk function that walks one step.
	This will be needed to implement printing of variables in upper
	levels.

	Print a level number with each stack frame in the list of ancestors.
	Where a line in the output represents several stack frames from the
	same procedure, the level number printed is the level number of the
	top frame.

	Change the output format a bit to accommodate the level number
	and to print the mode number the same way as the debugger does it.

An example of the new format:

	0       queens:qdelete/3-0 (nondet)
	1    2* queens:qperm/2-0 (nondet)
	3       queens:queen/2-0 (nondet)
	4       queens:main/2-0 (cc_multi)

Zoltan.

Index: mercury_stack_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.7
diff -u -u -r1.7 mercury_stack_trace.c
--- mercury_stack_trace.c	1998/06/08 08:27:05	1.7
+++ mercury_stack_trace.c	1998/06/10 11:11:50
@@ -14,6 +14,12 @@
 #include "mercury_stack_trace.h"
 #include <stdio.h>
 
+typedef	enum {
+	STEP_ERROR_BEFORE,
+	STEP_ERROR_AFTER,
+	STEP_OK
+} MR_stack_walk_step_result;
+
 static const char * detism_names[] = {
 	"failure",	/* 0 */
 	"",		/* 1 */
@@ -32,11 +38,15 @@
 	"cc_multi"	/* 14 */
 };
 
+static	MR_stack_walk_step_result MR_stack_walk_step(MR_Stack_Layout_Entry *,
+			MR_Stack_Layout_Entry **, Word **, Word **,
+			const char **);
+
 static	void	MR_dump_stack_record_init(void);
 static	void	MR_dump_stack_record_frame(FILE *fp, MR_Stack_Layout_Entry *);
 static	void	MR_dump_stack_record_flush(FILE *fp);
 static	void	MR_dump_stack_record_print(FILE *fp, MR_Stack_Layout_Entry *,
-			int);
+			int, int);
 
 void
 MR_dump_stack(Code *success_pointer, Word *det_stack_pointer,
@@ -72,85 +82,118 @@
 MR_dump_stack_from_layout(FILE *fp, MR_Stack_Layout_Entry *entry_layout,
 		Word *det_stack_pointer, Word *current_frame)
 {
+	MR_stack_walk_step_result	result;
+	MR_Stack_Layout_Entry		*next_entry_layout;
+	const char			*problem;
+	Word				*stack_trace_sp;
+	Word				*stack_trace_curfr;
+
+	MR_dump_stack_record_init();
+
+	stack_trace_sp = det_stack_pointer;
+	stack_trace_curfr = current_frame;
+
+	do {
+		result = MR_stack_walk_step(entry_layout, &next_entry_layout,
+				&stack_trace_sp, &stack_trace_curfr, &problem);
+		if (result == STEP_ERROR_BEFORE) {
+			MR_dump_stack_record_flush(fp);
+			return problem;
+		} else if (result == STEP_ERROR_AFTER) {
+			MR_dump_stack_record_frame(fp, entry_layout);
+			MR_dump_stack_record_flush(fp);
+			return problem;
+		} else {
+			MR_dump_stack_record_frame(fp, entry_layout);
+		}
+
+		if (next_entry_layout == NULL) {
+			break;
+		}
+
+		entry_layout = next_entry_layout;
+	} while (TRUE); 
+
+	MR_dump_stack_record_flush(fp);
+	return NULL;
+}
+
+static	MR_stack_walk_step_result MR_stack_walk_step(
+	MR_Stack_Layout_Entry *entry_layout,
+	MR_Stack_Layout_Entry **next_entry_layout,
+	Word **stack_trace_sp_ptr, Word **stack_trace_curfr_ptr,
+	const char **problem_ptr)
+{
 	Label			*label;
 	MR_Live_Lval		location;
 	MR_Stack_Layout_Label	*layout;
 	MR_Lval_Type		type;
-	Code			*success_pointer;
 	int			number, determinism;
-
-	MR_dump_stack_record_init();
-
-	do {
-		location = entry_layout->MR_sle_succip_locn;
-		type = MR_LIVE_LVAL_TYPE(location);
-		number = MR_LIVE_LVAL_NUMBER(location);
+	Code			*success;
 
-		determinism = entry_layout->MR_sle_detism;
+	determinism = entry_layout->MR_sle_detism;
 
+	if (determinism < 0) {
 		/*
-		** A negative determinism means handwritten code has
-		** been reached.  Usually this means we have reached
-		** "global_success", so we should stop dumping the stack.
-		**
-		** Otherwise it means we have reached some handwritten
-		** code that has no further information about the stack
-		** frame.  In this case, we also stop dumping the stack.
+		** This means we have reached some handwritten code that has
+		** no further information about the stack frame.
 		*/
 
-		if (determinism < 0) {
-			MR_dump_stack_record_flush(fp);
-			return "reached procedure with no stack trace info";
-		}
+		*problem_ptr = "reached procedure with no stack trace info";
+		return STEP_ERROR_BEFORE;
+	}
 
-		MR_dump_stack_record_frame(fp, entry_layout);
-		if (MR_DETISM_DET_STACK(determinism)) {
-			if (type == MR_LVAL_TYPE_STACKVAR) {
-				success_pointer = (Code *) field(0,
-					det_stack_pointer, -number);
-			} else {
-				MR_dump_stack_record_flush(fp);
-				return "can only handle stackvars";
-			}
-			det_stack_pointer = det_stack_pointer -
-				entry_layout->MR_sle_stack_slots;
-		} else {
-			success_pointer = bt_succip(current_frame);
-			current_frame = bt_succfr(current_frame);
-		}
+	if (MR_DETISM_DET_STACK(determinism)) {
+		location = entry_layout->MR_sle_succip_locn;
+		type = MR_LIVE_LVAL_TYPE(location);
+		number = MR_LIVE_LVAL_NUMBER(location);
 
-		if (success_pointer == MR_stack_trace_bottom) {
-			MR_dump_stack_record_flush(fp);
-			return NULL;
+		if (type != MR_LVAL_TYPE_STACKVAR) {
+			*problem_ptr = "can only handle stackvars";
+			return STEP_ERROR_AFTER;
 		}
 
-		label = lookup_label_addr(success_pointer);
-		if (label == NULL) {
-			MR_dump_stack_record_flush(fp);
-			return "reached label with no stack trace info";
-		}
+		success = (Code *) field(0, *stack_trace_sp_ptr, -number);
+		*stack_trace_sp_ptr = *stack_trace_sp_ptr -
+			entry_layout->MR_sle_stack_slots;
+	} else {
+		success = bt_succip(*stack_trace_curfr_ptr);
+		*stack_trace_curfr_ptr = bt_succfr(*stack_trace_curfr_ptr);
+	}
 
-		layout = (MR_Stack_Layout_Label *) label->e_layout;
-		if (layout == NULL) {
-			MR_dump_stack_record_flush(fp);
-			return "reached label with no stack layout info";
-		}
+	if (success == MR_stack_trace_bottom) {
+		*next_entry_layout = NULL;
+		return STEP_OK;
+	}
 
-		entry_layout = layout->MR_sll_entry;
-	} while (TRUE);
+	label = lookup_label_addr(success);
+	if (label == NULL) {
+		*problem_ptr = "reached label with no stack trace info";
+		return STEP_ERROR_AFTER;
+	}
+
+	layout = (MR_Stack_Layout_Label *) label->e_layout;
+	if (layout == NULL) {
+		*problem_ptr = "reached label with no stack layout info";
+		return STEP_ERROR_AFTER;
+	}
 
-	/*NOTREACHED*/
-	return "internal error in MR_dump_stack_from_layout";
+	*next_entry_layout = layout->MR_sll_entry;
+	return STEP_OK;
 }
 
-static MR_Stack_Layout_Entry	*prev_entry_layout;
-static int			prev_entry_layout_count;
+static	MR_Stack_Layout_Entry	*prev_entry_layout;
+static	int			prev_entry_layout_count;
+static	int			prev_entry_start_level;
+static	int			current_level;
 
 static void
 MR_dump_stack_record_init(void)
 {
 	prev_entry_layout = NULL;
 	prev_entry_layout_count = 0;
+	prev_entry_start_level = 0;
+	current_level = 0;
 }
 
 static void
@@ -162,7 +205,10 @@
 		MR_dump_stack_record_flush(fp);
 		prev_entry_layout = entry_layout;
 		prev_entry_layout_count = 1;
+		prev_entry_start_level = current_level;
 	}
+
+	current_level++;
 }
 
 static void
@@ -170,24 +216,26 @@
 {
 	if (prev_entry_layout != NULL) {
 		MR_dump_stack_record_print(fp, prev_entry_layout,
-			prev_entry_layout_count);
+			prev_entry_layout_count, prev_entry_start_level);
 	}
 }
 
 static void
 MR_dump_stack_record_print(FILE *fp, MR_Stack_Layout_Entry *entry_layout,
-	int count)
+	int count, int start_level)
 {
-	fprintf(fp, "\t%s:%s/%ld (mode %ld, %s)",
+	fprintf(fp, "%9d ", start_level);
+
+	if (count > 1) {
+		fprintf(fp, " %3d*", count);
+	} else {
+		fprintf(fp, "%5s", "");
+	}
+
+	fprintf(fp, " %s:%s/%ld-%ld (%s)\n",
 		entry_layout->MR_sle_def_module,
 		entry_layout->MR_sle_name,
 		(long) entry_layout->MR_sle_arity,
 		(long) entry_layout->MR_sle_mode,
 		detism_names[entry_layout->MR_sle_detism]);
-
-	if (count > 1) {
-		fprintf(fp, " * %d\n", count);
-	} else {
-		putc('\n', fp);
-	}
 }



More information about the developers mailing list