[m-dev.] MLDS variable declarations

Julien Fischer juliensf at cs.mu.OZ.AU
Sat Sep 10 00:12:54 AEST 2005

On Fri, 9 Sep 2005, Peter Hawkins wrote:

> Hi...
> I'm hoping someone can help me understand this comment in ml_code_gen.m:
> In this predicate:
>     % Generate an MLDS definition for the specified procedure.
>     %
> :- pred ml_gen_proc_defn(module_info::in, pred_id::in, proc_id::in,
>     mlds__entity_defn::out, mlds__defns::out) is det.
> at line 1187 there is this comment:
>         % This would generate all the local variables at the top of
>         % the function:
>         %   ml_gen_all_local_var_decls(Goal,
>         %       VarSet, VarTypes, HeadVars, MLDS_LocalVars,
>         %       Info1, Info2)
>         % But instead we now generate them locally for each goal.
>         % We just declare the `succeeded' var here, plus locals
>         % for any output arguments that are returned by value
>         % (e.g. if --nondet-copy-out is enabled, or for det function
>         % return values).

Presumably, it's because the initial version of the MLDS uses nested

> Why are the local vars now generated for each goal rather than at the
> top of the procedure body? Would anyone care if I changed it back?
There is probably no need to remove it, if the current arrangement of
locals needs changing then the right approach is to use a separate
MLDS-MLDS pass that does that.

> Motivation:
> I'm thinking about how you could implement tracing in a high-level
> grade, and it occurs to me the biggest problem is producing a meaningful
> label layout structure. It's (relatively) easy to work out which MLDS
> variable contains a HLDS variable's value at a given point in time, but
> there's no easy way of working out the location of an arbitrary (say) C
> variable, because the C compiler might have placed it in a register or
> at a random part of the stack.
> I can think of two ways to handle this:
> 1) Parse the .debug_info section of the generated object code, which
> contains information mapping C variables to their locations at given
> points in the program's execution. Not portable, and almost certainly
> not fun. This would involve writing per-operating system and
> per-architecture debug information parsing code, but much of this could
> possibly be stolen from gdb. And it's useless in languages other than C.

Can I be the first to say yuck?

> 2) Move all of the variable declarations of a function into a specially
> defined struct/class/..., like so a procedure body is changed from:
> void MR_CALL test__a_2_p_0(
>   MR_Integer test__A1_3,
>   MR_Integer * test__A2_4)
> {
>   {
>     MR_bool test__succeeded;
>     MR_Integer test__V_5_5;
>     MR_Integer test__V_6_6 = (MR_Integer) 3;
>     MR_Integer test__V_9_9;
> ...
> into something like:
> struct test__a_2_p_0_localvars {
> /* Arguments */
>   MR_Integer test__A1_3;
>   MR_Integer * test__A2_4;
> /* Local variables */
>     MR_Integer test__V_5_5;
>     MR_Integer test__V_6_6;
>     MR_Integer test__V_9_9;
> };
> void MR_CALL test__a_2_p_0(
>   MR_Integer test__A1_3,
>   MR_Integer * test__A2_4)
> {
>   {
>     MR_bool test__succeeded;
>     struct test__a_2_p_0_localvars lv;
>     lv.test__A1_3 = test__A1_3;
>     lv.test__A2_4 = test__A2_4;
>     lv.test__V_6_6 = (MR_Integer) 3;
> ...
The accurate garabage collector already has a similar transformation to this
(see ml_elim_nested.m), it hoists out locals that need to be traced by
the collector and puts them in structures that are then linked together
to form a shadow stack.  I imagine that a similar approach could be used
to implement tracing in the MLDS backend.

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