[m-rev.] for review: stack dumps in normal grades

Peter Wang novalazy at gmail.com
Tue Mar 25 17:24:45 AEDT 2008


For review by Zoltan.

With --force-stack-dump the mercury_compile executable increases by 30%
(15638064 bytes to 20376208 bytes).


Branches: main

Allow stack traces in low-level, non-debugging, non-deep-profiling grades.
Mainly we just need to generate the necessary layout information.  However, as
that information can be quite big we make some effort to (1) not store layout
information which isn't required for just stack tracing, (2) share some
information instead of duplicating it.

compiler/options.m:
compiler/handle_options.m:
	Add a new option `--force-stack-dump' (default: off) which implies the
	internal option `--stack-trace'.

compiler/continuation_info.m:
	Make procedures have basic and procedure id layouts if
	`--force-stack-dump' is set.

compiler/layout.m:
compiler/layout_out.m:
compiler/llds_out.m:
compiler/opt_debug.m:
compiler/stack_layout.m:
	Generate `MR_LabelLayoutProcLayoutOnly' structures if
	`--force-stack-dump' is set and no other information about the label
	is needed.  These structures only contain a pointer to the relevant
	proc layout.  Since these structures would be the same for all labels
	in a procedure, we only need one per procedure.

library/exception.m:
runtime/mercury_conf_param.h:
	Remove the MR_STACK_TRACE macro as stack tracing is now possible for
	all low-level grades.

runtime/mercury_stack_layout.h:
	Add a new variant of the MR_LabelLayout structure which contains just
	a pointer to the proc layout.  Move the variable count field in all
	label layout structures to the start, so its value can be used to
	distinguish between the three variants.

	Add `MR_DEF_LLPLO' macro to define a `MR_LabelLayoutProcLayoutOnly'.

	Unrelated: fix missing arguments in MR_DEF_LLNVI_* macros. 

runtime/mercury_goto.h:
	Add MR_init_label_slplo* macros which are like MR_init_label_sl* but
	initialise labels whose layout structures are of the
	MR_LabelLayoutProcLayoutOnly variety.

	Delete duplicated definitions of MR_init_label_sl* macros.

runtime/mercury_stack_trace.c:
	Try to print stack dumps in all low-level grades.

runtime/mercury_grade.h:
	Bump execution tracing and deep profiling version numbers due to
	change in label layout structures.

util/mkinit.c:
	Always define MR_MAY_NEED_INITIALIZATION in _init.c files for low-level
	grades as stack traces require label tables to be initialised.

doc/user_guide.texi:
	Document the new option.

Index: compiler/continuation_info.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/continuation_info.m,v
retrieving revision 1.95
diff -u -r1.95 continuation_info.m
--- compiler/continuation_info.m	18 Mar 2008 02:09:30 -0000	1.95
+++ compiler/continuation_info.m	25 Mar 2008 01:29:22 -0000
@@ -570,8 +570,12 @@
 basic_stack_layout_for_proc(PredInfo, Globals, BasicLayout,
         ForceProcIdLayout) :-
     (
-        globals.lookup_bool_option(Globals, stack_trace_higher_order, yes),
-        some_arg_is_higher_order(PredInfo)
+        (
+            globals.lookup_bool_option(Globals, force_stack_dump, yes)
+        ;
+            globals.lookup_bool_option(Globals, stack_trace_higher_order, yes),
+            some_arg_is_higher_order(PredInfo)
+        )
     ->
         BasicLayout = yes,
         ForceProcIdLayout = yes
Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.317
diff -u -r1.317 handle_options.m
--- compiler/handle_options.m	23 Jan 2008 13:12:15 -0000	1.317
+++ compiler/handle_options.m	25 Mar 2008 01:07:42 -0000
@@ -1127,6 +1127,10 @@
         option_implies(exec_trace, stack_trace, bool(yes), !Globals),
         option_implies(profile_deep, stack_trace, bool(yes), !Globals),
 
+        % --force-stack-dump makes stack dumps available in low-level C
+        % grades.
+        option_implies(force_stack_dump, stack_trace, bool(yes), !Globals),
+
         % Deep profiling disables the optimization for pretesting whether
         % x == y in runtime/mercury_unify_compare_body.h, so compensate by
         % doing the same test in the unify and compare predicates generated by
Index: compiler/layout.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/layout.m,v
retrieving revision 1.37
diff -u -r1.37 layout.m
--- compiler/layout.m	12 Sep 2007 06:21:06 -0000	1.37
+++ compiler/layout.m	25 Mar 2008 00:45:10 -0000
@@ -75,6 +75,12 @@
                 maybe_user_info         :: maybe(user_event_data),
                 maybe_var_info          :: maybe(label_var_info)
             )
+    ;       label_layout_proc_layout_only_data(
+                                        % defines MR_LabelLayoutProcLayoutOnly
+                llpo_proc_label         :: proc_label,
+                llpo_label_num          :: int,
+                llpo_proc_layout_name   :: layout_name
+            )
     ;       proc_layout_data(           % defines MR_ProcLayout
                 proc_layout_label       :: rtti_proc_label,
                 proc_layout_trav        :: proc_layout_stack_traversal,
@@ -219,6 +225,7 @@
 
 :- type layout_name
     --->    label_layout(proc_label, int, label_vars)
+    ;       label_layout_proc_layout_only(proc_label)
     ;       user_event_layout(proc_label, int)
     ;       user_event_attr_var_nums(proc_label, int)
     ;       proc_layout(rtti_proc_label, proc_layout_kind)
Index: compiler/layout_out.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/layout_out.m,v
retrieving revision 1.95
diff -u -r1.95 layout_out.m
--- compiler/layout_out.m	27 Feb 2008 07:23:08 -0000	1.95
+++ compiler/layout_out.m	25 Mar 2008 00:44:42 -0000
@@ -136,6 +136,11 @@
             MaybePort, MaybeIsHidden, LabelNumber, MaybeGoalPath,
             MaybeUserData, MaybeVarInfo, !DeclSet, !IO)
     ;
+        Data = label_layout_proc_layout_only_data(ProcLabel, _LabelNum,
+            ProcLayoutAddr),
+        output_label_layout_proc_layout_only_data_defn(ProcLabel,
+            ProcLayoutAddr, !DeclSet, !IO)
+    ;
         Data = proc_layout_data(ProcLabel, Traversal, MaybeRest),
         output_proc_layout_data_defn(ProcLabel, Traversal, MaybeRest,
             !DeclSet, !IO)
@@ -197,6 +202,9 @@
         ),
         LayoutName = label_layout(ProcLabel, LabelNum, LabelVars)
     ;
+        Data = label_layout_proc_layout_only_data(ProcLabel, _, _),
+        LayoutName = label_layout_proc_layout_only(ProcLabel)
+    ;
         Data = proc_layout_data(RttiProcLabel, _, MaybeRest),
         ProcLabel = make_proc_label_from_rtti(RttiProcLabel),
         Kind = maybe_proc_layout_and_more_kind(MaybeRest, ProcLabel),
@@ -250,6 +258,13 @@
         io.write_string(
             label_to_c_string(internal_label(LabelNum, ProcLabel), yes), !IO)
     ;
+        Data = label_layout_proc_layout_only(ProcLabel),
+        io.write_string(mercury_data_prefix, !IO),
+        io.write_string("_label_layout__", !IO),
+        io.write_string(
+            proc_label_to_label_layout_proc_layout_only_c_string(ProcLabel,
+                yes), !IO)
+    ;
         Data = user_event_layout(ProcLabel, LabelNum),
         io.write_string(mercury_data_prefix, !IO),
         io.write_string("_user_event_layout__", !IO),
@@ -453,6 +468,10 @@
         io.write_string(" ", !IO),
         output_layout_name(Name, !IO)
     ;
+        Name = label_layout_proc_layout_only(_ProcLabel),
+        io.write_string("static const MR_LabelLayoutProcLayoutOnly ", !IO),
+        output_layout_name(Name, !IO)
+    ;
         Name = user_event_layout(_ProcLabel, _LabelNum),
         io.write_string("static const struct MR_UserEvent_Struct ", !IO),
         output_layout_name(Name, !IO)
@@ -617,6 +636,7 @@
     ).
 
 layout_name_would_include_code_addr(label_layout(_, _, _)) = no.
+layout_name_would_include_code_addr(label_layout_proc_layout_only(_)) = no.
 layout_name_would_include_code_addr(user_event_layout(_, _)) = no.
 layout_name_would_include_code_addr(user_event_attr_var_nums(_, _)) = no.
 layout_name_would_include_code_addr(proc_layout(_, _)) = no.
@@ -822,6 +842,19 @@
     io.write_string(");\n", !IO),
     decl_set_insert(decl_data_addr(layout_addr(LayoutName)), !DeclSet).
 
+:- pred output_label_layout_proc_layout_only_data_defn(proc_label::in,
+    layout_name::in, decl_set::in, decl_set::out, io::di, io::uo) is det.
+
+output_label_layout_proc_layout_only_data_defn(ProcLabel, ProcLayoutAddr,
+        !DeclSet, !IO) :-
+    output_layout_decl(ProcLayoutAddr, !DeclSet, !IO),
+    io.write_string("\n", !IO),
+    io.write_string("MR_DEF_LLPLO(", !IO),
+    output_proc_label_no_prefix(ProcLabel, !IO),
+    io.write_string(");\n", !IO),
+    LayoutName = label_layout_proc_layout_only(ProcLabel),
+    decl_set_insert(decl_data_addr(layout_addr(LayoutName)), !DeclSet).
+
 :- pred output_maybe_var_num(maybe(int)::in, io::di, io::uo) is det.
 
 output_maybe_var_num(no, !IO) :-
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.325
diff -u -r1.325 llds_out.m
--- compiler/llds_out.m	11 Feb 2008 21:25:58 -0000	1.325
+++ compiler/llds_out.m	25 Mar 2008 00:59:09 -0000
@@ -124,6 +124,13 @@
     %
 :- func label_to_c_string(label, bool) = string.
 
+    % Convert a proc label to the name of the C symbol for the
+    % MR_LabelLayoutProcLayoutOnly structure of the proc. The boolean controls
+    % whether a prefix ("mercury__") is added to the string.
+    %
+:- func proc_label_to_label_layout_proc_layout_only_c_string(proc_label, bool)
+    = string.
+
     % The following are exported to rtti_out. It may be worthwhile
     % to put these in a new module (maybe llds_out_util).
 
@@ -314,7 +321,12 @@
     list.foldl2(output_vector_common_data_defn, VectorCommonDatas,
         !DeclSet, !IO),
     list.foldl2(output_rtti_data_defn, RttiDatas, !DeclSet, !IO),
-    list.foldl2(output_layout_data_defn, LayoutDatas, !DeclSet, !IO),
+    list.foldl2(filter_label_layout_proc_layout_only_datas, LayoutDatas,
+        [], NonProcLayoutOnlyDatas, [], CanonProcLayoutOnlyDatas),
+    list.foldl2(output_layout_data_defn, NonProcLayoutOnlyDatas,
+        !DeclSet, !IO),
+    list.foldl2(output_layout_data_defn, CanonProcLayoutOnlyDatas,
+        !DeclSet, !IO),
 
     list.foldl2(output_comp_gen_c_module(StackLayoutLabels), Modules,
         !DeclSet, !IO),
@@ -326,6 +338,29 @@
         UserFinalPredCNames, !DeclSet, !IO),
     io.set_output_stream(OutputStream, _, !IO).
 
+:- pred filter_label_layout_proc_layout_only_datas(layout_data::in,
+    list(layout_data)::in, list(layout_data)::out,
+    list(layout_data)::in, list(layout_data)::out) is det.
+
+filter_label_layout_proc_layout_only_datas(LayoutData,
+        !NonProcLayoutOnlyDatas, !CanonProcLayoutOnlyDatas) :-
+    % The MR_LabelLayoutProcOnly structures for each internal label of a
+    % procedure would all contain the same content, therefore we only define a
+    % single structure per procedure.
+    (
+        LayoutData = label_layout_proc_layout_only_data(ProcLabel, _,
+            LayoutName)
+    ->
+        Canon = label_layout_proc_layout_only_data(ProcLabel, 0, LayoutName),
+        ( list.member(Canon, !.CanonProcLayoutOnlyDatas) ->
+            true
+        ;
+            list.cons(Canon, !CanonProcLayoutOnlyDatas)
+        )
+    ;
+        list.cons(LayoutData, !NonProcLayoutOnlyDatas)
+    ).
+
 :- pred module_gather_env_var_names(list(comp_gen_c_module)::in,
     set(string)::in, set(string)::out) is det.
 
@@ -1561,26 +1596,35 @@
 
 output_c_label_inits(StackLayoutLabels, Labels, !IO) :-
     group_c_labels(StackLayoutLabels, Labels, multi_map.init, NoLayoutMap,
-        multi_map.init, LayoutMap, [], RevOtherLabels),
+        multi_map.init, LayoutMap, map.init, ProcLayoutOnlyMap,
+        [], RevOtherLabels),
     list.reverse(RevOtherLabels, OtherLabels),
     list.foldl(output_c_label_init(StackLayoutLabels), OtherLabels, !IO),
     multi_map.to_assoc_list(NoLayoutMap, NoLayoutList),
     multi_map.to_assoc_list(LayoutMap, LayoutList),
+    multi_map.to_assoc_list(ProcLayoutOnlyMap, ProcLayoutOnlyList),
     list.foldl(output_c_label_init_group(""), NoLayoutList, !IO),
-    list.foldl(output_c_label_init_group("_sl"), LayoutList, !IO).
+    list.foldl(output_c_label_init_group("_sl"), LayoutList, !IO),
+    list.foldl(output_c_label_init_group("_slplo"), ProcLayoutOnlyList, !IO).
 
 :- pred group_c_labels(map(label, data_addr)::in, list(label)::in,
     multi_map(proc_label, int)::in, multi_map(proc_label, int)::out,
     multi_map(proc_label, int)::in, multi_map(proc_label, int)::out,
+    multi_map(proc_label, int)::in, multi_map(proc_label, int)::out,
     list(label)::in, list(label)::out) is det.
 
-group_c_labels(_StackLayoutLabels, [], !NoLayoutMap, !LayoutMap, !RevOthers).
+group_c_labels(_StackLayoutLabels, [], !NoLayoutMap, !LayoutMap,
+        !ProcLayoutOnlyMap, !RevOthers).
 group_c_labels(StackLayoutLabels, [Label | Labels], !NoLayoutMap, !LayoutMap,
-        !RevOthers) :-
+        !ProcLayoutOnlyMap, !RevOthers) :-
     (
         Label = internal_label(LabelNum, ProcLabel),
-        ( map.search(StackLayoutLabels, Label, _DataAddr) ->
-            svmulti_map.set(ProcLabel, LabelNum, !LayoutMap)
+        ( map.search(StackLayoutLabels, Label, DataAddr) ->
+            ( DataAddr = layout_addr(label_layout_proc_layout_only(_)) ->
+                svmulti_map.set(ProcLabel, LabelNum, !ProcLayoutOnlyMap)
+            ;
+                svmulti_map.set(ProcLabel, LabelNum, !LayoutMap)
+            )
         ;
             svmulti_map.set(ProcLabel, LabelNum, !NoLayoutMap)
         )
@@ -1589,7 +1633,7 @@
         !:RevOthers = [Label | !.RevOthers]
     ),
     group_c_labels(StackLayoutLabels, Labels, !NoLayoutMap, !LayoutMap,
-        !RevOthers).
+        !ProcLayoutOnlyMap, !RevOthers).
 
 :- pred output_c_label_init_group(string::in,
     pair(proc_label, list(int))::in, io::di, io::uo) is det.
@@ -4720,6 +4764,11 @@
     string.append("_i", NumStr, NumSuffix),
     string.append(ProcLabelStr, NumSuffix, LabelStr).
 
+proc_label_to_label_layout_proc_layout_only_c_string(ProcLabel, AddPrefix) =   
+        Str :-
+    ProcLabelStr = proc_label_to_c_string(ProcLabel, AddPrefix),
+    string.append(ProcLabelStr, "_ipo", Str).
+
 :- pred output_reg(reg_type::in, int::in, io::di, io::uo) is det.
 
 output_reg(reg_r, N, !IO) :-
Index: compiler/opt_debug.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/opt_debug.m,v
retrieving revision 1.206
diff -u -r1.206 opt_debug.m
--- compiler/opt_debug.m	11 Feb 2008 21:26:05 -0000	1.206
+++ compiler/opt_debug.m	25 Mar 2008 00:46:51 -0000
@@ -494,6 +494,9 @@
         LabelVarsStr = "label_has_no_var_info"
     ),
     Str = "label_layout(" ++ LabelStr ++ ", " ++ LabelVarsStr ++ ")".
+dump_layout_name(label_layout_proc_layout_only(ProcLabel)) = Str :-
+    LabelStr = dump_label(no, internal_label(0, ProcLabel)),
+    Str = "label_layout_proc_layout_only(" ++ LabelStr ++ ")".
 dump_layout_name(user_event_layout(ProcLabel, LabelNum)) = Str :-
     LabelStr = dump_label(no, internal_label(LabelNum, ProcLabel)),
     Str = "user_event_layout(" ++ LabelStr ++ ")".
Index: compiler/options.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.613
diff -u -r1.613 options.m
--- compiler/options.m	29 Jan 2008 02:38:26 -0000	1.613
+++ compiler/options.m	19 Mar 2008 05:43:27 -0000
@@ -213,6 +213,7 @@
             % library to be linked in with an executable compiled in a .debug
             % grade.
 
+    ;       force_stack_dump
     ;       stack_trace_higher_order
     ;       force_disable_ssdebug
     ;       generate_bytecode
@@ -376,15 +377,15 @@
             % Stack layout information required to do a stack trace.
 
     ;       basic_stack_layout
-            % Stack layout information required to do accurate GC.
 
     ;       agc_stack_layout
-            % Stack layout information required to do procedure identification.
+            % Stack layout information required to do accurate GC.
 
     ;       procid_stack_layout
-            % Stack layout information required to do execution tracing.
+            % Stack layout information required to do procedure identification.
 
     ;       trace_stack_layout
+            % Stack layout information required to do execution tracing.
 
     ;       body_typeinfo_liveness
             % Use an alternate calculation of liveness where the typeinfo
@@ -1053,6 +1054,7 @@
     suppress_trace                      -   string(""),
     force_disable_tracing               -   bool(no),
     delay_death                         -   bool(yes),
+    force_stack_dump                    -   bool(no),
     stack_trace_higher_order            -   bool(no),
     force_disable_ssdebug               -   bool(no),
     generate_bytecode                   -   bool(no),
@@ -1849,6 +1851,7 @@
 long_option("suppress-trace",       suppress_trace).
 long_option("force-disable-tracing",    force_disable_tracing).
 long_option("delay-death",          delay_death).
+long_option("force-stack-dump",     force_stack_dump).
 long_option("stack-trace-higher-order", stack_trace_higher_order).
 long_option("force-disable-ssdebug",    force_disable_ssdebug).
 long_option("generate-bytecode",    generate_bytecode).
@@ -3439,6 +3442,9 @@
         "\tbeyond the point of their last use, in order to make them",
         "\taccessible from as many debugger events as possible.",
         "\tHowever, it will not do this if this option is given.",
+        "--force-stack-dump",
+        "\tEnable stack dump support even if it is not supported",
+        "\tin general.",
         "--stack-trace-higher-order",
         "\tEnable stack traces through predicates and functions with",
         "\thigher-order arguments, even if stack tracing is not",
Index: compiler/stack_layout.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/stack_layout.m,v
retrieving revision 1.140
diff -u -r1.140 stack_layout.m
--- compiler/stack_layout.m	11 Feb 2008 21:26:08 -0000	1.140
+++ compiler/stack_layout.m	25 Mar 2008 01:12:23 -0000
@@ -120,6 +120,7 @@
     globals.lookup_bool_option(Globals, agc_stack_layout, AgcLayout),
     globals.lookup_bool_option(Globals, trace_stack_layout, TraceLayout),
     globals.lookup_bool_option(Globals, procid_stack_layout, ProcIdLayout),
+    globals.lookup_bool_option(Globals, force_stack_dump, ForceStackDump),
     globals.lookup_bool_option(Globals, profile_deep, DeepProfiling),
     globals.get_trace_level(Globals, TraceLevel),
     globals.get_trace_suppress(Globals, TraceSuppress),
@@ -132,7 +133,7 @@
     global_data_get_static_cell_info(!.GlobalData, StaticCellInfo0),
     counter.init(1, LabelCounter0),
     LayoutInfo0 = stack_layout_info(ModuleInfo,
-        AgcLayout, TraceLayout, ProcIdLayout, StaticCodeAddr,
+        AgcLayout, TraceLayout, ProcIdLayout, ForceStackDump, StaticCodeAddr,
         LabelCounter0, [], [], [], LayoutLabels0, [],
         StringTable0, LabelTables0, StaticCellInfo0, no),
     lookup_string_in_table("", _, LayoutInfo0, LayoutInfo1),
@@ -345,6 +346,16 @@
             construct_internal_layout(ProcLabel, ProcLayoutName, VarNumMap),
             Internals, InternalLabelInfos, !Info)
     ;
+        % For --force-stack-dump we don't need detailed information, just
+        % enough to get to the proc layout from a label address.
+        !.Info ^ force_stack_dump = yes,
+        valid_proc_layout(ProcLayoutInfo)
+    ->
+        list.map_foldl(
+            construct_internal_layout_proc_layout_only(ProcLabel,
+                ProcLayoutName),
+            Internals, InternalLabelInfos, !Info)
+    ;
         InternalLabelInfos = []
     ),
     get_label_tables(!.Info, LabelTables0),
@@ -1048,6 +1059,23 @@
 
 %---------------------------------------------------------------------------%
 
+:- pred construct_internal_layout_proc_layout_only(proc_label::in,
+    layout_name::in, pair(int, internal_layout_info)::in,
+    internal_label_info::out, stack_layout_info::in, stack_layout_info::out)
+    is det.
+
+construct_internal_layout_proc_layout_only(ProcLabel, ProcLayoutName,
+        LabelNum - Internal, LabelLayout, !Info) :-
+    LayoutData = label_layout_proc_layout_only_data(ProcLabel, LabelNum,
+        ProcLayoutName),
+    Label = internal_label(LabelNum, ProcLabel),
+    LayoutName = label_layout_proc_layout_only(ProcLabel),
+    add_internal_layout_data(LayoutData, Label, LayoutName, !Info),
+    LabelLayout = internal_label_info(ProcLabel, LabelNum,
+        label_has_no_var_info, Internal).
+
+%---------------------------------------------------------------------------%
+
 :- pred construct_livelval_rvals(set(layout_var_info)::in,
     var_num_map::in, map(tvar, set(layout_locn))::in, int::out,
     rval::out, rval::out, rval::out,
@@ -1784,6 +1812,8 @@
                 agc_stack_layout        :: bool, % generate agc info?
                 trace_stack_layout      :: bool, % generate tracing info?
                 procid_stack_layout     :: bool, % generate proc id info?
+                force_stack_dump        :: bool, % otherwise generate enough info
+                                                 % for stack dumps?
                 static_code_addresses   :: bool, % have static code addresses?
                 label_counter           :: counter,
                 table_infos             :: list(layout_data),
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.560
diff -u -r1.560 user_guide.texi
--- doc/user_guide.texi	18 Mar 2008 03:09:42 -0000	1.560
+++ doc/user_guide.texi	25 Mar 2008 01:29:23 -0000
@@ -6692,6 +6692,12 @@
 accessible from as many debugger events as possible.
 However, it will not do this if this option is given.
 
+ at item --force-stack-dump
+ at findex --force-stack-dump
+Enable stack traces even if stack tracing is not supported in general.
+This option is only supported by the low-level C back-end.
+The cost is increase object code sizes and disabling of some optimisations.
+
 @item --stack-trace-higher-order
 @findex --stack-trace-higher-order
 Enable stack traces through predicates and functions with
Index: library/exception.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/exception.m,v
retrieving revision 1.133
diff -u -r1.133 exception.m
--- library/exception.m	17 Sep 2007 09:03:02 -0000	1.133
+++ library/exception.m	19 Mar 2008 05:28:21 -0000
@@ -1709,16 +1709,12 @@
 **     an exception.  This allows to user to use the `retry' command
 **     to restart a goal which exited via an exception.
 **
-**     Note that if MR_STACK_TRACE is not defined, then we may not be
-**     able to traverse the stack all the way; in that case, we just
-**     print a warning and then continue.  It might be better to just
-**     `#ifdef' out all this code (and the code in builtin_throw which
-**     calls it) if MR_STACK_TRACE is not defined.
+**     Note that in some grades we may not be able to traverse the stack all
+**     the way; in that case, we just print a warning and then continue.
 **
 ** (2) In deep profiling grades, execute the actions appropriate for
 **     execution leaving the procedure invocation via the exception port.
-**     (Deep profiling grades always set MR_STACK_TRACE, so in such grades
-**     we *will* be able to traverse the stack all the way.)
+**     (In such grades we *will* be able to traverse the stack all the way.)
 **
 ** The arguments base_sp and base_curfr always hold MR_sp and MR_curfr.
 ** They exist only because we cannot take the addresses of MR_sp and MR_curfr.
Index: runtime/mercury_conf_param.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_conf_param.h,v
retrieving revision 1.106
diff -u -r1.106 mercury_conf_param.h
--- runtime/mercury_conf_param.h	11 Feb 2008 03:56:13 -0000	1.106
+++ runtime/mercury_conf_param.h	20 Mar 2008 04:00:34 -0000
@@ -160,11 +160,6 @@
 /*
 ** Debugging options:
 **
-** MR_STACK_TRACE
-**	Require the inclusion of the layout information needed by error/1
-**	and the debugger to print stack traces. Set from the values of
-**	MR_EXEC_TRACE and MR_DEEP_PROFILING.
-**
 ** MR_EXEC_TRACE
 **	Require that all Mercury procedures linked in should be compiled
 **	with at least interface tracing.  This effect is achieved
@@ -317,29 +312,6 @@
 **	transactions used by software transactional memory.
 */
 
-/*
-** Execution tracing and deep profiling both need stack traces, e.g.
-** simulate exits from calls between an exception being thrown and being
-** caught. Stack tracing is therefore automatically enabled in debugging and
-** deep profiling grades.
-**
-** In theory, we could allow stack traces to be enabled even in non-debug,
-** non-deep-profiling grades. However, if you try to do a stack trace, you
-** would find it doesn't work very well unless all modules are compiled
-** with stack tracing. We could define a grade for situations in which
-** MR_STACK_TRACE is defined but MR_EXEC_TRACE and MR_DEEP_PROFILING aren't,
-** but such a grade wouldn't be very useful. We therefore ensure that
-** MR_STACK_TRACE is set iff at least one of MR_EXEC_TRACE and
-** MR_DEEP_PROFILING is set.
-*/
-
-#ifdef MR_STACK_TRACE
-  #error "MR_STACK_TRACE set independently"
-#endif
-#if defined(MR_EXEC_TRACE) || defined(MR_DEEP_PROFILING)
-  #define MR_STACK_TRACE
-#endif
-
 #ifdef	MR_HIGHLEVEL_CODE
   #ifdef MR_LOWLEVEL_DEBUG
     #error "MR_HIGHLEVEL_CODE and MR_LOWLEVEL_DEBUG are not supported together"
@@ -731,6 +703,9 @@
 **			   to be run some time before the first use of the
 **			   label table).
 **
+** Stack traces can always be enabled in low-level grades which is why
+** labels always need to be inserted in those cases.
+**
 ** Note that for the MLDS back-end, the calls to MR_init_entry()
 ** that insert the function addresses in the label table are only
 ** output if the right compiler options are enabled.  So if you change
@@ -742,7 +717,7 @@
 #ifdef MR_INSERT_LABELS
   #error "MR_INSERT_LABELS should not be defined on the command line"
 #endif
-#if defined(MR_STACK_TRACE) || defined(MR_NATIVE_GC) \
+#if !defined(MR_HIGHLEVEL_CODE) || defined(MR_NATIVE_GC) \
 	|| defined(MR_DEBUG_GOTOS) || defined(MR_BYTECODE_CALLABLE) \
 	|| defined(MR_DEBUG_LABEL_NAMES)
   #define MR_INSERT_LABELS
Index: runtime/mercury_goto.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_goto.h,v
retrieving revision 1.50
diff -u -r1.50 mercury_goto.h
--- runtime/mercury_goto.h	12 Jun 2007 06:06:33 -0000	1.50
+++ runtime/mercury_goto.h	25 Mar 2008 01:20:57 -0000
@@ -953,6 +953,9 @@
 	MR_make_label_an(MR_STRINGIFY(label), &&MR_entry(label), label)
   #define MR_init_label_sl(label)	\
 	MR_make_label_sl(MR_STRINGIFY(label), &&MR_entry(label), label)
+  #define MR_init_label_slplo(label, e)   \
+	MR_make_label_sl(MR_STRINGIFY(label), &&MR_entry(label), \
+		MR_label_name(MR_add_prefix(e), po))
 
   #define MR_LOCAL(label)	(&&MR_entry(label))
   #define MR_LABEL(label)	(&&MR_entry(label))
@@ -1033,6 +1036,9 @@
 		  				label, label)
   #define MR_init_label_sl(label)	MR_make_label_sl(MR_STRINGIFY(label), \
 		  				label, label)
+  #define MR_init_label_slplo(label, e)                                       \
+	MR_make_label_sl(MR_STRINGIFY(label), label,                          \
+		MR_label_name(MR_add_prefix(e), plo))
 
   #define MR_ENTRY(label) 	((MR_Code *) (label))
   #define MR_LOCAL(label)	((MR_Code *) (label))
@@ -1316,57 +1322,57 @@
 	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln7));		\
 	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln8));
 
-#define	MR_init_label_sl1(e, ln1)					\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln1));
-
-#define	MR_init_label_sl2(e, ln1, ln2)					\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln1));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln2));
-
-#define	MR_init_label_sl3(e, ln1, ln2, ln3)				\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln1));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln2));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln3));
-
-#define	MR_init_label_sl4(e, ln1, ln2, ln3, ln4)			\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln1));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln2));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln3));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln4));
-
-#define	MR_init_label_sl5(e, ln1, ln2, ln3, ln4, ln5)			\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln1));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln2));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln3));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln4));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln5));
-
-#define	MR_init_label_sl6(e, ln1, ln2, ln3, ln4, ln5, ln6)		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln1));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln2));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln3));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln4));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln5));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln6));
+#define	MR_init_label_slplo1(e, ln1)                                    \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln1), e);
 
-#define	MR_init_label_sl7(e, ln1, ln2, ln3, ln4, ln5, ln6, ln7)		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln1));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln2));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln3));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln4));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln5));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln6));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln7));
-
-#define	MR_init_label_sl8(e, ln1, ln2, ln3, ln4, ln5, ln6, ln7, ln8)	\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln1));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln2));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln3));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln4));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln5));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln6));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln7));		\
-	MR_init_label_sl(MR_label_name(MR_add_prefix(e), ln8));
+#define	MR_init_label_slplo2(e, ln1, ln2)                               \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln1), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln2), e);
+
+#define	MR_init_label_slplo3(e, ln1, ln2, ln3)                          \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln1), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln2), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln3), e);
+
+#define	MR_init_label_slplo4(e, ln1, ln2, ln3, ln4)                     \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln1), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln2), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln3), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln4), e);
+
+#define	MR_init_label_slplo5(e, ln1, ln2, ln3, ln4, ln5)                \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln1), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln2), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln3), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln4), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln5), e);
+
+#define	MR_init_label_slplo6(e, ln1, ln2, ln3, ln4, ln5, ln6)           \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln1), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln2), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln3), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln4), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln5), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln6), e);
+
+#define	MR_init_label_slplo7(e, ln1, ln2, ln3, ln4, ln5, ln6, ln7)      \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln1), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln2), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln3), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln4), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln5), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln6), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln7), e);
+
+#define	MR_init_label_slplo8(e, ln1, ln2, ln3, ln4, ln5, ln6, ln7, ln8) \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln1), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln2), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln3), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln4), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln5), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln6), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln7), e);   \
+	MR_init_label_slplo(MR_label_name(MR_add_prefix(e), ln8), e);
 
 #define	MR_decl_extern_entry(e)						\
 	MR_declare_extern_entry(MR_add_prefix(e));
Index: runtime/mercury_grade.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_grade.h,v
retrieving revision 1.76
diff -u -r1.76 mercury_grade.h
--- runtime/mercury_grade.h	20 Mar 2008 04:02:56 -0000	1.76
+++ runtime/mercury_grade.h	25 Mar 2008 01:20:10 -0000
@@ -61,8 +61,8 @@
 */
 
 #define MR_GRADE_PART_0	v15_
-#define MR_GRADE_EXEC_TRACE_VERSION_NO	8
-#define MR_GRADE_DEEP_PROF_VERSION_NO	3
+#define MR_GRADE_EXEC_TRACE_VERSION_NO	9
+#define MR_GRADE_DEEP_PROF_VERSION_NO	4
 
 #ifdef MR_HIGHLEVEL_CODE
 
Index: runtime/mercury_stack_layout.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stack_layout.h,v
retrieving revision 1.114
diff -u -r1.114 mercury_stack_layout.h
--- runtime/mercury_stack_layout.h	18 Mar 2008 01:31:33 -0000	1.114
+++ runtime/mercury_stack_layout.h	25 Mar 2008 01:49:52 -0000
@@ -388,9 +388,9 @@
 ** The remaining fields give information about the values live at the given
 ** label, if this information is available. If it is available, the
 ** MR_has_valid_var_count macro will return true and the last three fields are
-** meaningful; if it is not available, the macro will return false and the last
-** three fields are not meaningful (i.e. you are looking at an
-** MR_LabelLayoutNoVarInfo structure).
+** meaningful; if it is not available, the macro will return false and those
+** same fields are not meaningful (i.e. you are looking at either an
+** MR_LabelLayoutNoVarInfo or MR_LabelLayoutProcLayoutOnly structure).
 **
 ** The format in which we store information about the values live at the label
 ** is somewhat complicated, due to our desire to make this information compact.
@@ -475,12 +475,12 @@
 
 struct MR_LabelLayout_Struct {
 	const MR_ProcLayout		*MR_sll_entry;
+	MR_Integer			MR_sll_var_count; /* >= 0 */
 	MR_int_least8_t			MR_sll_port;
 	MR_int_least8_t			MR_sll_hidden;
 	MR_uint_least16_t		MR_sll_label_num_in_module;
 	MR_uint_least32_t		MR_sll_goal_path;
 	const MR_UserEvent		*MR_sll_user_event;
-	MR_Integer			MR_sll_var_count; /* >= 0 */
 	const void			*MR_sll_locns_types;
 	const MR_HLDSVarNum		*MR_sll_var_nums;
 	const MR_TypeParamLocns		*MR_sll_tvars;
@@ -488,14 +488,19 @@
 
 typedef	struct MR_LabelLayoutNoVarInfo_Struct {
 	const MR_ProcLayout		*MR_sll_entry;
+	MR_Integer			MR_sll_var_count; /* = -1 */
 	MR_int_least8_t			MR_sll_port;
 	MR_int_least8_t			MR_sll_hidden;
 	MR_uint_least16_t		MR_sll_label_num_in_module;
 	MR_uint_least32_t		MR_sll_goal_path;
 	const MR_UserEvent		*MR_sll_user_event;
-	MR_Integer			MR_sll_var_count; /* < 0 */
 } MR_LabelLayoutNoVarInfo;
 
+typedef	struct MR_LabelLayoutProcLayoutOnly_Struct {
+	const MR_ProcLayout		*MR_sll_entry;
+	MR_Integer			MR_sll_var_count; /* = -2 */
+} MR_LabelLayoutProcLayoutOnly;
+
 #define	MR_label_goal_path(layout)					\
 	((MR_PROC_LAYOUT_HAS_EXEC_TRACE((layout)->MR_sll_entry)) ?	\
 		((layout)->MR_sll_entry->MR_sle_module_layout		\
@@ -571,8 +576,9 @@
 		MR_LABEL_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)) \
 	= {								\
 		MR_PROC_LAYOUT(MR_add_prefix(e)),			\
+		(vc),							\
 		MR_PASTE2(MR_PORT_, port),				\
-		(h), (num), (path), (s), (vc),				\
+		(h), (num), (path), (s),      				\
 		((const void *) lt),					\
 		((const MR_uint_least16_t *) vn),			\
 		((const MR_TypeParamLocns *) tv)			\
@@ -583,10 +589,18 @@
 		MR_LABEL_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)) \
 	= {								\
 		MR_PROC_LAYOUT(MR_add_prefix(e)),			\
+		-1,							\
 		MR_PASTE2(MR_PORT_, port),				\
-		(h), (path), (s), (num), -1				\
+		(h), (num), (path), (s)    				\
 	}
 
+#define	MR_DEF_LLPLO(e)        						\
+	static const MR_LabelLayoutProcLayoutOnly 			\
+		MR_LABEL_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), po)) \
+	= {								\
+		MR_PROC_LAYOUT(MR_add_prefix(e)),			\
+		-2							\
+	}
 
 #define	MR_DEF_LL(e, ln, port, num, path, vc, lt, vn, tv)		\
 	MR_DEF_LL_GEN(e, ln, port, MR_FALSE, num, path, NULL, vc, lt, vn, tv)
@@ -657,20 +671,20 @@
 		MR_XCOMMON(vnt, vnc), 0)
 
 #define	MR_DEF_LLNVI(e, ln, port, num, path)				\
-	MR_DEF_LLNVI_GEN(e, ln, port, NULL, MR_FALSE, path)
+	MR_DEF_LLNVI_GEN(e, ln, port, NULL, MR_FALSE, num, path)
 
 #define	MR_DEF_LLNVIT(e, ln, port, num, path)				\
-	MR_DEF_LLNVI_GEN(e, ln, port, NULL, MR_TRUE, path)
+	MR_DEF_LLNVI_GEN(e, ln, port, NULL, MR_TRUE, num, path)
 
 #define	MR_DEF_LLNVI_U(e, ln, port, num, path)				\
 	MR_DEF_LLNVI_GEN(e, ln, port,					\
 		&MR_USER_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)), \
-		MR_FALSE, path)
+		MR_FALSE, num, path)
 
 #define	MR_DEF_LLNVIT_U(e, ln, port, num, path)				\
 	MR_DEF_LLNVI_GEN(e, ln, port,					\
 		&MR_USER_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)), \
-		MR_TRUE, path)
+		MR_TRUE, num, path)
 
 #define MR_DECL_LL(e, ln)						\
 	MR_declare_label(MR_label_name(MR_add_prefix(e), ln));		\
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.80
diff -u -r1.80 mercury_stack_trace.c
--- runtime/mercury_stack_trace.c	2 Oct 2007 17:04:36 -0000	1.80
+++ runtime/mercury_stack_trace.c	20 Mar 2008 02:04:51 -0000
@@ -109,7 +109,6 @@
     const MR_Internal       *label;
     const MR_LabelLayout    *label_layout;
     const char              *result;
-    MR_bool                 stack_dump_available;
     char                    *env_suppress;
 
     env_suppress = getenv("MERCURY_SUPPRESS_STACK_TRACE");
@@ -117,31 +116,25 @@
         return;
     }
 
-#ifdef MR_STACK_TRACE
-    stack_dump_available = MR_TRUE;
-#else
-    stack_dump_available = MR_FALSE;
-#endif
+    MR_do_init_modules();
+    label = MR_lookup_internal_by_addr(success_pointer);
+    if (label == NULL) {
+        fprintf(stderr, "Stack dump not available.\n");
+        return;
+    }
 
-    if (stack_dump_available) {
-        fprintf(stderr, "Stack dump follows:\n");
+    label_layout = label->MR_internal_layout;
+    if (label_layout == NULL) {
+        fprintf(stderr, "Stack dump not available.\n");
+        return;
+    }
 
-        MR_do_init_modules();
-        label = MR_lookup_internal_by_addr(success_pointer);
-        if (label == NULL) {
-            fprintf(stderr, "internal label not found\n");
-        } else {
-            label_layout = label->MR_internal_layout;
-            result = MR_dump_stack_from_layout(stderr, label_layout,
-                det_stack_pointer, current_frame, include_trace_data,
-                MR_TRUE, 0, 0, &MR_dump_stack_record_print);
+    result = MR_dump_stack_from_layout(stderr, label_layout,
+        det_stack_pointer, current_frame, include_trace_data,
+        MR_TRUE, 0, 0, &MR_dump_stack_record_print);
 
-            if (result != NULL) {
-                fprintf(stderr, "%s\n", result);
-            }
-        }
-    } else {
-        fprintf(stderr, "Stack dump not available in this grade.\n");
+    if (result != NULL) {
+        fprintf(stderr, "%s\n", result);
     }
 }
 
@@ -164,6 +157,8 @@
     int                             frames_dumped_so_far;
     int                             lines_dumped_so_far;
 
+    fprintf(stderr, "Stack dump follows:\n");
+
     MR_do_init_modules();
     MR_dump_stack_record_init(include_trace_data, include_contexts);
 
Index: util/mkinit.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/util/mkinit.c,v
retrieving revision 1.119
diff -u -r1.119 mkinit.c
--- util/mkinit.c	12 Sep 2007 06:21:20 -0000	1.119
+++ util/mkinit.c	20 Mar 2008 05:14:40 -0000
@@ -314,7 +314,7 @@
     "#include \"mercury_grade.h\"\n"
     "\n"
     "#define MR_TRACE_ENABLED %d\n"
-    "#if MR_TRACE_ENABLED\n"
+    "#if MR_TRACE_ENABLED || !defined(MR_HIGHLEVEL_CODE)\n"
     "  #define MR_MAY_NEED_INITIALIZATION\n"
     "#endif\n"
     "\n"


--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list