[m-dev.] for review: stack dumps in the debugger and a bug fix

Fergus Henderson fjh at cs.mu.OZ.AU
Mon Jun 8 13:35:50 AEST 1998


On 07-Jun-1998, Zoltan Somogyi <zs at cs.mu.OZ.AU> wrote:
> 
> compiler/liveness.m:
> 	Turn off type_info liveness for builtins without typeinfos.
> 	Since these builtins establish no gc points and shouldn't be
> 	execution traced, this is OK.

OK so far...

> compiler/mercury_compile.m:
> 	Turn off execution tracing for the modules builtin.m and
> 	private_builtin.m.

I think the diff turns off stack tracing too, not just execution tracing.

>       The latter contains the interface predicates
> 	for the builtins without typeinfos. Since the interface predicates
> 	also lack the typeinfos, the compiler would get an internal abort
> 	if we left execution tracing on.
> 
> 	In any case, these two modules contain stuff that users should
> 	consider language builtins, which means they should not be traced.

What about predicates such as

	table_loopcheck_error,
	builtin_compare_pred,
	builtin_compare_non_canonical,

which call error/1 -- surely the user will want a stack dump in those
cases.

Also if the user has a type with a user-defined equality, then unify/2
could call user code, and again the user may want a stack trace in that
case.

> The next batch of changes have to do with allowing execution tracing
> to work in the usual (non-debug) grades, on programs in which only
> some modules are compiled with tracing.

Did you mean stack tracing rather than execution tracing?

Execution tracing seems to work in the usual grades already.

> compiler/llds_out.m:
> compiler/mercury_compile.m:
> runtime/mercury_conf_param.h:
...
> 	The new version of llds_out takes a parameter that says whether
> 	this module is compiled with execution tracing or not, and if it is,
> 	it generates a #define MR_LABELS_FOR_EXEC_TRACE *before* the #include
> 	of mercury_imp.h. This causes mercury_conf_param.h, included from
> 	mercury_imp.h, to define the macros MR_USE_STACK_LAYOUTS and
> 	and MR_INSERT_LABELS, which in turn cause stack layouts for this
> 	module to be handled as if the grade was debug.

Why does execution tracing need stack layouts and MR_INSERT_LABELS?

> Index: compiler/llds_out.m
...
>  	% Given a 'c_file' structure, open the appropriate .c file
> -	% and output the code into that file.
> +	% and output the code into that file. The bool says whether
> +	% this Mercury module was compiled with any flavor of execution
> +	% tracing; the third argument gives the set of labels that have
> +	% layout structures.
>  
> -:- pred output_c_file(c_file, set_bbbtree(label), io__state, io__state).
> -:- mode output_c_file(in, in, di, uo) is det.
> +:- pred output_c_file(c_file, bool, set_bbbtree(label), io__state, io__state).
> +:- mode output_c_file(in, in, in, di, uo) is det.

I think it would make more sense for output_c_file to get this bool
directly from the globals structure in the io__state rather than
passing it as a parameter.  After all, in general there may 
be lots of other options that it would like to check.

For example, it would be a good idea for it to emit macros
in the generated code for all the options that affect binary
compatibility of the generated C code, and for mercury_conf_param.h
to use these to check that the options you're using to compile
the C file are consistent with those used to generate the C file.

> @@ -194,7 +198,13 @@
>  		io__write_string("\n"),
>  		io__write_string("ENDINIT\n"),
>  		io__write_string("*/\n\n"),
> -		io__write_string("#include ""mercury_imp.h""\n"),
> +		( { ExecTrace = yes } ->
> +			io__write_string("#define MR_LABELS_FOR_EXEC_TRACE\n"),
> +			io__write_string("#include ""mercury_imp.h""\n"),
> +			io__write_string("#include ""mercury_trace.h""\n")
> +		;
> +			io__write_string("#include ""mercury_imp.h""\n")
> +		),
...
> +		),
> +		( { ExecTrace = yes } ->
> +			io__write_string("#define MR_LABELS_FOR_EXEC_TRACE\n"),
> +			io__write_string("#include ""mercury_imp.h""\n"),
> +			io__write_string("#include ""mercury_trace.h""\n")
> +		;
> +			io__write_string("#include ""mercury_imp.h""\n")

It would be a good idea to split this duplicate code out into a
seperate procedure.

>  /*
> +** MR_NEED_INITIALIZATION_AT_START -- the module specific initialization code
> +**				      must be run any Mercury code is run.

I think you omitted a word or two here.

> --- mercury_goto.h	1998/05/16 07:28:15	1.9
> +++ mercury_goto.h	1998/06/03 11:05:59
> @@ -18,12 +18,12 @@
>  #define entry(label) paste(_entry_,label)
>  #define skip(label) paste(skip_,label)
>  
> -#ifdef MR_USE_STACK_LAYOUTS
> +#if defined(MR_USE_STACK_LAYOUTS)

I prefer the more concise form.

> Index: runtime/mercury_stack_trace.h
...
> +/*
> +** MR_dump_stack_from_layout:
> +**	This function does the same job and makes the same assumptions
> +**	as MR_dump_stack, but instead of the succip, it takes the entry
> +**	layout of the current procedure as input. It also takes a paramater
> +**	that tells it where to put the stack dump. If the entire stack
> +**	was printed successfully, the return value is NULL; otherwise,
> +**	it is a string indicating why the dump was cut short.
> +*/

s/paramater/parameter/

> +static MR_next
> +MR_trace_debug_cmd(MR_trace_cmd_info *cmd, const MR_Stack_Layout_Label *layout,
> +	MR_trace_port port, int seqno, int depth, const char *path)
> +{
> +	char	line[MR_MAX_LINE_LEN];
> +	char	count_buf[MR_MAX_LINE_LEN];
> +	char	*raw_words[MR_MAX_LINE_LEN/2+1];

I suggest whitespace around operators (/ and +).

> +	raw_word_count = MR_trace_break_into_words(line, raw_words+1);

Ditto.

> +	if (raw_word_count > 0 && isdigit(*raw_words[1])) {

For portability, the call to isdigit() needs to cast the
argument to `unsigned char':

	if (raw_word_count > 0 && isdigit((unsigned char) *raw_words[1])) {

Otherwise, it can result in undefined behaviour on machines with
signed characters if the user types in a character with the top bit set.

> +		while (isdigit(*s)) {

Ditto.

> +static bool
> +MR_trace_is_number(char *word, int *value)
>  {
> +	if (isdigit(*word)) {
> +		*value = *word - '0';
> +		word++;
> +		while (isdigit(*word)) {
> +			*value = (*value * 10) + *word - '0';
> +			word++;
> +		}

Ditto.

> +MR_trace_break_into_words(char line[], char *words[])
...
> +		while (line[char_pos] != '\0' && isspace(line[char_pos])) {
...
> +		while (line[char_pos] != '\0' && !isspace(line[char_pos])) {

Ditto.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3        |     -- the last words of T. S. Garp.



More information about the developers mailing list