[m-dev.] For review: implementation of collect for Opium-M

Fergus Henderson fjh at cs.mu.OZ.AU
Fri Oct 29 01:49:37 AEST 1999


On 28-Oct-1999, Erwan Jahier <Erwan.Jahier at irisa.fr> wrote:
> | I'll start off with the easy review comments.
> | (I have one or two more complicated ones brewing... ;-)
> | 
> | On 27-Oct-1999, Erwan Jahier <Erwan.Jahier at irisa.fr> wrote:
> | collect_lib.m:
> | > +%		3) the predicate filter/3 which updates it at each execution 
> | > +%		   event. filter/3 should have the following declarations:
> | > +%			:- pred filter(event, collected_type, collected_type).
> | > +%			:- mode filter(in, di, uo) is det.
> | 
> | It would be better if this predicate also returned a bool
> | to say whether or not to keep on going.
> | The collection process would stop when this predicate returns `no'.
> 
> I will think about that.

OK.

(If you add the bool, then this feature could be used for
emulating breakpoints with user-defined conditions.)

> | > +		%
> | > +		% Look up the address of the first mode (mode number 0)
> | > +		% of the predicates initialize/1 and filter/14  in the 
> | > +		% module collect.
> | > +		%
> | > +		dl__sym(Handle, "Collect_initialize", MaybeInitialize),
> | > +		dl__sym(Handle, "Collect_filter", MaybeFilter),
> | > +		dl__sym(Handle, "Collect_send_collect_result", MaybeSendResult),
> | 
> | The comment here is misleading.  You're actually looking up the
> | address of the corresponding C functions.
> 
> ok.
> I have replaced that comment by:
> 		%
> 		% Look up the address of the initialize/1 and filter/14 
> 		% corresponding C functions in the module collect.
> 		%

I suggest
 		%
 		% Look up the address of the C functions corresponding to the 
		% initialize/1 and filter/14 predicates in the collect module.
 		%

> | In fact a general `link' command to link in an arbitrary shared object
> | might be useful.  You might want to think about whether the
> | parts of this command's functionality which are related specifically
> | to collect could be put in the `collect' command rather than
> | in the `link_collect' command.
> 
> Is it ok if I deal with that in a separate change later on?

Yes.

> | >  Code *
> | >  MR_trace_event_external(MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info)
> | >  {
> | > -	static bool	searching = FALSE;
> | > +	static MR_external_debugger_mode_type 
> | > +			external_debugger_mode = reading_request;
> | >  	static Word	search_data;
> | > +	static Word	collecting_variable;
> | > +	static Word	(*initialize_ptr)(Word *) = NULL;
> | > +	static Word    	(*filter_ptr)(Integer, Integer, Integer, MR_Trace_Port,
> | > +				MR_PredFunc, String, String, String, Integer,
> | > +				Integer, Integer, String, Word, Word *) = NULL;
> | > +	static Word	(*send_collect_result_ptr)(Word, Word);
> | > +	static Word    	*handle = NULL;
> | > +	static bool    	collect_linked = FALSE;
> | 
> | The function pointer types look wrong.  For example, why do `initialize_ptr'
> | and `send_collect_result_ptr' point to functions that return values
> | of type `Word', rather than `void'?
> 
> It was to avoid the following warning:
> 
> 	mercury_trace_external.c: In function `MR_trace_event_external':
> 	mercury_trace_external.c:484: warning: passing arg 1 of pointer to function makes pointer 
> 	from integer without a cast
> 	mercury_trace_external.c:484: warning: passing arg 2 of pointer to function makes pointer 
> 	from integer without a cast

That warning is about the type of the first and second arguments,
not about the return type.

When you call the initialize_ptr function (in mercury_trace_external.c),
you call it like so:

|	 (*initialize_ptr)(&collecting_variable));

Here you ignore the function's return value.
So probably the return value should have type `void'.

> And I though it was the type of pointers on Mercury objets.
> So, what should it be?

Have a look at the header file collect.h that the Mercury compiler
generates; it will have declarations for the "Collect_filter",
"Collect_initialize", and "Collect_send_collect_result" functions.
The declarations for the function pointers should exactly match
those automatically-generated function declarations.

Another point, while I think of it: for consistency with the
naming conventions used elsewhere in the Mercury implementation,
the names used for those functions in the `pragma export' declarations
should probably be something like `ML_COLLECT_filter', `ML_COLLECT_initialize',
etc., rather than `Collect_filter', `Collect_initialize', etc.

> | Also, the use of MR_Trace_Port
> | and MR_PredFunc looks dangerous; the type here should exactly match
> | the type with which the function is defined, and I'll bet that it
> | will be defined using Integer or Word rather than MR_Trace_Port.
> 
> Well, collect.m is generated with the help of the file collect.in (which is 
> not typed by users) which contains:
> 
> 	% The stuff defined below is similar to types goal_path and trace_port
> 	% defined in modules compiler/hlds_goal.m and compiler/trace.m.
> 	% This enumeration must be EXACTLY the same as the MR_trace_port enum in
> 	% runtime/mercury_trace_base.h, and in the same order, since the code
> 	% assumes the representation is the same.
>
> 	:- type trace_port_type
> 		--->	call
> 		;	exit
> 		;	redo
> 		;	fail
> 		...
> 
> In runtime/mercury_trace_base.h, there is the comment:
> 
> 	/*
> 	** This enum should EXACTLY match the definition of the `trace_port_type'
> 	** type in browser/debugger_interface, and the port names list in the
> 	** C source file of this module.
> 	*/
> 
> 	typedef	enum {
> 		MR_PORT_CALL,
> 		MR_PORT_EXIT,
> 		...}

Actually I think that code only assumes that the representation of the
enum VALUES are the same.  I don't think it assumes that the representation
of the TYPES are the same.  (If it does, then that assumption is a bug.)
In particular, although the same numerical values will be used, the C
compiler may well choose to use a `short' or `unsigned short' or
even `unsigned char' type to represent the enum.  There is no guarantee
that the type used will have the same representation and calling convention
as `Word' or `Integer'.

In particular, for the `pred_or_func'/`MR_PredFunc' type, the enum has
only two values.  The numerical values of these two will always be the
same (pred = MR_PREDICATE = 0, func = MR_FUNCTION = 1).  But a clever C
compiler might recognize that the MR_PredFunc type has only two values
and thus might try passing values of type MR_PredFunc in a single-bit
condition register rather than in a full-word register.  The calling
convention might depend on the type.

It might be best to change the definitions of the types so that
they are typedefs for `Word' rather than being enums.  The enumeration
constants would of course stay.  So the declarations would look like
this

	enum { MR_PORT_CALL, MR_PORT_EXIT, ... };
	typedef Word MR_Trace_Port;

or perhaps like this

	typedef enum { MR_PORT_CALL, MR_PORT_EXIT, ... } MR_Trace_Port_Enum;
	typedef Word MR_Trace_Port;

> Maybe I should replace it by:
> 
> 	/*
> 	** This enum should EXACTLY match the definition of the `trace_port_type'
> 	** type in browser/debugger_interface and extras/opium_m/source/collect.in, 
> 	** and the port names list in the C source file of this module.
> 	*/
> 
> ??

That would be a good idea too.  But for reasons explained above
it is not sufficient.

> | The indentation of the `case' should be the same as that of the `switch'.
> 
> It was to be consistent with the indentation of the switch that accurs after 
> in the code

I checked the "C coding guidelines" on our WWW page,
and I found that according to that, you are right,
and I am wrong.  So please leave it as is.

I also had a look for switches through our source code, and found that
most of it does follow the style recommended in our C coding guidelines.
There were a few places which did not:

	runtime/mercury_memory_handlers.c
	runtime/mercury_wrapper.c
	library/std_util.m
	runtime/mercury_deep_copy_body.h

Probably we should change those places...

> | > +		case collecting:
> | > +			if (seqno == 1 && port == MR_PORT_EXIT) {
> | > +				/* The end of the execution is reached */
> | 
> | That condition is wrong; it does not necessarily indicate the last
> | event.  For one thing, you should use MR_port_is_final(port) rather
> | than `port == MR_PORT_EXIT', because the final port could be an
> | exception or a fail port.  Even that is not enough, though:  if `main'
> | is compiled without tracing, but some other modules that it calls are
> | compiled with tracing, then you can reach the exit port for event #1
> | long before all the events have finished.
> 
> Yes, you are right.
> 
> I'm now sending the result via MR_trace_final_external() (which is even more
> efficient since I win a switch ;-); this implied to declare
> external_debugger_mode, MR_collecting_variable, send_collect_result_ptr, handle
> as global.
> 
> Do you think it ok?

Yes.

> | Content-Description: collect.op
> | ...
> | > % There are several things to do in order to be able to execute a 
> | > % collect/1 command:
> | > % 1) create a file that will that contain the definition of collected_type, 
> | > %	initialize/1 and filter/3,
> | > % 2) generate `collect.m' from this file (generate_collect/1),
> | > % 3) compile collect.m (compile_collect/0),
> | > % 4) dynamically link it with the current execution (dyn_link_collect/0).
> | > % 5) run the command (run_command/1).
> | 
> | It would be nice if there was a single command that did steps 2-5
> | all at once.
> 
> Why? 
> 
> Note that collect/2 (which does 1-5 all at once)

That is sufficient; I didn't notice the existence of that command.

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