[m-dev.] for review: line numbers in the debugger (part 1)

Tyson Dowd trd at cs.mu.OZ.AU
Thu Nov 11 18:18:53 AEDT 1999


On 10-Nov-1999, Zoltan Somogyi <zs at cs.mu.OZ.AU> wrote:
> 
> Estimated hours taken: 
> 
> Support breakpoints on line numbers that correspond to calls. Internally,
> these are implemented as breakpoints on the proc layouts of the called
> procedure.
> 
> This required extending the debugging RTTI, so that associated with each
> module there is now a new data structure listing the source file names that
> contribute labels with layout structures to the code of the module. For each
> such source file, this table gives a list of all such labels arising from
> that file. The table entry for a label gives the line number within the file,
> and the pointer to the label layout structure.
> 
> compiler/llds.m:
> 	Add a context field to the call instruction.
> 
> compiler/continuation_info.m:
> 	Instead of the old division of continuation info about labels into
> 	trace ports and everything else, divide them into trace ports, resume
> 	points and return sites. Record contexts with trace ports, and record
> 	contexts and called procedure information with return sites.
> 
> compiler/code_info.m:
> 	Conform to the changes in continuation_info.m.
> 
> compiler/options.m:
> 	Add a new option that allows us to disable the generation of line
> 	number information for size benchmarking (it has no other use).
> 
> compiler/stack_layout.m:
> 	Generate the new components of the RTTI, unless the option says not to.
> 
> compiler/code_gen.m:
> compiler/pragma_c_gen.m:
> compiler/trace.m:
> 	Include contexts in the events we generate.
> 
> compiler/call_gen.m:
> 	Include contexts in the call LLDS instructions.
> 
> compiler/handle_options.m:
> 	Delete the code that tests or sets the deleted options.
> 
> compiler/mercury_compile.m:
> 	Delete the code that tests the deleted options.
> 
> compiler/basic_block.m:
> compiler/dupelim.m:
> compiler/frameopt.m:
> compiler/livemap.m:
> compiler/llds_common.m:
> compiler/llds_out.m:
> compiler/middle_rec.m:
> compiler/opt_debug.m:
> compiler/opt_util.m:
> compiler/value_number.m:
> compiler/vn_*.m:
> 	Trivial changes to conform to the changes to llds.m.
> 
> compiler/jumpopt.m:
> 	Do not optimize away jumps to labels with layout structures.
> 	The jumps we are particularly concerned about now are the jumps
> 	that return from procedure calls. Previously, it was okay to redirect
> 	returns from several calls so that all go to the same label, since
> 	the live variable information associated with the labels could be
> 	merged. However, we now also associate line numbers with calls, and
> 	these cannot be usefully merged.
> 
> compiler/optimize.m:
> 	Pass the information required by jumpopt to it.
> 
> doc/user_guide.texi:
> 	Document that you can now break at line numbers.
> 
> 	Document the new "context" command, and the -d or --detailed option
> 	of the stack command and the commands that set ancestor levels.
> 
> runtime/mercury_stack_layout.h:
> 	Extend the module layout structure definition with the new tables.
> 
> 	Remove the conditional facility for including label numbers in label
> 	layout structures. It hasn't been used in a long time, and neither
> 	Tyson or me expect to use it to debug either gc or the debugger itself,
> 	so it has no uses left; the line numbers have superseded it.
> 
> runtime/mercury_stack_trace.[ch]:
> 	Extend the code to print stack traces to also optionally print
> 	contexts.
> 
> 	Add some utility predicates currently used by the debugger that could
> 	also be use for debugging gc or for more detailed stack traces.
> 
> trace/mercury_trace_internal.c:
> 	Implement the "break <context>" command, the "context" command, and
> 	the -d or --detailed option of the stack command and the commands
> 	that set ancestor levels.
> 
> 	Conditionally define a conditionally used variable.
> 
> trace/mercury_trace_external.c:
> 	Minor changes to keep up with the changes to stack traces.
> 
> 	Delete an unused variable.
> 
> trace/mercury_trace_spy.[ch]:
> 	Check for breakpoints on contexts.
> 
> trace/mercury_trace_tables.[ch]:
> 	Add functions to search the RTTI data structures for labels
> 	corresponding to a given context.
> 
> trace/mercury_trace_vars.[ch]:
> 	Remember the context of the current environment.
> 
> tests/debugger/queen.{inp,exp}:
> 	Test the new capabilities of the debugger.
> 
> tests/debugger/*.{inp,exp}:
> 	Update the expected output of the debugger to account for contexts.
> 	In some cases, modify the input script to put contexts where they don't
> 	overflow lines.
> 
> Zoltan.
> 
> cvs diff: Diffing .
> cvs diff: Diffing bindist
> cvs diff: Diffing boehm_gc
> cvs diff: Diffing boehm_gc/Mac_files
> cvs diff: Diffing boehm_gc/cord
> cvs diff: Diffing boehm_gc/cord/private
> cvs diff: Diffing boehm_gc/include
> cvs diff: Diffing boehm_gc/include/private
> cvs diff: Diffing browser
> cvs diff: Diffing bytecode
> cvs diff: Diffing compiler



> Index: runtime/mercury_stack_trace.c
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
> retrieving revision 1.32
> diff -u -b -r1.32 mercury_stack_trace.c
> --- mercury_stack_trace.c	1999/06/08 03:47:41	1.32
> +++ mercury_stack_trace.c	1999/11/10 03:41:43


> @@ -364,26 +398,59 @@
>  		** so we don't reserve space for the repeat counts.
>  		*/
>  	}
> +
> +	MR_print_call_trace_info(fp, entry_layout, base_sp, base_curfr);
> +	MR_print_proc_id(fp, entry_layout);
> +	if (strdiff(filename, "") && linenumber > 0) {
> +		fprintf(fp, " (%s:%d%s)", filename, linenumber,
> +			context_mismatch? " and others" : "");
> +	}

I know we probably don't have anything about this in our style
guildelines, but I prefer a space before my operators.

> +void
> +MR_print_proc_id_trace_and_context(FILE *fp, MR_Context_Position pos,
> +	const MR_Stack_Layout_Entry *entry, Word *base_sp, Word *base_curfr,
> +	const char *path, const char *filename, int lineno, bool print_parent, 
> +	const char *parent_filename, int parent_lineno, int indent)
> +{
> +
> +	switch (pos) {
> +		case MR_CONTEXT_NOWHERE:
> +			fprintf(fp, " ");
> +			MR_print_call_trace_info(fp, entry,
> +				base_sp, base_curfr);
> +			MR_print_proc_id(fp, entry);
> +			if (strlen(path) > 0) {
> +				fprintf(fp, " %s", path);
> +			}
>  		fprintf(fp, "\n");
> +			break;
> +
> +		case MR_CONTEXT_BEFORE:
> +			MR_maybe_print_context(fp, filename, lineno);
> +			MR_maybe_print_parent_context(fp, print_parent,
> +				FALSE, parent_filename, parent_lineno);
> +			fprintf(fp, " ");
> +			MR_print_call_trace_info(fp, entry,
> +				base_sp, base_curfr);
> +			MR_print_proc_id(fp, entry);
> +			if (strlen(path) > 0) {
> +				fprintf(fp, " %s", path);
>  	}
> +			fprintf(fp, "\n");
> +			break;
> +
> +		case MR_CONTEXT_AFTER:
> +			fprintf(fp, " ");
> +			MR_print_call_trace_info(fp, entry,
> +				base_sp, base_curfr);
> +			MR_print_proc_id(fp, entry);
> +			if (strlen(path) > 0) {
> +				fprintf(fp, " %s", path);
> +			}
> +			MR_maybe_print_context(fp, filename, lineno);
> +			MR_maybe_print_parent_context(fp, print_parent,
> +				FALSE, parent_filename, parent_lineno);
> +			fprintf(fp, "\n");
> +			break;
> +
> +		case MR_CONTEXT_PREVLINE:
> +			MR_maybe_print_context(fp, filename, lineno);
> +			MR_maybe_print_parent_context(fp, print_parent,
> +				TRUE, parent_filename, parent_lineno);
> +			fprintf(fp, "\n%*s ", indent, "");
> +			MR_print_call_trace_info(fp, entry,
> +				base_sp, base_curfr);
> +			MR_print_proc_id(fp, entry);
> +			if (strlen(path) > 0) {
> +				fprintf(fp, " %s", path);
> +			}
> +			fprintf(fp, "\n");
> +			break;
> +
> +		case MR_CONTEXT_NEXTLINE:
> +			fprintf(fp, " ");
> +			MR_print_call_trace_info(fp, entry,
> +				base_sp, base_curfr);
> +			MR_print_proc_id(fp, entry);
> +			if (strlen(path) > 0) {
> +				fprintf(fp, " %s", path);
> +			}
> +			fprintf(fp, "\n%*s", indent, "");
> +			MR_maybe_print_context(fp, filename, lineno);
> +			MR_maybe_print_parent_context(fp, print_parent,
> +				TRUE, parent_filename, parent_lineno);
> +			fprintf(fp, "\n");
> +			break;
> +
> +		default:
> +			fatal_error("invalid MR_Context_Position");
> +	}
> +}

Hmmmm.... I'm not completely happy with this.  The creeping featuritis
of the debugger makes a formatting function 60 lines of rather similar
looking code.

Can I suggest something like:


	if (pos == MR_CONTEXT_PREVLINE || pos == MR_CONTEXT_BEFORE) {
		MR_maybe_print_context(fp, filename, lineno);
		MR_maybe_print_parent_context(fp, print_parent,
			(pos == MR_CONTEXT_PREVLINE), parent_filename,
			parent_lineno);
	}

	if (pos == MR_CONTEXT_PREVLINE) {
		fprintf(fp, "\n%*s", indent, "");
	} else {
		fprintf(fp, " ");
	}

	MR_print_call_trace_info(fp, entry,
		base_sp, base_curfr);
	MR_print_proc_id(fp, entry);
	if (strlen(path) > 0) {
		fprintf(fp, " %s", path);
	}

	if (pos == MR_CONTEXT_NEXTLINE) {
		fprintf(fp, "\n%*s", indent, "");
	}
	if (pos == MR_CONTEXT_NEXTLINE || pos == MR_CONTEXT_AFTER) {
		MR_maybe_print_context(fp, filename, lineno);
		MR_maybe_print_parent_context(fp, print_parent,
			(pos == MR_CONTEXT_NEXTLINE), parent_filename,
			parent_lineno);
	}
	fprintf(fp, "\n");

It's half the size, admittedly less efficient (but who cares, it's doing
I/O) and I find it easy to see what parameter controls what formatting
option.  I also think it's easier to maintain. 

I guess a drawback is if you are planning on adding even more options to
the enum.

But why can't I define a printf style formatting string for where
I want to print everything?  (actually, that isn't as tongue in cheek as
it might seem). 

I wouldn't worry about this comment for this commit, but if
the debugger keeps getting features like this it's going to become
a nightmare.

> Index: runtime/mercury_stack_trace.h
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.h,v
> retrieving revision 1.18
> diff -u -b -r1.18 mercury_stack_trace.h
> --- mercury_stack_trace.h	1999/06/08 03:47:41	1.18
> +++ mercury_stack_trace.h	1999/11/10 03:16:58

> @@ -143,29 +150,69 @@
>  ** the names that are usually used to denote determinisms.
>  */
>  
> -extern const char * MR_detism_names[];
> +extern	const char *MR_detism_names[];
>  
>  /*
> +** MR_find_context attempts to look up the file name and line number
> +** corresponding to a label identified by its layout structure. If successful,
> +** it fills in *fileptr and *lineptr accordingly, and returns TRUE; otherwise,
> +** it returns FALSE.
> +*/
> +
> +extern	bool	MR_find_context(const MR_Stack_Layout_Label *label,
> +			const char **fileptr, int *lineptr);
> +
> +/*
> +** If the procedure has trace layout information and the relevant one of
> +** base_sp and base_curfr is not NULL, MR_print_call_trace_info prints
> +** the call event number, call sequence number and call depth of the call
> +** stored in the stack frame of the procedure.
> +*/
> +
> +extern	void	MR_print_call_trace_info(FILE *fp,
> +			const MR_Stack_Layout_Entry *entry,
> +			Word *base_sp, Word *base_curfr);
> +
> +/*
>  ** MR_print_proc_id prints an identification of the given procedure,
>  ** consisting of "pred" or "func", module name, pred or func name, arity,
> -** mode number and determinism, followed by an optional extra string,
> -** and a newline.
> -**
> -** If the procedure has trace layout information and the relevant one of
> -** base_sp and base_curfr is not NULL, it also prints the call event number,
> -** call sequence number and call depth of the call.
> +** mode number and determinism. It does not output a newline, so that
> +** the caller can pu something else after the procedure id on the same line.

s/pu/put/

> +	} else if (streq(words[0], "context")) {
> +		if (word_count == 2) {
> +			if (streq(words[1], "none")) {
> +				MR_context_position = MR_CONTEXT_NOWHERE;
> +				if (MR_trace_internal_interacting) {
> +					fprintf(MR_mdb_out, "Contexts "
> +						"will not be printed.\n");
> +				}
> +			} else if (streq(words[1], "before")) {
> +				MR_context_position = MR_CONTEXT_BEFORE;
> +				if (MR_trace_internal_interacting) {
> +					fprintf(MR_mdb_out, "Contexts "
> +						"will be printed before, "
> +						"on the same line.\n");
> +				}
> +			} else if (streq(words[1], "after")) {
> +				MR_context_position = MR_CONTEXT_AFTER;
> +				if (MR_trace_internal_interacting) {
> +					fprintf(MR_mdb_out, "Contexts "
> +						"will be printed after, "
> +						"on the same line.\n");
> +				}
> +			} else if (streq(words[1], "prevline")) {
> +				MR_context_position = MR_CONTEXT_PREVLINE;
> +				if (MR_trace_internal_interacting) {
> +					fprintf(MR_mdb_out, "Contexts "
> +						"will be printed "
> +						"on the previous line.\n");
> +				}
> +			} else if (streq(words[1], "nextline")) {
> +				MR_context_position = MR_CONTEXT_NEXTLINE;
> +				if (MR_trace_internal_interacting) {
> +					fprintf(MR_mdb_out, "Contexts "
> +						"will be printed "
> +						"on the next line.\n");
> +				}
> +			} else {
> +				MR_trace_usage("parameter", "context");
> +			}
> +		} else if (word_count == 1) {
> +			fprintf(MR_mdb_out, "Contexts are ");
> +			switch (MR_context_position) {
> +			case MR_CONTEXT_NOWHERE:
> +				fprintf(MR_mdb_out, "not printed.");
> +				break;
> +
> +			case MR_CONTEXT_BEFORE:
> +				fprintf(MR_mdb_out,
> +					"printed before, on the same line.");
> +				break;
> +
> +			case MR_CONTEXT_AFTER:
> +				fprintf(MR_mdb_out,
> +					"printed after, on the same line.");
> +				break;
> +
> +			case MR_CONTEXT_PREVLINE:
> +				fprintf(MR_mdb_out,
> +					"printed on the previous line.");
> +				break;
> +
> +			case MR_CONTEXT_NEXTLINE:
> +				fprintf(MR_mdb_out,
> +					"printed on the next line.");
> +				break;
> +
> +			default:
> +				fatal_error("invalid MR_context_position");
> +			}
> +		} else {
> +			MR_trace_usage("parameter", "context");
> +		}

A short table of constant strings and MR_context_position values 
could do all this in about 5 lines.  Doesn't really matter though.


Other than those comments the diff looks fine.


-- 
       Tyson Dowd           # 
                            #  Surreal humour isn't eveyone's cup of fur.
     trd at cs.mu.oz.au        # 
http://www.cs.mu.oz.au/~trd #
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list