for review: --stack-trace-higher-order

Zoltan Somogyi zs at cs.mu.OZ.AU
Sun Nov 1 19:50:53 AEDT 1998


For review by Fergus or Tyson, whichever of them read this first.
Others may wish to look at the new library predicate list__filter_any.

Estimated hours taken: 18

Make it possible to compile a module (e.g. std_util) without debugging,
while still allowing debuggable code called from that module via higher-order
predicates (e.g. solutions) to have a proper stack trace.

compiler/options.m:
	Add the new option --stack-trace-higher-order.

compiler/mercury_compile.m:
	Always invoke continuation_info and stack_layout, since it is no
	longer the case that either all procedures or none get layout
	structures generated for them, and the other modules are in a better
	position to make that decision.

compiler/continuation_info.m:
	Handle the extra tests required by the change to mercury_compile.m.

	When we gather info about a procedure, remember whether that
	procedure must have a procedure layout that includes the procedure id
	section.

compiler/stack_layout.m:
	Use the flag remembered by continuation_info to help decide
	whether we need procedure layout structures.

	Fix an old space wastage: after generating marker saying that
	the second and later groups of fields of a procedure layout are
	not present, do not generate another marker saying that the
	third group of fields is not present.

compiler/code_gen.m:
	Use the new capability of continuation_info.m to require
	procedure layouts including procedure id sections for any predicate
	that has higher-order arguments, if --stack-trace-higher-order is set.

compiler/globals.m:
	Rename want_return_layouts as want_return_var_layouts, since this
	is a more accurate representation of what the predicate does.

compiler/call_gen.m:
compiler/code_info.m:
	Conform to the change in globals.m.

compiler/llds_out.m:
	Separate the c_modules containing compiler-generated code into two
	groups, those that define labels that have stack layouts and those
	that don't. In most cases one or the other category will be empty,
	but with --stack-trace-higher-order, the c_modules containing
	higher-order procedures will have stack layouts, while others will
	not.

	Reorganize the way the way the initialization functions are generated,
	by putting c_modules falling into different categories into different
	bunches. c_module falling into the first category always have their
	initialization code included, while those in the second category
	have it included only if the old flag MR_MAY_NEED_INITIALIZATION
	is set.

	Delete the obsolete #define of MR_STACK_TRACE_THIS_MODULE.

	Improve some predicate names, in an effort to prevent confusion
	about what a "file" is (since the code uses more than meaning,
	given the presence of --split-c-files).

compiler/pragma_c_gen.m:
	Fix an old bug: s/NONDET_FIXED_SIZE/MR_NONDET_FIXED_SIZE/.
	Required for the change to library/string.m.

doc/user_guide.texi:
	Document the new option.

runtime/mercury_goto.c:
	Simplify the conditions under which labels get added to the label
	table with:

	- The macros init_{entry,label,local}_ai always add
	rhe label to the label table without a layout structure.
	
	- The macros init_{entry,label,local}_sl always add it with a layout
	structure.
	
	- Whether the macros init_{entry,label,local} with no suffix
	add the label to the label table depends on the values of other
	configuration parameters, but they will never include a layout
	structure.

	The intended use is that any label that has a layout structure should
	be initialized with a _sl macro. Any other label that should always
	be in the label table if the label table is needed at all (labels
	such as do_fail) should be initialized with _ai. Everything else
	should be initialized with a suffixless macro.

runtime/mercury_conf_params.c:
	Remove MR_USE_STACK_LAYOUTS and MR_STACK_TRACE_THIS_MODULE, since
	due to the simplification of mercury_goto.h, they are not used anymore.

runtime/mercury_stack_layout.c:
	Remove the old macros for creating layout structures with bogus
	contents, and replace them with new macros for creating layout
	structures with meaningful contents.

runtime/mercury_bootstrap.c:
	Remove bogus layout structures. Add proper ones.

runtime/mercury_engine.c:
runtime/mercury_wrapper.c:
	Remove bogus layout structures. Ensure the labels defined here
	always get into the label table.

runtime/mercury_ho_call.c:
	Remove bogus layout structures. Add proper ones where necessary.

runtime/mercury_type_info.c:
	Remove bogus layout structures.

runtime/mercury_stacks.c:
	Temporarily #define NONDET_FIXED_SIZE as MR_NONDET_FIXED_SIZE, since
	pragma_c_gen.m refers to the former until the update to it gets
	installed.

library/builtin.m:
	Remove bogus layout structures.

library/array.m:
library/benchmarking.m:
library/private_builtin.m:
	Remove bogus layout structures. Add proper ones.

library/std_util.m:
	Remove bogus layout structures. Add proper ones.

	Replace references to framevar(n) with references to MR_framevar(n+1).

library/string.m:
	Remove the need for bogus layout structures, by converting the
	implementation of string__append(out, out, in) from hand-written
	C module into nondet pragma C code.

library/list.m:
	Add a new predicate list__filter_any for use by llds_out.m.

NEWS:
	Mention the new library predicate.

Zoltan.

cvs diff: Diffing .
Index: NEWS
===================================================================
RCS file: /home/mercury1/repository/mercury/NEWS,v
retrieving revision 1.122
diff -u -u -r1.122 NEWS
--- NEWS	1998/10/20 02:02:29	1.122
+++ NEWS	1998/11/01 08:35:51
@@ -329,6 +329,7 @@
 	  det_univ_to_type/2
 	  eqvclass__same_eqvclass_list/2
 	  io__read_line_as_string/{3,4}
+	  list__filter_any/2
 	  list__take_upto/3
 	  map__det_insert_from_assoc_list/3
 	  map__det_intersect/5
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 bytecode/test
cvs diff: Diffing compiler
Index: compiler/call_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/call_gen.m,v
retrieving revision 1.125
diff -u -u -r1.125 call_gen.m
--- call_gen.m	1998/10/23 00:39:51	1.125
+++ call_gen.m	1998/10/29 04:42:56
@@ -649,8 +649,8 @@
 	code_info__generate_stack_livelvals(OutArgs, AfterCallInstMap, 
 		LiveVals0),
 	code_info__get_globals(Globals),
-	{ globals__want_return_layouts(Globals, WantReturnLayout) },
-	call_gen__insert_arg_livelvals(OutputArgs, WantReturnLayout,
+	{ globals__want_return_var_layouts(Globals, WantReturnVarLayout) },
+	call_gen__insert_arg_livelvals(OutputArgs, WantReturnVarLayout,
 		AfterCallInstMap, LiveVals0, LiveVals).
 
 % Maybe a varlist to type_id list would be a better way to do this...
@@ -662,13 +662,13 @@
 :- mode call_gen__insert_arg_livelvals(in, in, in, in, out, in, out) is det.
 
 call_gen__insert_arg_livelvals([], _, _, LiveVals, LiveVals) --> [].
-call_gen__insert_arg_livelvals([Var - L | As], WantReturnLayout,
+call_gen__insert_arg_livelvals([Var - L | As], WantReturnVarLayout,
 		AfterCallInstMap, LiveVals0, LiveVals) -->
 	code_info__get_varset(VarSet),
 	{ varset__lookup_name(VarSet, Var, Name) },
 	{ code_util__arg_loc_to_register(L, R) },
 	(
-		{ WantReturnLayout = yes }
+		{ WantReturnVarLayout = yes }
 	->
 		{ instmap__lookup_var(AfterCallInstMap, Var, Inst) },
 
@@ -681,8 +681,8 @@
 		{ map__init(Empty) },
 		{ LiveVal = live_lvalue(direct(R), unwanted, Empty) }
 	),
-	call_gen__insert_arg_livelvals(As, WantReturnLayout, AfterCallInstMap, 
-		[LiveVal | LiveVals0], LiveVals).
+	call_gen__insert_arg_livelvals(As, WantReturnVarLayout,
+		AfterCallInstMap, [LiveVal | LiveVals0], LiveVals).
 
 %---------------------------------------------------------------------------%
 
Index: compiler/code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_gen.m,v
retrieving revision 1.57
diff -u -u -r1.57 code_gen.m
--- code_gen.m	1998/10/23 00:39:54	1.57
+++ code_gen.m	1998/10/30 07:26:38
@@ -44,8 +44,8 @@
 		% structures and the counter for ensuring the uniqueness
 		% of cell numbers.
 
-:- pred generate_proc_code(proc_info::in, proc_id::in, pred_id::in,
-	module_info::in, globals::in,
+:- pred generate_proc_code(pred_info::in, proc_info::in,
+	proc_id::in, pred_id::in, module_info::in, globals::in,
 	continuation_info::in, continuation_info::out, int::in, int::out,
 	c_procedure::out) is det.
 
@@ -144,8 +144,8 @@
 		Procs0, Procs) :-
 	pred_info_procedures(PredInfo, ProcInfos),
 	map__lookup(ProcInfos, ProcId, ProcInfo),
-	generate_proc_code(ProcInfo, ProcId, PredId, ModuleInfo0, Globals,
-		ContInfo0, ContInfo1, CellCount0, CellCount1, Proc),
+	generate_proc_code(PredInfo, ProcInfo, ProcId, PredId, ModuleInfo0,
+		Globals, ContInfo0, ContInfo1, CellCount0, CellCount1, Proc),
 	generate_proc_list_code(ProcIds, PredId, PredInfo, ModuleInfo0,
 		Globals, ContInfo1, ContInfo, CellCount1, CellCount,
 		[Proc | Procs0], Procs).
@@ -169,7 +169,7 @@
 
 %---------------------------------------------------------------------------%
 
-generate_proc_code(ProcInfo, ProcId, PredId, ModuleInfo, Globals,
+generate_proc_code(PredInfo, ProcInfo, ProcId, PredId, ModuleInfo, Globals,
 		ContInfo0, ContInfo, CellCount0, CellCount, Proc) :-
 	proc_info_interface_determinism(ProcInfo, Detism),
 	proc_info_interface_code_model(ProcInfo, CodeModel),
@@ -186,8 +186,8 @@
 		MaybeFollowVars = no,
 		map__init(FollowVars)
 	),
-	globals__lookup_bool_option(Globals, basic_stack_layout,
-		BasicStackLayout),
+	continuation_info__basic_stack_layout_for_proc(PredInfo, Globals,
+		BasicStackLayout, ForceProcId),
 	( BasicStackLayout = yes ->
 		SaveSuccip = yes
 	;
@@ -236,7 +236,7 @@
 		continuation_info__add_proc_info(proc(PredId, ProcId),
 			EntryLabel, TotalSlots, Detism, MaybeSuccipSlot,
 			MaybeTraceCallLabel, MaybeFromFullSlot,
-			LayoutInfo, ContInfo0, ContInfo)
+			ForceProcId, LayoutInfo, ContInfo0, ContInfo)
 	;
 		ContInfo = ContInfo0
 	),
Index: compiler/code_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_info.m,v
retrieving revision 1.230
diff -u -u -r1.230 code_info.m
--- code_info.m	1998/10/23 00:39:56	1.230
+++ code_info.m	1998/10/29 04:47:53
@@ -3097,8 +3097,8 @@
 	code_info__generate_var_livelvals(VarList, LiveVals0, LiveVals1),
 	{ set__to_sorted_list(LiveVals1, LiveVals2) },
 	code_info__get_globals(Globals),
-	{ globals__want_return_layouts(Globals, WantReturnLayout) },
-	code_info__livevals_to_livelvals(LiveVals2, WantReturnLayout, 
+	{ globals__want_return_var_layouts(Globals, WantReturnVarLayout) },
+	code_info__livevals_to_livelvals(LiveVals2, WantReturnVarLayout, 
 		AfterCallInstMap, LiveVals3),
 	code_info__get_temps_in_use(TempsSet),
 	{ map__to_assoc_list(TempsSet, Temps) },
@@ -3131,11 +3131,11 @@
 :- mode code_info__livevals_to_livelvals(in, in, in, out, in, out) is det.
 
 code_info__livevals_to_livelvals([], _, _, []) --> [].
-code_info__livevals_to_livelvals([Lval - Var | Ls], WantReturnLayout,
+code_info__livevals_to_livelvals([Lval - Var | Ls], WantReturnVarLayout,
 		AfterCallInstMap, [LiveLval | Lives]) -->
 	code_info__get_varset(VarSet),
 	(
-		{ WantReturnLayout = yes }
+		{ WantReturnVarLayout = yes }
 	->
 		{ instmap__lookup_var(AfterCallInstMap, Var, Inst) },
 		{ varset__lookup_name(VarSet, Var, Name) },
@@ -3149,7 +3149,7 @@
 		{ map__init(Empty) },
 		{ LiveLval = live_lvalue(direct(Lval), unwanted, Empty) }
 	),
-	code_info__livevals_to_livelvals(Ls, WantReturnLayout,
+	code_info__livevals_to_livelvals(Ls, WantReturnVarLayout,
 		AfterCallInstMap, Lives).
 
 :- pred code_info__get_live_value_type(slot_contents, live_value_type).
Index: compiler/continuation_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/continuation_info.m,v
retrieving revision 1.16
diff -u -u -r1.16 continuation_info.m
--- continuation_info.m	1998/10/23 00:40:01	1.16
+++ continuation_info.m	1998/10/30 07:30:10
@@ -46,7 +46,7 @@
 
 :- interface.
 
-:- import_module llds, hlds_pred, prog_data, hlds_data.
+:- import_module llds, hlds_module, hlds_pred, hlds_data, prog_data, globals.
 :- import_module set, map, list, std_util, bool.
 
 	%
@@ -77,6 +77,10 @@
 					% stack slot containing the
 					% value of MR_trace_from_full
 					% at the time of the call.
+			bool,		% Do we require the procedure id
+					% section of the procedure layout
+					% to be present, even if the option
+					% procid_stack_layout is not set?
 			proc_label_layout_info
 					% Info for each internal label,
 					% needed for basic_stack_layouts.
@@ -172,31 +176,38 @@
 :- pred continuation_info__init(continuation_info::out) is det.
 
 	%
-	% Add the information for a single proc.
+	% Add all the information accumulated by the first three passes
+	% above for a single procedure.
 	%
 	% Takes the pred_proc_id, entry label, the number of stack slots,
-	% the code model for this proc, and the stack slot of the succip
-	% in this proc (if there is one).
+	% the determinism of the proc, the stack slot of the succip
+	% in this proc (if there is one), the label of the call event
+	% if there is such an event), the slot containing the saved from-full
+	% flag (if there is such a slot), a flag saying whether we definitely
+	% need a procedure id section in the procedure layout, as well as the
+	% layouts at all the trace event labels.
 	%
 :- pred continuation_info__add_proc_info(pred_proc_id::in, label::in,
 	int::in, determinism::in, maybe(int)::in, maybe(label)::in,
-	maybe(int)::in, proc_label_layout_info::in, continuation_info::in,
-	continuation_info::out) is det.
+	maybe(int)::in, bool::in, proc_label_layout_info::in,
+	continuation_info::in, continuation_info::out) is det.
 
 	%
-	% Call continuation_info__process_instructions on the code
+	% Call continuation_info__maybe_process_proc_llds on the code
 	% of every procedure in the list.
 	%
-:- pred continuation_info__process_llds(list(c_procedure)::in, bool::in,
-	continuation_info::in, continuation_info::out) is det.
+:- pred continuation_info__maybe_process_llds(list(c_procedure)::in,
+	module_info::in, continuation_info::in, continuation_info::out) is det.
 
 	%
-	% Add the information for all the continuation labels within a proc.
-	% The bool says whether we want information about the variables
-	% live at continuation labels.
+	% Check whether this procedure ought to have any layout structures
+	% generated for it. If yes, then update the continuation_info to
+	% include all the continuation labels within a proc. Whether or not
+	% the information about a continuation label includes the variables
+	% live at that label depends on the values of options.
 	%
-:- pred continuation_info__process_instructions(pred_proc_id::in,
-	list(instruction)::in, bool::in,
+:- pred continuation_info__maybe_process_proc_llds(list(instruction)::in,
+	pred_proc_id::in, module_info::in,
 	continuation_info::in, continuation_info::out) is det.
 
 	%
@@ -205,11 +216,20 @@
 :- pred continuation_info__get_all_proc_layouts(continuation_info::in,
 	list(proc_layout_info)::out) is det.
 
+	%
+	% Check whether the given procedure should have at least (a) a basic
+	% stack layout, and (b) a procedure id layout generated for it.
+	% The two bools returned answer these two questions respectively.
+	%
+:- pred continuation_info__basic_stack_layout_for_proc(pred_info::in,
+	globals::in, bool::out, bool::out) is det.
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
 :- implementation.
 
+:- import_module options, type_util.
 :- import_module require.
 
 	% The continuation_info data structure
@@ -232,13 +252,14 @@
 	%
 continuation_info__add_proc_info(PredProcId, EntryLabel, StackSize,
 		Detism, SuccipLocation, MaybeTraceCallLabel,
-		MaybeFromFullSlot, InternalMap, ContInfo0, ContInfo) :-
+		MaybeFromFullSlot, ForceProcId, InternalMap,
+		ContInfo0, ContInfo) :-
 	( map__contains(ContInfo0, PredProcId) ->
 		error("duplicate continuation_info for proc.")
 	;
 		LayoutInfo = proc_layout_info(EntryLabel, Detism, StackSize,
 			SuccipLocation, MaybeTraceCallLabel,
-			MaybeFromFullSlot, InternalMap),
+			MaybeFromFullSlot, ForceProcId, InternalMap),
 		map__det_insert(ContInfo0, PredProcId, LayoutInfo, ContInfo)
 	).
 
@@ -248,23 +269,42 @@
 continuation_info__get_all_proc_layouts(ContInfo, Entries) :-
 	map__values(ContInfo, Entries).
 
-continuation_info__process_llds([], _) --> [].
-continuation_info__process_llds([Proc | Procs], WantReturnInfo) -->
+continuation_info__maybe_process_llds([], _) --> [].
+continuation_info__maybe_process_llds([Proc | Procs], ModuleInfo) -->
 	{ Proc = c_procedure(_, _, PredProcId, Instrs) },
-	continuation_info__process_instructions(PredProcId, Instrs,
-		WantReturnInfo),
-	continuation_info__process_llds(Procs, WantReturnInfo).
+	continuation_info__maybe_process_proc_llds(Instrs, PredProcId,
+		ModuleInfo),
+	continuation_info__maybe_process_llds(Procs, ModuleInfo).
+
+continuation_info__maybe_process_proc_llds(Instructions, PredProcId,
+		ModuleInfo, ContInfo0, ContInfo) :-
+	PredProcId = proc(PredId, ProcId),
+	module_info_pred_proc_info(ModuleInfo, PredId, ProcId, PredInfo, _),
+	module_info_globals(ModuleInfo, Globals),
+	continuation_info__basic_stack_layout_for_proc(PredInfo, Globals,
+		Layout, _),
+	( Layout = yes ->
+		globals__want_return_var_layouts(Globals, WantReturnLayout),
+		continuation_info__process_proc_llds(PredProcId, Instructions,
+			WantReturnLayout, ContInfo0, ContInfo)
+	;
+		ContInfo = ContInfo0
+	).
 
 	%
 	% Process the list of instructions for this proc, adding
 	% all internal label information to the continuation_info.
 	%
-continuation_info__process_instructions(PredProcId, Instructions,
+:- pred continuation_info__process_proc_llds(pred_proc_id::in,
+	list(instruction)::in, bool::in,
+	continuation_info::in, continuation_info::out) is det.
+
+continuation_info__process_proc_llds(PredProcId, Instructions,
 		WantReturnInfo, ContInfo0, ContInfo) :-
 
 		% Get all the continuation info from the call instructions.
 	map__lookup(ContInfo0, PredProcId, ProcLayoutInfo0),
-	ProcLayoutInfo0 = proc_layout_info(A, B, C, D, E, F, Internals0),
+	ProcLayoutInfo0 = proc_layout_info(A, B, C, D, E, F, G, Internals0),
 	GetCallLivevals = lambda([Instr::in, Pair::out] is semidet, (
 		Instr = call(_, label(Label), LiveInfo, _) - _Comment,
 		Pair = Label - LiveInfo
@@ -275,7 +315,7 @@
 	list__foldl(continuation_info__process_continuation(WantReturnInfo),
 		Calls, Internals0, Internals),
 
-	ProcLayoutInfo = proc_layout_info(A, B, C, D, E, F, Internals),
+	ProcLayoutInfo = proc_layout_info(A, B, C, D, E, F, G, Internals),
 	map__det_update(ContInfo0, PredProcId, ProcLayoutInfo, ContInfo).
 
 %-----------------------------------------------------------------------------%
@@ -354,5 +394,35 @@
 	;
 		Filtered = Filtered1
 	).
+
+%-----------------------------------------------------------------------------%
+
+continuation_info__basic_stack_layout_for_proc(PredInfo, Globals,
+		BasicLayout, ForceProcIdLayout) :-
+	(
+		globals__lookup_bool_option(Globals, stack_trace_higher_order,
+			yes),
+		continuation_info__some_arg_is_higher_order(PredInfo)
+	->
+		BasicLayout = yes,
+		ForceProcIdLayout = yes
+	;
+		globals__lookup_bool_option(Globals, basic_stack_layout, yes)
+	->
+		BasicLayout = yes,
+		ForceProcIdLayout = no
+	;
+		BasicLayout = no,
+		ForceProcIdLayout = no
+	).
+
+:- pred continuation_info__some_arg_is_higher_order(pred_info::in) is semidet.
+
+continuation_info__some_arg_is_higher_order(PredInfo) :-
+	pred_info_arg_types(PredInfo, ArgTypes),
+	some([Type], (
+		list__member(Type, ArgTypes),
+		type_is_higher_order(Type, _, _)
+	)).
 
 %-----------------------------------------------------------------------------%
Index: compiler/globals.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/globals.m,v
retrieving revision 1.32
diff -u -u -r1.32 globals.m
--- globals.m	1998/10/16 06:17:14	1.32
+++ globals.m	1998/10/29 04:42:05
@@ -103,9 +103,10 @@
 
 :- pred globals__have_static_code_addresses(globals::in, bool::out) is det.
 
-	% Check if we should generate stack layouts at call return sites.
+	% Check if we should include variable information in the layout
+	% structures of call return sites.
 
-:- pred globals__want_return_layouts(globals::in, bool::out) is det.
+:- pred globals__want_return_var_layouts(globals::in, bool::out) is det.
 
 %-----------------------------------------------------------------------------%
 
@@ -296,7 +297,7 @@
 	getopt__lookup_bool_option(OptionTable, asm_labels, AsmLabels),
 	exprn_aux__imported_is_constant(NonLocalGotos, AsmLabels, IsConst).
 
-globals__want_return_layouts(Globals, WantReturnLayouts) :-
+globals__want_return_var_layouts(Globals, WantReturnLayouts) :-
 	% We need to generate layout info for call return labels
 	% if we are using accurate gc or if the user wants uplevel printing.
 	(
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.94
diff -u -u -r1.94 llds_out.m
--- llds_out.m	1998/10/30 05:10:56	1.94
+++ llds_out.m	1998/11/01 07:44:49
@@ -20,14 +20,13 @@
 :- import_module llds, prog_data, hlds_data.
 :- import_module set_bbbtree, bool, io.
 
-	% Given a 'c_file' structure, open the appropriate .c 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.
+	% Given a 'c_file' structure, output the LLDS code inside it
+	% into one or more .c files, depending on the setting of the
+	% --split-c-files option. The second 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_llds(c_file, set_bbbtree(label), io__state, io__state).
+:- mode output_llds(in, in, di, uo) is det.
 
 	% Convert an lval to a string description of that lval.
 
@@ -163,14 +162,17 @@
 decl_set_is_member(DeclId, DeclSet) :-
 	map__search(DeclSet, DeclId, _).
 
-output_c_file(C_File, StackLayoutLabels) -->
+%-----------------------------------------------------------------------------%
+
+output_llds(C_File, StackLayoutLabels) -->
 	globals__io_lookup_bool_option(split_c_files, SplitFiles),
 	( { SplitFiles = yes } ->
 		{ C_File = c_file(ModuleName, C_HeaderInfo, C_Modules) },
 		module_name_to_file_name(ModuleName, ".dir", yes, ObjDirName),
 		make_directory(ObjDirName),
-		output_c_file_init(ModuleName, C_Modules),
-		output_c_file_list(C_Modules, 1, ModuleName,
+		output_split_c_file_init(ModuleName, C_Modules,
+			StackLayoutLabels),
+		output_split_c_file_list(C_Modules, 1, ModuleName,
 			C_HeaderInfo, StackLayoutLabels)
 	;
 		output_single_c_file(C_File, no, StackLayoutLabels)
@@ -184,23 +186,24 @@
 		Command) },
 	io__call_system(Command, _Result).
 
-:- pred output_c_file_list(list(c_module), int, module_name,
+:- pred output_split_c_file_list(list(c_module), int, module_name,
 	list(c_header_code), set_bbbtree(label), io__state, io__state).
-:- mode output_c_file_list(in, in, in, in, in, di, uo) is det.
+:- mode output_split_c_file_list(in, in, in, in, in, di, uo) is det.
 
-output_c_file_list([], _, _, _, _) --> [].
-output_c_file_list([Module|Modules], Num, ModuleName, C_HeaderLines,
+output_split_c_file_list([], _, _, _, _) --> [].
+output_split_c_file_list([Module|Modules], Num, ModuleName, C_HeaderLines,
 		StackLayoutLabels) -->
 	output_single_c_file(c_file(ModuleName, C_HeaderLines, [Module]),
 		yes(Num), StackLayoutLabels),
 	{ Num1 is Num + 1 },
-	output_c_file_list(Modules, Num1, ModuleName, C_HeaderLines,
+	output_split_c_file_list(Modules, Num1, ModuleName, C_HeaderLines,
 		StackLayoutLabels).
 
-:- pred output_c_file_init(module_name, list(c_module), io__state, io__state).
-:- mode output_c_file_init(in, in, di, uo) is det.
+:- pred output_split_c_file_init(module_name, list(c_module),
+	set_bbbtree(label), io__state, io__state).
+:- mode output_split_c_file_init(in, in, in, di, uo) is det.
 
-output_c_file_init(ModuleName, C_Modules) -->
+output_split_c_file_init(ModuleName, C_Modules, StackLayoutLabels) -->
 	module_name_to_file_name(ModuleName, ".m", no, SourceFileName),
 	module_name_to_split_c_file_name(ModuleName, 0, ".c", FileName),
 
@@ -224,7 +227,8 @@
 		io__write_string("*/\n\n"),
 		output_c_file_mercury_headers,
 		io__write_string("\n"),
-		output_c_module_init_list(ModuleName, C_Modules),
+		output_c_module_init_list(ModuleName, C_Modules,
+			StackLayoutLabels),
 		io__told
 	;
 		io__progname_base("llds.m", ProgName),
@@ -247,7 +251,6 @@
 	io__write_string("#define MR_USE_REDOFR\n"),
 	globals__io_get_trace_level(TraceLevel),
 	( { TraceLevel \= none } ->
-		io__write_string("#define MR_STACK_TRACE_THIS_MODULE\n"),
 		io__write_string("#include ""mercury_imp.h""\n"),
 		io__write_string("#include ""mercury_trace_base.h""\n")
 	;
@@ -301,7 +304,8 @@
 			[]
 		;
 			io__write_string("\n"),
-			output_c_module_init_list(ModuleName, Modules)
+			output_c_module_init_list(ModuleName, Modules,
+				StackLayoutLabels)
 		),
 		io__told
 	;
@@ -315,23 +319,28 @@
 	).
 
 :- pred output_c_module_init_list(module_name, list(c_module),
-					io__state, io__state).
-:- mode output_c_module_init_list(in, in, di, uo) is det.
+	set_bbbtree(label), io__state, io__state).
+:- mode output_c_module_init_list(in, in, in, di, uo) is det.
 
-output_c_module_init_list(ModuleName, Modules) -->
+output_c_module_init_list(ModuleName, Modules, StackLayoutLabels) -->
+	{ divide_modules_on_init_status(Modules, StackLayoutLabels,
+		AlwaysInitModules, MaybeInitModules) },
+	{ list__chunk(AlwaysInitModules, 40, AlwaysInitModuleBunches) },
+	{ list__chunk(MaybeInitModules, 40, MaybeInitModuleBunches) },
+	globals__io_lookup_bool_option(split_c_files, SplitFiles),
 
-		% Output initialization functions, bunched into groups
-		% of 40.
-	io__write_string("#if defined(MR_MAY_NEED_INITIALIZATION)\n\n"),
-	io__write_string("static void "),
-	output_bunch_name(ModuleName, 0),
-	io__write_string("(void)\n"),
-	io__write_string("{\n"),
-	output_c_module_init_list_2(Modules, ModuleName, 0, 40, 0, InitFuncs),
-	io__write_string("}\n\n#endif\n\n"),
+	output_init_bunch_defs(AlwaysInitModuleBunches, ModuleName,
+		"always", 0, SplitFiles),
+
+	( { MaybeInitModuleBunches = [] } ->
+		[]
+	;
+		io__write_string("#ifdef MR_MAY_NEED_INITIALIZATION\n\n"),
+		output_init_bunch_defs(MaybeInitModuleBunches, ModuleName,
+			"maybe", 0, SplitFiles),
+		io__write_string("#endif\n\n")
+	),
 
-		% Output code to call each of the init functions created
-		% above.
 	io__write_string("void "),
 	output_init_name(ModuleName),
 	io__write_string("(void);"),
@@ -340,79 +349,134 @@
 	output_init_name(ModuleName),
 	io__write_string("(void)\n"),
 	io__write_string("{\n"),
-	io__write_string("#if defined(MR_MAY_NEED_INITIALIZATION)\n\n"),
 	io__write_string("\tstatic bool done = FALSE;\n"),
 	io__write_string("\tif (!done) {\n"),
 	io__write_string("\t\tdone = TRUE;\n"),
-	output_c_module_init_list_3(0, ModuleName, InitFuncs),
-	io__write_string("\t}\n"),
-	io__write_string("#endif\n"),
+
+	output_init_bunch_calls(AlwaysInitModuleBunches, ModuleName,
+		"always", 0),
+
+	( { MaybeInitModuleBunches = [] } ->
+		[]
+	;
+		io__write_string("\n#ifdef MR_MAY_NEED_INITIALIZATION\n"),
+		output_init_bunch_calls(MaybeInitModuleBunches, ModuleName,
+			"maybe", 0),
+		io__write_string("#endif\n\n")
+	),
+
 	output_c_data_init_list(Modules),
-	io__write_string("}\n"),
-	io__write_string("\n"),
+	io__write_string("\t}\n"),
+	io__write_string("}\n\n"),
 	io__write_string(
 		"/* ensure everything is compiled with the same grade */\n"),
 	io__write_string(
 		"static const void *const MR_grade = &MR_GRADE_VAR;\n").
 
-:- pred output_c_module_init_list_2(list(c_module), module_name, int, int, int,
-		int, io__state, io__state).
-:- mode output_c_module_init_list_2(in, in, in, in, in, out, di, uo) is det.
-
-output_c_module_init_list_2([], _, _, _, InitFunc, InitFunc) --> [].
-output_c_module_init_list_2([c_data(_, _, _, _, _) | Ms], A, B, C, D, E) -->
-	output_c_module_init_list_2(Ms, A, B, C, D, E).
-output_c_module_init_list_2([c_export(_) | Ms], A, B, C, D, E) -->
-	output_c_module_init_list_2(Ms, A, B, C, D, E).
-output_c_module_init_list_2([c_code(_, _) | Ms], A, B, C, D, E) -->
-	output_c_module_init_list_2(Ms, A, B, C, D, E).
-output_c_module_init_list_2([c_module(C_ModuleName, _) | Ms], ModuleName,
-		Calls0, MaxCalls, InitFunc0, InitFunc) -->
-	( { Calls0 > MaxCalls } ->
-		io__write_string("}\n\n"),
-		{ InitFunc1 is InitFunc0 + 1 },
-		io__write_string("static void "),
-		output_bunch_name(ModuleName, InitFunc1),
-		io__write_string("(void)\n"),
-		io__write_string("{\n"),
-		{ Calls1 = 1 }
+	% Divide_modules_on_init_status checks every module in its input list.
+	% If the module does not have compiler-generated code in it, it
+	% ignores the module. If it does, it will include the module in
+	% one of its output lists. If the module defines a label that has
+	% a stack layout structure, it will go into the always-init list,
+	% otherwise it will go into the maybe-init list.
+
+:- pred divide_modules_on_init_status(list(c_module), set_bbbtree(label),
+	list(c_module), list(c_module)).
+:- mode divide_modules_on_init_status(in, in, out, out) is det.
+
+divide_modules_on_init_status([], _, [], []).
+divide_modules_on_init_status([Module | Modules], StackLayoutLabels,
+		AlwaysInit, MaybeInit) :-
+	(
+		Module = c_data(_, _, _, _, _),
+		divide_modules_on_init_status(Modules, StackLayoutLabels,
+			AlwaysInit, MaybeInit)
 	;
-		{ InitFunc1 = InitFunc0 },
-		{ Calls1 is Calls0 + 1 }
-	),
-	globals__io_lookup_bool_option(split_c_files, SplitFiles),
-	( { SplitFiles = yes } ->
-		io__write_string("\t{ extern ModuleFunc "),
-		io__write_string(C_ModuleName),
-		io__write_string(";\n"),
-		io__write_string("\t  "),
-		io__write_string(C_ModuleName),
-		io__write_string("(); }\n")
-	;
-		io__write_string("\t"),
-		io__write_string(C_ModuleName),
-		io__write_string("();\n")
-	),
-	output_c_module_init_list_2(Ms, ModuleName,
-		Calls1, MaxCalls, InitFunc1, InitFunc).
+		Module = c_export(_),
+		divide_modules_on_init_status(Modules, StackLayoutLabels,
+			AlwaysInit, MaybeInit)
+	;
+		Module = c_code(_, _),
+		divide_modules_on_init_status(Modules, StackLayoutLabels,
+			AlwaysInit, MaybeInit)
+	;
+		Module = c_module(_, Procedures),
+		divide_modules_on_init_status(Modules, StackLayoutLabels,
+			AlwaysInit1, MaybeInit1),
+		( set_bbbtree__empty(StackLayoutLabels) ->
+			% Checking whether the set is empty or not
+			% allows us to avoid calling gather_c_module_labels.
+			AlwaysInit = AlwaysInit1,
+			MaybeInit = [Module | MaybeInit1]
+		;
+			gather_c_module_labels(Procedures, Labels),
+			LabelHasStackLayout = lambda([Label::in] is semidet, (
+				set_bbbtree__member(Label, StackLayoutLabels)
+			)),
+			( list__filter_any(LabelHasStackLayout, Labels) ->
+				AlwaysInit = [Module | AlwaysInit1],
+				MaybeInit = MaybeInit1
+			;
+				AlwaysInit = AlwaysInit1,
+				MaybeInit = [Module | MaybeInit1]
+			)
+		)
+	).
 
-	% Output calls to all the bunched initialization functions.
+:- pred output_init_bunch_defs(list(list(c_module)), module_name, string, int,
+	bool, io__state, io__state).
+:- mode output_init_bunch_defs(in, in, in, in, in, di, uo) is det.
+
+output_init_bunch_defs([], _, _, _, _) --> [].
+output_init_bunch_defs([Bunch | Bunches], ModuleName, InitStatus, Seq,
+		SplitFiles) -->
+	io__write_string("static void "),
+	output_bunch_name(ModuleName, InitStatus, Seq),
+	io__write_string("(void)\n"),
+	io__write_string("{\n"),
+	output_init_bunch_def(Bunch, ModuleName, SplitFiles),
+	io__write_string("}\n\n"),
+	{ NextSeq is Seq + 1 },
+	output_init_bunch_defs(Bunches, ModuleName, InitStatus, NextSeq,
+		SplitFiles).
 
-:- pred output_c_module_init_list_3(int, module_name, int,
-				io__state, io__state).
-:- mode output_c_module_init_list_3(in, in, in, di, uo) is det.
+:- pred output_init_bunch_def(list(c_module), module_name, bool,
+	io__state, io__state).
+:- mode output_init_bunch_def(in, in, in, di, uo) is det.
 
-output_c_module_init_list_3(InitFunc0, ModuleName, MaxInitFunc) -->
-	( { InitFunc0 > MaxInitFunc } ->
-		[]
+output_init_bunch_def([], _, _) --> [].
+output_init_bunch_def([Module | Modules], ModuleName, SplitFiles) -->
+	( { Module = c_module(C_ModuleName, _) } ->
+		( { SplitFiles = yes } ->
+			io__write_string("\t{ extern ModuleFunc "),
+			io__write_string(C_ModuleName),
+			io__write_string(";\n"),
+			io__write_string("\t  "),
+			io__write_string(C_ModuleName),
+			io__write_string("(); }\n")
+		;
+			io__write_string("\t"),
+			io__write_string(C_ModuleName),
+			io__write_string("();\n")
+		),
+		output_init_bunch_def(Modules, ModuleName, SplitFiles)
 	;
-		io__write_string("\t\t"),
-		output_bunch_name(ModuleName, InitFunc0),
-		io__write_string("();\n"),
-		{ InitFunc1 is InitFunc0 + 1},
-		output_c_module_init_list_3(InitFunc1, ModuleName, MaxInitFunc)
+		% divide_modules_on_init_status should have filtered out
+		% whatever kind of module we just got.
+		{ error("unexpected type of c_module in output_init_bunch") }
 	).
 
+:- pred output_init_bunch_calls(list(list(c_module)), module_name, string, int,
+	io__state, io__state).
+:- mode output_init_bunch_calls(in, in, in, in, di, uo) is det.
+
+output_init_bunch_calls([], _, _, _) --> [].
+output_init_bunch_calls([_ | Bunches], ModuleName, InitStatus, Seq) -->
+	io__write_string("\t\t"),
+	output_bunch_name(ModuleName, InitStatus, Seq),
+	io__write_string("();\n"),
+	{ NextSeq is Seq + 1 },
+	output_init_bunch_calls(Bunches, ModuleName, InitStatus, NextSeq).
 
 	% Output MR_INIT_BASE_TYPE_INFO(BaseTypeInfo, TypeId);
 	% for each base_type_info defined in this module.
@@ -431,9 +495,9 @@
 	(
 		{ DataName = base_type(info, TypeName, Arity) }
 	->
-		io__write_string("\tMR_INIT_BASE_TYPE_INFO(\n\t\t"),
+		io__write_string("\t\tMR_INIT_BASE_TYPE_INFO(\n\t\t"),
 		output_data_addr(ModuleName, DataName),
-		io__write_string(",\n\t\t"),
+		io__write_string(",\n\t\t\t"),
 		{ llds_out__sym_name_mangle(ModuleName, ModuleNameString) },
 		{ string__append(ModuleNameString, "__", UnderscoresModule) },
 		( 
@@ -464,15 +528,16 @@
 	llds_out__sym_name_mangle(ModuleName, MangledModuleName),
 	string__append_list(["mercury__", MangledModuleName, "__init"],
 		InitName).
-
 
-:- pred output_bunch_name(module_name, int, io__state, io__state).
-:- mode output_bunch_name(in, in, di, uo) is det.
+:- pred output_bunch_name(module_name, string, int, io__state, io__state).
+:- mode output_bunch_name(in, in, in, di, uo) is det.
 
-output_bunch_name(ModuleName, Number) -->
+output_bunch_name(ModuleName, InitStatus, Number) -->
 	io__write_string("mercury__"),
 	{ llds_out__sym_name_mangle(ModuleName, MangledModuleName) },
 	io__write_string(MangledModuleName),
+	io__write_string("_"),
+	io__write_string(InitStatus),
 	io__write_string("_bunch_"),
 	io__write_int(Number).
 
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.111
diff -u -u -r1.111 mercury_compile.m
--- mercury_compile.m	1998/10/30 05:11:04	1.111
+++ mercury_compile.m	1998/11/01 05:11:45
@@ -1099,19 +1099,20 @@
 		ModuleInfo0, ModuleInfo, [Proc | Procs]) -->
 	{ pred_info_procedures(PredInfo, ProcTable) },
 	{ map__lookup(ProcTable, ProcId, ProcInfo) },
-	mercury_compile__backend_pass_by_preds_4(ProcInfo, ProcId, PredId,
-		ModuleInfo0, ModuleInfo1, Proc),
+	mercury_compile__backend_pass_by_preds_4(PredInfo, ProcInfo,
+		ProcId, PredId, ModuleInfo0, ModuleInfo1, Proc),
 	mercury_compile__backend_pass_by_preds_3(ProcIds, PredId, PredInfo,
 		ModuleInfo1, ModuleInfo, Procs).
 
-:- pred mercury_compile__backend_pass_by_preds_4(proc_info, proc_id, pred_id,
-	module_info, module_info, c_procedure, io__state, io__state).
-% :- mode mercury_compile__backend_pass_by_preds_4(in, in, in, di, uo,
+:- pred mercury_compile__backend_pass_by_preds_4(pred_info, proc_info,
+	proc_id, pred_id, module_info, module_info, c_procedure,
+	io__state, io__state).
+% :- mode mercury_compile__backend_pass_by_preds_4(in, in, in, in, di, uo,
 % 	out, di, uo) is det.
-:- mode mercury_compile__backend_pass_by_preds_4(in, in, in, in, out,
+:- mode mercury_compile__backend_pass_by_preds_4(in, in, in, in, in, out,
 	out, di, uo) is det.
 
-mercury_compile__backend_pass_by_preds_4(ProcInfo0, ProcId, PredId,
+mercury_compile__backend_pass_by_preds_4(PredInfo, ProcInfo0, ProcId, PredId,
 		ModuleInfo0, ModuleInfo, Proc) -->
 	globals__io_get_globals(Globals),
 	{ globals__lookup_bool_option(Globals, follow_code, FollowCode) },
@@ -1151,17 +1152,17 @@
 		write_proc_progress_message(
 			"% Calculating goal paths in ",
 					PredId, ProcId, ModuleInfo3),
-		{ goal_path__fill_slots(ProcInfo6, ModuleInfo3, ProcInfo7) }
+		{ goal_path__fill_slots(ProcInfo6, ModuleInfo3, ProcInfo) }
 	;
-		{ ProcInfo7 = ProcInfo6 }
+		{ ProcInfo = ProcInfo6 }
 	),
 	write_proc_progress_message(
 		"% Generating low-level (LLDS) code for ",
 				PredId, ProcId, ModuleInfo3),
 	{ module_info_get_continuation_info(ModuleInfo3, ContInfo0) },
 	{ module_info_get_cell_count(ModuleInfo3, CellCount0) },
-	{ generate_proc_code(ProcInfo7, ProcId, PredId, ModuleInfo3, Globals,
-		ContInfo0, ContInfo1, CellCount0, CellCount, Proc0) },
+	{ generate_proc_code(PredInfo, ProcInfo, ProcId, PredId, ModuleInfo3,
+		Globals, ContInfo0, ContInfo1, CellCount0, CellCount, Proc0) },
 	{ module_info_set_continuation_info(ModuleInfo3, ContInfo1, 
 		ModuleInfo4) },
 	{ module_info_set_cell_count(ModuleInfo4, CellCount, ModuleInfo5) },
@@ -1171,24 +1172,16 @@
 	;
 		{ Proc = Proc0 }
 	),
-	{ globals__lookup_bool_option(Globals, basic_stack_layout,
-		BasicStackLayout) },
-	( { BasicStackLayout = yes } ->
-		{ Proc = c_procedure(_, _, PredProcId, Instructions) },
-		{ module_info_get_continuation_info(ModuleInfo5, ContInfo2) },
-		write_proc_progress_message(
-			"% Generating call continuation information for ",
-				PredId, ProcId, ModuleInfo5),
-		{ globals__want_return_layouts(Globals, WantReturnLayout) },
-		{ continuation_info__process_instructions(PredProcId,
-			Instructions, WantReturnLayout,
-			ContInfo2, ContInfo3) },
-		{ module_info_set_continuation_info(ModuleInfo5, ContInfo3, 
-			ModuleInfo) }
-	;
-		{ ModuleInfo = ModuleInfo5 }
-	).
-	
+	{ Proc = c_procedure(_, _, PredProcId, Instructions) },
+	{ module_info_get_continuation_info(ModuleInfo5, ContInfo2) },
+	write_proc_progress_message(
+		"% Generating call continuation information for ",
+			PredId, ProcId, ModuleInfo5),
+	{ continuation_info__maybe_process_proc_llds(Instructions, PredProcId,
+		ModuleInfo5, ContInfo2, ContInfo3) },
+	{ module_info_set_continuation_info(ModuleInfo5, ContInfo3, 
+		ModuleInfo) }.
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -1835,23 +1828,16 @@
 
 mercury_compile__maybe_generate_stack_layouts(ModuleInfo0, LLDS0, Verbose, 
 		Stats, ModuleInfo) -->
-	globals__io_lookup_bool_option(basic_stack_layout, BasicStackLayout),
-	( { BasicStackLayout = yes } ->
-		maybe_write_string(Verbose,
-			"% Generating call continuation information..."),
-		maybe_flush_output(Verbose),
-		globals__io_get_globals(Globals),
-		{ globals__want_return_layouts(Globals, WantReturnLayout) },
-		{ module_info_get_continuation_info(ModuleInfo0, ContInfo0) },
-		{ continuation_info__process_llds(LLDS0, WantReturnLayout,
-			ContInfo0, ContInfo) },
-		{ module_info_set_continuation_info(ModuleInfo0, ContInfo,
-			ModuleInfo) },
-		maybe_write_string(Verbose, " done.\n"),
-		maybe_report_stats(Stats)
-	;
-		{ ModuleInfo = ModuleInfo0 }
-	).
+	maybe_write_string(Verbose,
+		"% Generating call continuation information..."),
+	maybe_flush_output(Verbose),
+	{ module_info_get_continuation_info(ModuleInfo0, ContInfo0) },
+	{ continuation_info__maybe_process_llds(LLDS0, ModuleInfo0,
+		ContInfo0, ContInfo) },
+	{ module_info_set_continuation_info(ModuleInfo0, ContInfo,
+		ModuleInfo) },
+	maybe_write_string(Verbose, " done.\n"),
+	maybe_report_stats(Stats).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -1889,28 +1875,19 @@
 mercury_compile__output_pass(HLDS0, LLDS0, ModuleName, CompileErrors) -->
 	globals__io_lookup_bool_option(verbose, Verbose),
 	globals__io_lookup_bool_option(statistics, Stats),
-	globals__io_lookup_bool_option(basic_stack_layout, BasicStackLayout),
-
 	{ base_type_info__generate_llds(HLDS0, BaseTypeInfos) },
 	{ base_type_layout__generate_llds(HLDS0, HLDS1, BaseTypeLayouts) },
-	{ BasicStackLayout = yes ->
-		stack_layout__generate_llds(HLDS1, HLDS,
-			StackLayouts, StackLayoutLabelMap),
-		list__append(StackLayouts, BaseTypeLayouts, StaticData0)
-	;
-		HLDS = HLDS1,
-		set_bbbtree__init(StackLayoutLabelMap),
-		StaticData0 = BaseTypeLayouts
-	},
-	{ get_c_interface_info(HLDS, C_InterfaceInfo) },
-
+	{ stack_layout__generate_llds(HLDS1, HLDS,
+		StackLayouts, StackLayoutLabels) },
+	{ list__append(StackLayouts, BaseTypeLayouts, StaticData0) },
 	{ llds_common(LLDS0, StaticData0, ModuleName, LLDS1, 
 		StaticData, CommonData) },
-
 	{ list__append(BaseTypeInfos, StaticData, AllData) },
+
+	{ get_c_interface_info(HLDS, C_InterfaceInfo) },
 	mercury_compile__chunk_llds(C_InterfaceInfo, LLDS1, AllData,
 		CommonData, LLDS2, NumChunks),
-	mercury_compile__output_llds(ModuleName, LLDS2, StackLayoutLabelMap,
+	mercury_compile__output_llds(ModuleName, LLDS2, StackLayoutLabels,
 		Verbose, Stats),
 
 	{ C_InterfaceInfo = c_interface_info(_ModuleName,
@@ -2031,7 +2008,7 @@
 	maybe_write_string(Verbose, "'..."),
 	maybe_flush_output(Verbose),
 	transform_llds(LLDS0, LLDS),
-	output_c_file(LLDS, StackLayoutLabels),
+	output_llds(LLDS, StackLayoutLabels),
 	maybe_write_string(Verbose, " done.\n"),
 	maybe_flush_output(Verbose),
 	maybe_report_stats(Stats).
Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.247
diff -u -u -r1.247 options.m
--- options.m	1998/10/30 05:11:09	1.247
+++ options.m	1998/11/01 07:38:19
@@ -94,6 +94,7 @@
 		;	trace_return
 		;	trace_redo
 		;	trace_optimized
+		;	stack_trace_higher_order
 		;	generate_bytecode
 		;	generate_prolog
 		;	prolog_dialect
@@ -384,6 +385,7 @@
 	trace_return		-	bool(yes),
 	trace_redo		-	bool(yes),
 	trace_optimized		-	bool(no),
+	stack_trace_higher_order -	bool(no),
 	generate_bytecode	-	bool(no),
 	generate_prolog		-	bool(no),
 	prolog_dialect		-	string("default"),
@@ -721,6 +723,7 @@
 long_option("trace-redo",		trace_redo).
 long_option("trace-optimised",		trace_optimized).
 long_option("trace-optimized",		trace_optimized).
+long_option("stack-trace-higher-order",	stack_trace_higher_order).
 long_option("generate-bytecode",	generate_bytecode).
 long_option("generate-prolog",		generate_prolog).
 long_option("generate-Prolog",		generate_prolog).
@@ -1411,6 +1414,10 @@
 		"\tDo not generate code to trace REDO events.",
 		"--trace-optimized",
 		"\tDo not disable optimizations that can change the trace.",
+		"--stack-trace-higher-order",
+		"\tEnable stack traces through predicates and functions with",
+		"\thigher-order arguments, even if stack tracing is not",
+		"\tsupported in general.",
 		"--generate-bytecode",
 		"\tOutput a bytecode form of the module for use",
 		"\tby an experimental debugger.",
Index: compiler/pragma_c_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/pragma_c_gen.m,v
retrieving revision 1.20
diff -u -u -r1.20 pragma_c_gen.m
--- pragma_c_gen.m	1998/08/12 02:39:56	1.20
+++ pragma_c_gen.m	1998/10/30 06:18:50
@@ -531,7 +531,7 @@
 		StructName) },
 	{ SaveStructDecl = pragma_c_struct_ptr_decl(StructName, "LOCALS") },
 	{ string__format("\tLOCALS = (struct %s *) (
-		(char *) (curfr - MR_ORDINARY_SLOTS - NONDET_FIXED_SIZE)
+		(char *) (curfr - MR_ORDINARY_SLOTS - MR_NONDET_FIXED_SIZE)
 		- sizeof(struct %s));\n",
 		[s(StructName), s(StructName)],
 		InitSaveStruct) },
Index: compiler/stack_layout.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/stack_layout.m,v
retrieving revision 1.21
diff -u -u -r1.21 stack_layout.m
--- stack_layout.m	1998/10/28 05:23:40	1.21
+++ stack_layout.m	1998/10/30 07:33:34
@@ -232,9 +232,10 @@
 stack_layout__construct_layouts(ProcLayoutInfo) -->
 	{ ProcLayoutInfo = proc_layout_info(EntryLabel, Detism,
 		StackSlots, SuccipLoc, MaybeCallLabel, MaybeFromFullSlot,
-		InternalMap) },
+		ForceProcIdLayout, InternalMap) },
 	stack_layout__construct_proc_layout(EntryLabel, Detism,
-		StackSlots, SuccipLoc, MaybeCallLabel, MaybeFromFullSlot),
+		StackSlots, SuccipLoc, MaybeCallLabel, MaybeFromFullSlot,
+		ForceProcIdLayout),
 	{ map__to_assoc_list(InternalMap, Internals) },
 	list__foldl(stack_layout__construct_internal_layout(EntryLabel),
 		Internals).
@@ -243,12 +244,13 @@
 
 	% Construct a procedure-specific layout.
 
-:- pred stack_layout__construct_proc_layout(label::in,
-	determinism::in, int::in, maybe(int)::in, maybe(label)::in,
-	maybe(int)::in, stack_layout_info::in, stack_layout_info::out) is det.
+:- pred stack_layout__construct_proc_layout(label::in, determinism::in,
+	int::in, maybe(int)::in, maybe(label)::in, maybe(int)::in, bool::in,
+	stack_layout_info::in, stack_layout_info::out) is det.
 
 stack_layout__construct_proc_layout(EntryLabel, Detism, StackSlots,
-		MaybeSuccipLoc, MaybeCallLabel, MaybeFromFullSlot) -->
+		MaybeSuccipLoc, MaybeCallLabel, MaybeFromFullSlot,
+		ForceProcIdLayout) -->
 	{
 		MaybeSuccipLoc = yes(Location0)
 	->
@@ -295,22 +297,26 @@
 	{ MaybeRvals0 = [yes(CodeAddrRval), yes(DetismRval),
 		yes(StackSlotsRval), yes(SuccipRval)] },
 
-	stack_layout__get_procid_stack_layout(ProcIdLayout),
-	(
-		{ ProcIdLayout = yes }
+	stack_layout__get_procid_stack_layout(ProcIdLayout0),
+	{ bool__or(ProcIdLayout0, ForceProcIdLayout, ProcIdLayout) },
+	{
+		ProcIdLayout = yes
 	->
-		{ stack_layout__construct_procid_rvals(EntryLabel, IdRvals) },
-		{ list__append(MaybeRvals0, IdRvals, MaybeRvals1) }
+		stack_layout__construct_procid_rvals(EntryLabel, IdRvals),
+		list__append(MaybeRvals0, IdRvals, MaybeRvals1)
 	;
-		{ NoIdRvals = yes(const(int_const(-1))) },
-		{ list__append(MaybeRvals0, [NoIdRvals], MaybeRvals1) }
-	),
+		% Indicate the absence of the procedure id fields.
+		NoIdRvals = yes(const(int_const(-1))),
+		list__append(MaybeRvals0, [NoIdRvals], MaybeRvals1)
+	},
 
 	stack_layout__get_module_name(ModuleName),
 	stack_layout__get_trace_stack_layout(TraceLayout),
 	{
 		TraceLayout = yes
 	->
+		require(unify(ProcIdLayout, yes),
+			"trace_layout is set but proc_id_layout is not"),
 		( MaybeCallLabel = yes(CallLabel) ->
 			CallRval = yes(const(data_addr_const(
 					data_addr(ModuleName,
@@ -326,8 +332,15 @@
 		list__append(MaybeRvals1, [CallRval, FromFullRval],
 			MaybeRvals)
 	;
+		ProcIdLayout = yes
+	->
+		% Indicate the absence of the trace layout fields.
 		NoCallRval = yes(const(int_const(0))),
 		list__append(MaybeRvals1, [NoCallRval], MaybeRvals)
+	;
+		% The absence of the procedure id fields implies
+		% the absence of the trace layout fields as well.
+		MaybeRvals = MaybeRvals1
 	},
 
 	{ Exported = no },	% XXX With the new profiler, we will need to
cvs diff: Diffing compiler/notes
cvs diff: Diffing doc
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.139
diff -u -u -r1.139 user_guide.texi
--- user_guide.texi	1998/10/30 05:11:31	1.139
+++ user_guide.texi	1998/11/01 07:38:17
@@ -1786,6 +1786,11 @@
 @item --trace-optimized
 Do not disable optimizations that can change the trace.
 
+ at item --stack-trace-higher-order
+Enable stack traces through predicates and functions with
+higher-order arguments, even if stack tracing is not
+supported in general.
+
 @item --generate-bytecode
 @c Output a bytecode version of the module
 @c into the @file{@var{module}.bytecode} file,
cvs diff: Diffing extras
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/exceptions
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing library
Index: library/array.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/array.m,v
retrieving revision 1.49
diff -u -u -r1.49 array.m
--- array.m	1998/09/04 11:26:04	1.49
+++ array.m	1998/10/30 05:27:37
@@ -263,9 +263,15 @@
 Define_extern_entry(mercury____Unify___array__array_1_0);
 Define_extern_entry(mercury____Index___array__array_1_0);
 Define_extern_entry(mercury____Compare___array__array_1_0);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Unify___array__array_1_0);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Index___array__array_1_0);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Compare___array__array_1_0);
+MR_MAKE_PROC_LAYOUT(mercury____Unify___array__array_1_0,
+	MR_DETISM_SEMI, -1, MR_LVAL_TYPE_UNKNOWN,
+	MR_PREDICATE, ""array"", ""unify_array"", 2, 0);
+MR_MAKE_PROC_LAYOUT(mercury____Index___array__array_1_0,
+	MR_DETISM_DET, -1, MR_LVAL_TYPE_UNKNOWN,
+	MR_PREDICATE, ""array"", ""index_array"", 2, 0);
+MR_MAKE_PROC_LAYOUT(mercury____Compare___array__array_1_0,
+	MR_DETISM_DET, -1, MR_LVAL_TYPE_UNKNOWN,
+	MR_PREDICATE, ""array"", ""compare_array"", 3, 0);
 
 #ifdef  USE_TYPE_LAYOUT
 
Index: library/benchmarking.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/benchmarking.m,v
retrieving revision 1.17
diff -u -u -r1.17 benchmarking.m
--- benchmarking.m	1998/10/30 05:11:46	1.17
+++ benchmarking.m	1998/10/30 07:39:40
@@ -565,13 +565,21 @@
   #define	time_output	r7
 #endif
 
+#ifdef MR_USE_TRAIL
+  #define BENCHMARK_NONDET_STACK_SLOTS 7
+#else
+  #define BENCHMARK_NONDET_STACK_SLOTS 6
+#endif
+
 Define_extern_entry(mercury__benchmarking__benchmark_nondet_5_0);
 Declare_label(mercury__benchmarking__benchmark_nondet_5_0_i1);
 Declare_label(mercury__benchmarking__benchmark_nondet_5_0_i2);
 
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__benchmarking__benchmark_nondet_5_0);
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__benchmarking__benchmark_nondet_5_0, 1);
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__benchmarking__benchmark_nondet_5_0, 2);
+MR_MAKE_PROC_LAYOUT(mercury__benchmarking__benchmark_nondet_5_0,
+	MR_DETISM_NON, BENCHMARK_NONDET_STACK_SLOTS, MR_LVAL_TYPE_UNKNOWN,
+	MR_PREDICATE, ""benchmarking"", ""benchmark_nondet"", 5, 0);
+MR_MAKE_INTERNAL_LAYOUT(mercury__benchmarking__benchmark_nondet_5_0, 1);
+MR_MAKE_INTERNAL_LAYOUT(mercury__benchmarking__benchmark_nondet_5_0, 2);
 
 Declare_entry(do_call_nondet_closure);
 Declare_entry(do_call_det_closure);
@@ -598,14 +606,8 @@
 	** We must make that the closure is called at least once,
 	** otherwise the count we return isn't valid.
 	*/
-
-#ifdef MR_USE_TRAIL
-  #define NONDET_STACK_SLOTS 7
-#else
-  #define NONDET_STACK_SLOTS 6
-#endif
 
-	mkframe(""benchmark_nondet"", NONDET_STACK_SLOTS,
+	mkframe(""benchmark_nondet"", BENCHMARK_NONDET_STACK_SLOTS,
 		LABEL(mercury__benchmarking__benchmark_nondet_5_0_i2));
 
 	framevar(0) = r3;
@@ -674,14 +676,22 @@
 	time_output = MR_get_user_cpu_miliseconds() - framevar(4);
 	succeed_discard();
 
-#undef NONDET_STACK_SLOTS
-
 END_MODULE
 
+#undef BENCHMARK_NONDET_STACK_SLOTS
+
+#ifdef MR_USE_TRAIL
+  #define BENCHMARK_DET_STACK_SLOTS	7
+#else
+  #define BENCHMARK_DET_STACK_SLOTS	6
+#endif
+
 Define_extern_entry(mercury__benchmarking__benchmark_det_5_0);
 Declare_label(mercury__benchmarking__benchmark_det_5_0_i1);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__benchmarking__benchmark_det_5_0);
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__benchmarking__benchmark_det_5_0, 1);
+MR_MAKE_PROC_LAYOUT(mercury__benchmarking__benchmark_det_5_0,
+	MR_DETISM_NON, BENCHMARK_DET_STACK_SLOTS, MR_LIVE_LVAL_STACKVAR(6),
+	MR_PREDICATE, ""benchmarking"", ""benchmark_nondet"", 5, 0);
+MR_MAKE_INTERNAL_LAYOUT(mercury__benchmarking__benchmark_det_5_0, 1);
 
 BEGIN_MODULE(benchmark_det_module)
 	init_entry_sl(mercury__benchmarking__benchmark_det_5_0);
@@ -704,14 +714,8 @@
 	** We must make that the closure is called at least once,
 	** otherwise the count we return isn't valid.
 	*/
-
-#ifdef MR_USE_TRAIL
-  #define DET_STACK_SLOTS 7
-#else
-  #define DET_STACK_SLOTS 6
-#endif
 
-	incr_sp(DET_STACK_SLOTS);
+	incr_sp(BENCHMARK_DET_STACK_SLOTS);
 #ifdef MR_USE_TRAIL
 	detstackvar(7) = MR_trail_ptr;
 #endif
@@ -767,12 +771,12 @@
 	soln_output = r1; /* the closure *always* returns its output in r1 */
 	time_output = MR_get_user_cpu_miliseconds() - detstackvar(4);
 	succip = (Word *) detstackvar(6);
-	decr_sp(DET_STACK_SLOTS);
+	decr_sp(BENCHMARK_DET_STACK_SLOTS);
 	proceed();
 
-#undef DET_STACK_SLOTS
-
 END_MODULE
+
+#undef BENCHMARK_DET_STACK_SLOTS
 
 void mercury_benchmarking_init_benchmark(void); /* suppress gcc warning */
 void mercury_benchmarking_init_benchmark(void) {
Index: library/builtin.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/builtin.m,v
retrieving revision 1.6
diff -u -u -r1.6 builtin.m
--- builtin.m	1998/09/04 11:26:05	1.6
+++ builtin.m	1998/11/01 08:33:46
@@ -517,8 +517,6 @@
 :- pragma c_code("
 Define_extern_entry(mercury__copy_2_0);
 Define_extern_entry(mercury__copy_2_1);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__copy_2_0);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__copy_2_1);
 
 BEGIN_MODULE(copy_module)
 	init_entry(mercury__copy_2_0);
@@ -602,9 +600,6 @@
 Define_extern_entry(mercury____Unify___builtin__c_pointer_0_0);
 Define_extern_entry(mercury____Index___builtin__c_pointer_0_0);
 Define_extern_entry(mercury____Compare___builtin__c_pointer_0_0);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Unify___builtin__c_pointer_0_0);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Index___builtin__c_pointer_0_0);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Compare___builtin__c_pointer_0_0);
 
 BEGIN_MODULE(unify_c_pointer_module)
 	init_entry(mercury____Unify___builtin__c_pointer_0_0);
Index: library/list.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/list.m,v
retrieving revision 1.85
diff -u -u -r1.85 list.m
--- list.m	1998/09/15 07:38:31	1.85
+++ list.m	1998/11/01 05:55:39
@@ -432,6 +432,14 @@
 :- pred list__filter_map(pred(X, Y), list(X), list(Y), list(X)).
 :- mode list__filter_map(pred(in, out) is semidet, in, out, out) is det.
 
+	% list__filter_any(Pred, List) takes a closure with one input argument
+	% and for each member of List `X', calls the closure. If call(Pred, X)
+	% succeeds for any member of List, list__filter_any succeeds
+	% immediately. If call(Pred, X) fails on all members of the list,
+	% list__filter_any fails.
+:- pred list__filter_any(pred(X), list(X)).
+:- mode list__filter_any(pred(in) is semidet, in) is semidet.
+
 	% list__takewhile(Predicate, List, UptoList, AfterList) takes a
 	% closure with one input argument, and calls it on successive members
 	% of List as long as the calls succeed. The elements for which
@@ -1022,6 +1030,13 @@
 		M = [H0|M1]
         ),
         list__filter_map(P, T0, L1, M1).
+
+list__filter_any(P, [H|T]) :-
+	( call(P, H) ->
+		true
+	;
+		list__filter_any(P, T)
+	).
 
 list__takewhile(_, [], [], []).
 list__takewhile(P, [X|Xs], Ins, Outs) :-
Index: library/private_builtin.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/private_builtin.m,v
retrieving revision 1.10
diff -u -u -r1.10 private_builtin.m
--- private_builtin.m	1998/10/30 05:11:55	1.10
+++ private_builtin.m	1998/10/30 07:39:49
@@ -853,7 +853,9 @@
 ** fail; the code to return the answers is in table_resume.
 */ 
 Define_extern_entry(mercury__table_suspend_2_0);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__table_suspend_2_0);
+MR_MAKE_PROC_LAYOUT(mercury__table_suspend_2_0,
+	MR_DETISM_NON, 0, MR_LVAL_TYPE_UNKNOWN,
+	MR_PREDICATE, ""private_builtin"", ""table_suspend"", 2, 0);
 BEGIN_MODULE(table_suspend_module)
 	init_entry_sl(mercury__table_suspend_2_0);
 BEGIN_CODE
@@ -1023,20 +1025,22 @@
 Declare_label(mercury__table_resume_1_0_AnsListLoopDone2);
 Declare_label(mercury__table_resume_1_0_RedoPoint);
 
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__table_resume_1_0);
-MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(
+MR_MAKE_PROC_LAYOUT(mercury__table_resume_1_0,
+	MR_DETISM_NON, -1, MR_LVAL_TYPE_UNKNOWN,
+	MR_PREDICATE, ""private_builtin"", ""table_resume"", 1, 0);
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
 	mercury__table_resume_1_0_ChangeLoop, mercury__table_resume_1_0);
-MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
 	mercury__table_resume_1_0_ChangeLoopDone, mercury__table_resume_1_0);
-MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
 	mercury__table_resume_1_0_SolutionsListLoop, mercury__table_resume_1_0);
-MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
 	mercury__table_resume_1_0_AnsListLoop, mercury__table_resume_1_0);
-MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
 	mercury__table_resume_1_0_AnsListLoopDone1, mercury__table_resume_1_0);
-MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
 	mercury__table_resume_1_0_AnsListLoopDone2, mercury__table_resume_1_0);
-MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(
+MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(
 	mercury__table_resume_1_0_RedoPoint, mercury__table_resume_1_0);
 
 BEGIN_MODULE(table_resume_module)
Index: library/std_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/std_util.m,v
retrieving revision 1.131
diff -u -u -r1.131 std_util.m
--- std_util.m	1998/10/30 05:11:56	1.131
+++ std_util.m	1998/10/30 07:39:53
@@ -489,23 +489,36 @@
 Declare_label(mercury__std_util__builtin_aggregate_4_0_i1);
 Declare_label(mercury__std_util__builtin_aggregate_4_0_i2);
 Declare_label(mercury__std_util__builtin_aggregate_4_0_i3);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__std_util__builtin_aggregate_4_0);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__std_util__builtin_aggregate_4_1);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__std_util__builtin_aggregate_4_2);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__std_util__builtin_aggregate_4_3);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__std_util__builtin_aggregate_4_4);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__std_util__builtin_aggregate_4_5);
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__std_util__builtin_aggregate_4_0, 1);
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__std_util__builtin_aggregate_4_0, 2);
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__std_util__builtin_aggregate_4_0, 3);
 
+#ifndef CONSERVATIVE_GC
+  #ifdef MR_USE_TRAIL
+    #define num_framevars		7
+  #else
+    #define num_framevars		6
+  #endif
+#else
+  #ifdef MR_USE_TRAIL
+    #define num_framevars		3
+  #else
+    #define num_framevars		2
+  #endif
+#endif
+
+MR_MAKE_PROC_LAYOUT(mercury__std_util__builtin_aggregate_4_0,
+	MR_DETISM_MULTI, num_framevars, -1,
+	MR_PREDICATE, ""std_util"", ""builtin_aggregate"", 4, 0);
+
+MR_MAKE_INTERNAL_LAYOUT(mercury__std_util__builtin_aggregate_4_0, 1);
+MR_MAKE_INTERNAL_LAYOUT(mercury__std_util__builtin_aggregate_4_0, 2);
+MR_MAKE_INTERNAL_LAYOUT(mercury__std_util__builtin_aggregate_4_0, 3);
+
 BEGIN_MODULE(builtin_aggregate_module)
 	init_entry_sl(mercury__std_util__builtin_aggregate_4_0);
-	init_entry_sl(mercury__std_util__builtin_aggregate_4_1);
-	init_entry_sl(mercury__std_util__builtin_aggregate_4_2);
-	init_entry_sl(mercury__std_util__builtin_aggregate_4_3);
-	init_entry_sl(mercury__std_util__builtin_aggregate_4_4);
-	init_entry_sl(mercury__std_util__builtin_aggregate_4_5);
+	init_entry(mercury__std_util__builtin_aggregate_4_1);
+	init_entry(mercury__std_util__builtin_aggregate_4_2);
+	init_entry(mercury__std_util__builtin_aggregate_4_3);
+	init_entry(mercury__std_util__builtin_aggregate_4_4);
+	init_entry(mercury__std_util__builtin_aggregate_4_5);
 	init_label_sl(mercury__std_util__builtin_aggregate_4_0_i1);
 	init_label_sl(mercury__std_util__builtin_aggregate_4_0_i2);
 	init_label_sl(mercury__std_util__builtin_aggregate_4_0_i3);
@@ -521,7 +534,7 @@
 ** the address of the respective deep copy routines).
 **
 ** The type_info structures will be in r1 and r2, the closures will be in
-** r3 and r4, and the 'initial value' will be in r5, with both caling
+** r3 and r4, and the 'initial value' will be in r5, with both calling
 ** conventions. The output should go either in r6 (for the normal parameter
 ** convention) or r1 (for the compact parameter convention).
 */
@@ -566,7 +579,7 @@
 /*
 ** In order to implement any sort of code that requires terms to survive
 ** backtracking, we need to (deeply) copy them out of the heap and into some
-** other area before backtracking.  The obious thing to do then is just call
+** other area before backtracking.  The obvious thing to do then is just call
 ** the generator predicate, let it run to completion, and copy its result into
 ** another memory area (call it the solutions heap) before forcing
 ** backtracking.  When we get the next solution, we do the same, this time
@@ -624,17 +637,15 @@
 ** Finally, we store the collection of solutions so far in sofar_fv.
 */
 
-#define saved_hp_fv		(framevar(0))
-#define saved_solhp_fv		(framevar(1))
-#define collector_pred_fv	(framevar(2))
-#define sofar_fv		(framevar(3))
-#define element_type_info_fv	(framevar(4))
-#define collection_type_info_fv	(framevar(5))
+/* This must be kept in sync with the definition of num_framevars above. */
+#define saved_hp_fv		(MR_framevar(1))
+#define saved_solhp_fv		(MR_framevar(2))
+#define collector_pred_fv	(MR_framevar(3))
+#define sofar_fv		(MR_framevar(4))
+#define element_type_info_fv	(MR_framevar(5))
+#define collection_type_info_fv	(MR_framevar(6))
 #ifdef MR_USE_TRAIL
-  #define saved_trail_ticket_fv	(framevar(6))
-  #define num_framevars		7
-#else
-  #define num_framevars		6
+  #define saved_trail_ticket_fv	(MR_framevar(7))
 #endif
 
 	/*
@@ -771,7 +782,6 @@
 #undef sofar_fv
 #undef element_type_info_fv
 #undef collection_type_info_fv
-#undef num_framevars
 
 #else
 
@@ -783,13 +793,11 @@
 ** make deep copies of the solutions.  This is a `copy-zero' implementation ;-)
 */
 
-#define collector_pred_fv	(framevar(0))
-#define sofar_fv		(framevar(1))
+/* This must be kept in sync with the definition of num_framevars above. */
+#define collector_pred_fv	(MR_framevar(1))
+#define sofar_fv		(MR_framevar(2))
 #ifdef MR_USE_TRAIL
-  #define saved_trail_ticket_fv	(framevar(2))
-  #define num_framevars		3
-#else
-  #define num_framevars		2
+  #define saved_trail_ticket_fv	(MR_framevar(3))
 #endif
 
 	/* create a nondet stack frame with two slots, to hold the collector
@@ -871,15 +879,15 @@
  
 #undef collector_pred_fv
 #undef sofar_fv
-#undef num_framevars
 
 #endif
- 
+
+END_MODULE
+
+#undef num_framevars
 #undef builtin_aggregate_output
 #undef swap_heap_and_solutions_heap
 
-END_MODULE
- 
 /* Ensure that the initialization code for the above module gets run. */
 /*
 INIT sys_init_builtin_aggregate_module
@@ -1084,17 +1092,29 @@
 Define_extern_entry(mercury____Index___std_util__univ_0_0);
 Define_extern_entry(mercury____Compare___std_util__univ_0_0);
 Declare_label(mercury____Compare___std_util__univ_0_0_i1);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Unify___std_util__univ_0_0);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Index___std_util__univ_0_0);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Compare___std_util__univ_0_0);
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury____Compare___std_util__univ_0_0, 1);
+MR_MAKE_PROC_LAYOUT(mercury____Unify___std_util__univ_0_0,
+	MR_DETISM_SEMI, -1, MR_LVAL_TYPE_UNKNOWN,
+	MR_PREDICATE, ""std_util"", ""unify_univ"", 2, 0);
+MR_MAKE_PROC_LAYOUT(mercury____Index___std_util__univ_0_0,
+	MR_DETISM_DET, -1, MR_LVAL_TYPE_UNKNOWN,
+	MR_PREDICATE, ""std_util"", ""index_univ"", 2, 0);
+MR_MAKE_PROC_LAYOUT(mercury____Compare___std_util__univ_0_0,
+	MR_DETISM_DET, -1, MR_LVAL_TYPE_UNKNOWN,
+	MR_PREDICATE, ""std_util"", ""compare_univ"", 3, 0);
+MR_MAKE_INTERNAL_LAYOUT(mercury____Compare___std_util__univ_0_0, 1);
 
 Define_extern_entry(mercury____Unify___std_util__type_info_0_0);
 Define_extern_entry(mercury____Index___std_util__type_info_0_0);
 Define_extern_entry(mercury____Compare___std_util__type_info_0_0);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Unify___std_util__type_info_0_0);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Index___std_util__type_info_0_0);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Compare___std_util__type_info_0_0);
+MR_MAKE_PROC_LAYOUT(mercury____Unify___std_util__type_info_0_0,
+	MR_DETISM_SEMI, -1, MR_LVAL_TYPE_UNKNOWN,
+	MR_PREDICATE, ""std_util"", ""unify_type_info"", 2, 0);
+MR_MAKE_PROC_LAYOUT(mercury____Index___std_util__type_info_0_0,
+	MR_DETISM_DET, -1, MR_LVAL_TYPE_UNKNOWN,
+	MR_PREDICATE, ""std_util"", ""index_type_info"", 2, 0);
+MR_MAKE_PROC_LAYOUT(mercury____Compare___std_util__type_info_0_0,
+	MR_DETISM_DET, -1, MR_LVAL_TYPE_UNKNOWN,
+	MR_PREDICATE, ""std_util"", ""compare_type_info"", 3, 0);
 
 BEGIN_MODULE(unify_univ_module)
 	init_entry_sl(mercury____Unify___std_util__univ_0_0);
Index: library/string.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/string.m,v
retrieving revision 1.107
diff -u -u -r1.107 string.m
--- string.m	1998/10/27 15:36:35	1.107
+++ string.m	1998/10/30 06:36:20
@@ -1754,105 +1754,42 @@
 	strcpy(S3 + len_1, S2);
 }").
 
-:- pragma c_code("
-
-#ifdef	COMPACT_ARGS
-#define	string__append_ooi_input_reg	r1
-#else
-#define	string__append_ooi_input_reg	r3
-#endif
-
-Define_extern_entry(mercury__string__append_3_3_xx);
-Declare_label(mercury__string__append_3_3_xx_i1);
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__string__append_3_3_xx);
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__string__append_3_3_xx, 1);
-
-BEGIN_MODULE(string_append_module)
-	init_entry(mercury__string__append_3_3_xx);
-	init_label(mercury__string__append_3_3_xx_i1);
-BEGIN_CODE
-Define_entry(mercury__string__append_3_3_xx);
-	mkframe(""string__append/3"", 4,
-		LABEL(mercury__string__append_3_3_xx_i1));
-	mark_hp(framevar(0));
-	framevar(1) = string__append_ooi_input_reg;
-	framevar(2) = strlen((char *) string__append_ooi_input_reg);
-	framevar(3) = 0;
-Define_label(mercury__string__append_3_3_xx_i1);
-	update_prof_current_proc(LABEL(mercury__string__append_3_3_xx));
-{
-	String	s3;
-	size_t	s3_len;
-	size_t	count;
-
-	restore_hp(framevar(0));
-	s3 = (String) framevar(1);
-	s3_len = framevar(2);
-	count = framevar(3);
-	if (count > s3_len) {
-		/* modframe(ENTRY(do_fail)); */
-		fail();
-	}
-	incr_hp_atomic(r1, (count + sizeof(Word)) / sizeof(Word));
-	memcpy((char *) r1, s3, count);
-	((char *) r1)[count] = '\\0';
-	/*
-	** We need to make a copy to ensure that the pointer is
-	** word-aligned.
-	*/
-	incr_hp_atomic(r2, (s3_len - count + sizeof(Word)) / sizeof(Word));
-	strcpy((char *) r2, s3 + count);
-	framevar(3) = count + 1;
-	succeed();
-}
-END_MODULE
-
-#undef	string__append_ooi_input_reg
-
-/* Ensure that the initialization code for the above module gets run. */
-/*
-INIT sys_init_string_append_module
-*/
-/* suppress gcc -Wmissing-decl warning */
-void sys_init_string_append_module(void);
-
-void sys_init_string_append_module(void) {
-	extern ModuleFunc string_append_module;
-	string_append_module();
-}
-
-").
-
-% :- mode string__append(out, out, in) is multidet.
 :- pragma c_code(string__append(S1::out, S2::out, S3::in),
-		[will_not_call_mercury, thread_safe], "
-	/*
-	** The pragma_c_code will generate a mkframe();
-	** we need to pop off that frame before jumping to the hand-coded
-	** fragment above.
-	**
-	** We mention S1, S2 and S3 here to shut up a warning.
-	*/
-
-	maxfr = curprevfr;
-	curfr = cursuccfr;
-	{
-		/*
-		** We need to use `tailcall' to get the profiling
-		** information right.  The caller is guaranteed
-		** to be string__append_3_3 only because we
-		** have a `pragma no_inline' declaration for
-		** string__append.
-		*/
-		Declare_entry(mercury__string__append_3_3_xx);
-		tailcall(ENTRY(mercury__string__append_3_3_xx),
-			LABEL(mercury__string__append_3_3));
+		[will_not_call_mercury, thread_safe],
+	local_vars("
+		String s;
+		size_t len;
+		size_t count;
+	"),
+	first_code("
+		LOCALS->s = S3;
+		LOCALS->len = strlen(S3);
+		LOCALS->count = 0;
+	"),
+	retry_code("
+		LOCALS->count++;
+	"),
+	common_code("
+		Word	temp;
+
+		incr_hp_atomic(temp,
+			(LOCALS->count + sizeof(Word)) / sizeof(Word));
+		S1 = (String) temp;
+		memcpy(S1, LOCALS->s, LOCALS->count);
+		S1[LOCALS->count] = '\\0';
+		incr_hp_atomic(temp,
+			(LOCALS->len - LOCALS->count + sizeof(Word))
+			/ sizeof(Word));
+		S2 = (String) temp;
+		strcpy(S2, LOCALS->s + LOCALS->count);
+
+	if (LOCALS->count < LOCALS->len) {
+		SUCCEED;
+	} else {
+		SUCCEED_LAST;
 	}
-").
-
-% The following is required to ensure that the caller label
-% in the above hand-coded C is correct.
-:- pragma no_inline(string__append/3).
+	")
+).
 
 /*-----------------------------------------------------------------------*/
 
cvs diff: Diffing lp_solve
cvs diff: Diffing lp_solve/lp_examples
cvs diff: Diffing profiler
cvs diff: Diffing runtime
Index: runtime/mercury_bootstrap.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_bootstrap.c,v
retrieving revision 1.4
diff -u -u -r1.4 mercury_bootstrap.c
--- mercury_bootstrap.c	1998/08/06 07:59:07	1.4
+++ mercury_bootstrap.c	1998/10/30 08:56:38
@@ -78,10 +78,16 @@
 	MR_TYPEFUNCTORS_SPECIAL
 };
 
+MR_MAKE_PROC_LAYOUT(mercury____Unify___private_builtin__type_info_1_0,
+	MR_DETISM_SEMI, -1, MR_LVAL_TYPE_UNKNOWN,
+	MR_PREDICATE, "builtin", "unify_type_info", 2, 0);
+MR_MAKE_PROC_LAYOUT(mercury____Index___private_builtin__type_info_1_0,
+	MR_DETISM_DET, -1, MR_LVAL_TYPE_UNKNOWN,
+	MR_PREDICATE, "builtin", "index_type_info", 2, 0);
+MR_MAKE_PROC_LAYOUT(mercury____Compare___private_builtin__type_info_1_0,
+	MR_DETISM_DET, -1, MR_LVAL_TYPE_UNKNOWN,
+	MR_PREDICATE, "builtin", "compare_type_info", 3, 0);
 
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Unify___private_builtin__type_info_1_0)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Index___private_builtin__type_info_1_0)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury____Compare___private_builtin__type_info_1_0)
 BEGIN_MODULE(type_info_module)
 	init_entry_sl(mercury____Unify___private_builtin__type_info_1_0);
 	init_entry_sl(mercury____Index___private_builtin__type_info_1_0);
Index: runtime/mercury_conf_param.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf_param.h,v
retrieving revision 1.12
diff -u -u -r1.12 mercury_conf_param.h
--- mercury_conf_param.h	1998/10/16 06:18:46	1.12
+++ mercury_conf_param.h	1998/10/30 09:16:06
@@ -95,13 +95,6 @@
 **	and the debugger to print stack traces. This effect is achieved by
 **	including MR_STACK_TRACE in the mangled grade (see mercury_grade.h).
 **
-** MR_STACK_TRACE_THIS_MODULE
-**	Include the layout information needed by error/1 and the debugger
-**	to print stack traces. Unlike MR_STACK_TRACE, this does not affect
-**	the mangled grade, so it can be specified on a module-by-module basis.
-**	(When a stack trace encounters a stack frame created by code from a
-**	module which does not have layout information, the trace stops.)
-**
 ** MR_REQUIRE_TRACING
 **	Require that all Mercury procedures linked in should be compiled
 **	with at least interface tracing.  This effect is achieved
@@ -229,17 +222,6 @@
 #endif
 
 /*
-** MR_USE_STACK_LAYOUTS -- stack layouts are in use, generate stack
-**                         layout structures.
-*/
-#ifdef MR_USE_STACK_LAYOUTS
-  #error "MR_USE_STACK_LAYOUTS should not be defined on the command line"
-#endif
-#if (defined(MR_STACK_TRACE) || defined(NATIVE_GC) || defined(MR_STACK_TRACE_THIS_MODULE)) && defined(MR_STATIC_CODE_ADDRESSES)
-  #define MR_USE_STACK_LAYOUTS
-#endif
-
-/*
 ** MR_INSERT_LABELS     -- labels need to be inserted into the label table. 
 **			   (this also means the initialization code needs
 **			   to be run some time before the first use of the
@@ -248,7 +230,7 @@
 #ifdef MR_INSERT_LABELS
   #error "MR_INSERT_LABELS should not be defined on the command line"
 #endif
-#if defined(MR_STACK_TRACE) || defined(NATIVE_GC) || defined(MR_DEBUG_GOTOS) || defined(MR_STACK_TRACE_THIS_MODULE)
+#if defined(MR_STACK_TRACE) || defined(NATIVE_GC) || defined(MR_DEBUG_GOTOS)
   #define MR_INSERT_LABELS
 #endif
 
Index: runtime/mercury_engine.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_engine.c,v
retrieving revision 1.14
diff -u -u -r1.14 mercury_engine.c
--- mercury_engine.c	1998/08/24 08:24:38	1.14
+++ mercury_engine.c	1998/10/30 09:14:38
@@ -8,7 +8,6 @@
 ** Public License - see the file COPYING.LIB in the Mercury distribution.
 */
 
-#define		MR_STACK_TRACE_THIS_MODULE
 #include	"mercury_imp.h"
 
 #include	<stdio.h>
@@ -34,7 +33,6 @@
 #ifndef USE_GCC_NONLOCAL_GOTOS
   static Code	*engine_done(void);
   static Code	*engine_init_registers(void);
-  MR_MAKE_STACK_LAYOUT_ENTRY(engine_done)
 #endif
 
 bool	MR_debugflag[MR_MAXFLAG];
@@ -532,18 +530,12 @@
 Define_extern_entry(do_last_succeed);
 Define_extern_entry(do_not_reached);
 
-MR_MAKE_STACK_LAYOUT_ENTRY(do_redo)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_fail)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_succeed)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_last_succeed)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_not_reached)
-
 BEGIN_MODULE(special_labels_module)
-	init_entry(do_redo);
-	init_entry(do_fail);
-	init_entry(do_succeed);
-	init_entry(do_last_succeed);
-	init_entry(do_not_reached);
+	init_entry_ai(do_redo);
+	init_entry_ai(do_fail);
+	init_entry_ai(do_succeed);
+	init_entry_ai(do_last_succeed);
+	init_entry_ai(do_not_reached);
 BEGIN_CODE
 
 Define_entry(do_redo);
Index: runtime/mercury_goto.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_goto.h,v
retrieving revision 1.15
diff -u -u -r1.15 mercury_goto.h
--- mercury_goto.h	1998/10/02 05:35:54	1.15
+++ mercury_goto.h	1998/11/01 04:26:49
@@ -19,15 +19,10 @@
 #define entry(label) paste(_entry_,label)
 #define skip(label) paste(skip_,label)
 
-#if defined(MR_USE_STACK_LAYOUTS)
-  #define MR_ENTRY_LAYOUT(label)	(const MR_Stack_Layout_Entry *) (Word) \
-	&(paste(mercury_data__layout__,label))
-  #define MR_INTERNAL_LAYOUT(label)	(const MR_Stack_Layout_Label *) (Word) \
-	&(paste(mercury_data__layout__,label))
-#else
-  #define MR_ENTRY_LAYOUT(label)	(const MR_Stack_Layout_Entry *) NULL
-  #define MR_INTERNAL_LAYOUT(label)	(const MR_Stack_Layout_Label *) NULL
-#endif
+#define MR_ENTRY_LAYOUT(label)		(const MR_Stack_Layout_Entry *) (Word) \
+				&(paste(mercury_data__layout__,label))
+#define MR_INTERNAL_LAYOUT(label)	(const MR_Stack_Layout_Label *) (Word) \
+				&(paste(mercury_data__layout__,label))
 
 /*
 ** Taking the address of a label can inhibit gcc's optimization,
@@ -36,37 +31,40 @@
 ** or if we need the label address for profiling or
 ** accurate garbage collection.
 **
-** The versions of the macros below with the _sl suffix assume that the label
-** that they are applied to has a stack layout record; the versions without
-** do not. This governs whether they try to pass the address of this record
-** to insert_entry().
+** The versions of the macros below with the _ai or _sl suffix always insert
+** the label into the label table, the difference between them being that
+** the _ai variant does not include a layout structure. If the label *has*
+** a layout structure, use the _sl variant.
 */
 
+#define make_label_ai(n, a, l)		MR_insert_internal_label(n, a, NULL)
+#define make_label_sl(n, a, l)		MR_insert_internal_label(n, a, \
+						MR_INTERNAL_LAYOUT(l))
+
+#define make_local_ai(n, a, l)		MR_insert_internal_label(n, a, NULL)
+#define make_local_sl(n, a, l)		MR_insert_internal_label(n, a, \
+						MR_INTERNAL_LAYOUT(l))
+
+#define make_entry_ai(n, a, l)		MR_insert_entry_label(n, a, NULL)
+#define make_entry_sl(n, a, l)		MR_insert_entry_label(n, a, \
+						MR_ENTRY_LAYOUT(l))
+
 #if defined(MR_INSERT_LABELS)
-  #define make_label(n, a, l)		MR_insert_internal_label(n, a, NULL)
-  #define make_label_sl(n, a, l)	\
-  		MR_insert_internal_label(n, a, MR_INTERNAL_LAYOUT(l))
+  #define make_label(n, a, l)		make_label_ai(n, a, l)
 #else
   #define make_label(n, a, l)		/* nothing */
-  #define make_label_sl(n, a, l)	/* nothing */
 #endif
 
 #if defined(MR_INSERT_LABELS) || defined(PROFILE_CALLS)
-  #define make_local(n, a, l)		MR_insert_internal_label(n, a, NULL)
-  #define make_local_sl(n, a, l)	\
-  		MR_insert_internal_label(n, a, MR_INTERNAL_LAYOUT(l))
+  #define make_local(n, a, l)		make_local_ai(n, a, l)
 #else 
   #define make_local(n, a, l)		/* nothing */
-  #define make_local_sl(n, a, l)	/* nothing */
 #endif
 
 #if defined(MR_INSERT_LABELS) || defined(PROFILE_CALLS)
-  #define make_entry(n, a, l)		MR_insert_entry_label(n, a, NULL)
-  #define make_entry_sl(n, a, l)	\
-  		MR_insert_entry_label(n, a, MR_ENTRY_LAYOUT(l))
+  #define make_entry(n, a, l)		make_entry_ai(n, a, l)
 #else
   #define make_entry(n, a, l)		/* nothing */
-  #define make_entry_sl(n, a, l)	/* nothing */
 #endif
 
 #ifdef SPLIT_C_FILES
@@ -508,6 +506,9 @@
     #define init_entry(label)	\
 	PRETEND_ADDRESS_IS_USED(&&label); \
 	make_entry(stringify(label), label, label)
+    #define init_entry_ai(label)	\
+	PRETEND_ADDRESS_IS_USED(&&label); \
+	make_entry_ai(stringify(label), label, label)
     #define init_entry_sl(label)	\
 	PRETEND_ADDRESS_IS_USED(&&label); \
 	make_entry_sl(stringify(label), label, label)
@@ -538,6 +539,9 @@
     #define init_entry(label)	\
 	make_entry(stringify(label), &&label, label);	\
 	entry(label) = &&label
+    #define init_entry_ai(label)	\
+	make_entry_ai(stringify(label), &&label, label);	\
+	entry(label) = &&label
     #define init_entry_sl(label)	\
 	make_entry_sl(stringify(label), &&label, label);	\
 	entry(label) = &&label
@@ -557,16 +561,20 @@
 	label:	\
 	{
   #define init_local(label)	make_local(stringify(label), &&label, label)
+  #define init_local_ai(label)	make_local_ai(stringify(label), &&label, label)
   #define init_local_sl(label)	make_local_sl(stringify(label), &&label, label)
   #define Define_label(label)	Define_local(label)
   #define Declare_label(label)	/* no declaration required */
   #ifdef MR_INSERT_LABELS
    #define init_label(label)	\
 	make_label(stringify(label), &&entry(label), label)
+   #define init_label_ai(label)	\
+	make_label_ai(stringify(label), &&entry(label), label)
    #define init_label_sl(label)	\
 	make_label_sl(stringify(label), &&entry(label), label)
   #else
    #define init_label(label)	make_label(stringify(label), &&label, label)
+   #define init_label_ai(label)	make_label_ai(stringify(label), &&label, label)
    #define init_label_sl(label)	make_label_sl(stringify(label), &&label, label)
   #endif
 
@@ -607,6 +615,7 @@
 	}				\
 	static Code* label(void) {
   #define init_entry(label)	make_entry(stringify(label), label, label)
+  #define init_entry_ai(label)	make_entry_ai(stringify(label), label, label)
   #define init_entry_sl(label)	make_entry_sl(stringify(label), label, label)
 
   #define Declare_local(label)	static Code *label(void)
@@ -615,6 +624,7 @@
 	}				\
 	static Code* label(void) {
   #define init_local(label)	make_local(stringify(label), label, label)
+  #define init_local_ai(label)	make_local_ai(stringify(label), label, label)
   #define init_local_sl(label)	make_local_sl(stringify(label), label, label)
 
   #define Declare_label(label)	static Code *label(void)
@@ -623,6 +633,7 @@
 	}				\
 	static Code* label(void) {
   #define init_label(label)	make_label(stringify(label), label, label)
+  #define init_label_ai(label)	make_label_ai(stringify(label), label, label)
   #define init_label_sl(label)	make_label_sl(stringify(label), label, label)
 
   #define ENTRY(label) 		((Code *) (label))
Index: runtime/mercury_ho_call.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_ho_call.c,v
retrieving revision 1.12
diff -u -u -r1.12 mercury_ho_call.c
--- mercury_ho_call.c	1998/09/10 06:53:52	1.12
+++ mercury_ho_call.c	1998/10/30 08:54:16
@@ -67,23 +67,26 @@
 Define_extern_entry(mercury__compare_3_3);
 Declare_label(mercury__compare_3_0_i1);
 
-MR_MAKE_STACK_LAYOUT_ENTRY(do_call_det_closure)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_call_semidet_closure)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_call_nondet_closure)
-
-MR_MAKE_STACK_LAYOUT_ENTRY(do_call_det_class_method)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_call_semidet_class_method)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_call_nondet_class_method)
-
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__unify_2_0)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__index_2_0)
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__index_2_0, 1)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__compare_3_0)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__compare_3_1)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__compare_3_2)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__compare_3_3)
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__compare_3_0, 1)
-
+#ifdef	COMPACT_ARGS
+  /*
+  ** With compact args, all these methods just do some data shuffling
+  ** and then a tailcall. They never have stack frames, and therefore
+  ** do not participate in stack traces.
+  */
+#else
+  /*
+  ** With simple args, some of these procedures make proper calls,
+  ** and thus have stack frames.
+  */
+  MR_MAKE_PROC_LAYOUT(mercury__index_2_0,
+	MR_DETISM_DET, 2, MR_LIVE_LVAL_STACKVAR(2),
+	MR_PREDICATE, ""builtin"", ""index"", 2, 0);
+  MR_MAKE_INTERNAL_LAYOUT(mercury__index_2_0, 1);
+  MR_MAKE_PROC_LAYOUT(mercury__compare_3_0,
+	MR_DETISM_DET, 2, MR_LIVE_LVAL_STACKVAR(2),
+	MR_PREDICATE, ""builtin"", ""compare"", 3, 0);
+  MR_MAKE_INTERNAL_LAYOUT(mercury__compare_3_0, 1);
+#endif
 
 BEGIN_MODULE(call_module)
 	init_entry(do_call_det_closure);
@@ -95,13 +98,23 @@
 	init_entry(do_call_nondet_class_method);
 
 	init_entry(mercury__unify_2_0);
+#ifdef	COMPACT_ARGS
 	init_entry(mercury__index_2_0);
-	init_label_sl(mercury__index_2_0_i1);
+	init_label(mercury__index_2_0_i1);
 	init_entry(mercury__compare_3_0);
+#else
+	init_entry_sl(mercury__index_2_0);
+	init_label_sl(mercury__index_2_0_i1);
+	init_entry_sl(mercury__compare_3_0);
+#endif
 	init_entry(mercury__compare_3_1);
 	init_entry(mercury__compare_3_2);
 	init_entry(mercury__compare_3_3);
+#ifdef	COMPACT_ARGS
+	init_label(mercury__compare_3_0_i1);
+#else
 	init_label_sl(mercury__compare_3_0_i1);
+#endif
 BEGIN_CODE
 
 Define_entry(do_call_det_closure);
@@ -440,27 +453,18 @@
 #ifdef	COMPACT_ARGS
 	tailcall(index_pred, LABEL(mercury__index_2_0));
 #else
-	push(MR_succip);
-	push(type_arity);
+	incr_sp_push_msg(2, "mercury__index_2_0");
+	MR_stackvar(2) = (Word) MR_succip;
+	MR_stackvar(1) = type_arity;
 	call(index_pred, LABEL(mercury__index_2_0_i1), 
 		LABEL(mercury__index_2_0));
-#endif
 }
-/*
-** Since mod2c declares this label, we must define it,
-** even though it is not needed with COMPACT_ARGS.
-*/
 Define_label(mercury__index_2_0_i1);
 {
-#ifdef	COMPACT_ARGS
-	fatal_error("mercury__index_2_0_i1 reached in COMPACT_ARGS mode");
-#else
-	int	type_arity;
-
-	type_arity = pop();
-	MR_succip = (Code *) pop();
+	MR_succip = (Code *) MR_stackvar(2);
 	save_registers();
-	r3 = virtual_reg(type_arity + 2);
+	r3 = virtual_reg(MR_stackvar(1) + 2);
+	decr_sp_pop_msg(2);
 	proceed();
 #endif
 }
@@ -549,27 +553,18 @@
 #ifdef	COMPACT_ARGS
 	tailcall(compare_pred, LABEL(mercury__compare_3_3));
 #else
-	push(MR_succip);
-	push(type_arity);
+	incr_sp_push_msg(2, "mercury__index_2_0");
+	MR_stackvar(2) = (Word) MR_succip;
+	MR_stackvar(1) = type_arity;
 	call(compare_pred, LABEL(mercury__compare_3_0_i1),
 		LABEL(mercury__compare_3_3));
-#endif
 }
-/*
-** Since mod2c declares this label, we must define it,
-** even though it is not needed with COMPACT_ARGS.
-*/
 Define_label(mercury__compare_3_0_i1);
 {
-#ifdef	COMPACT_ARGS
-	fatal_error("mercury__compare_3_0_i1 reached in COMPACT_ARGS mode");
-#else
-	int	type_arity;
-
-	type_arity = pop();
-	MR_succip = (Code *) pop();
+	MR_succip = (Code *) MR_stackvar(2);
 	save_registers();
-	r2 = virtual_reg(type_arity + 1);
+	r2 = virtual_reg(MR_stackvar(1) + 1);
+	decr_sp_pop_msg(2);
 	proceed();
 #endif
 }
Index: runtime/mercury_stack_layout.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_layout.h,v
retrieving revision 1.11
diff -u -u -r1.11 mercury_stack_layout.h
--- mercury_stack_layout.h	1998/10/28 05:24:06	1.11
+++ mercury_stack_layout.h	1998/10/30 05:24:34
@@ -132,6 +132,15 @@
 #define MR_LIVE_LVAL_INDIRECT_BASE_LVAL(LocnNumber)		\
 	(((Word) (LocnNumber)) >> MR_LIVE_LVAL_OFFSETBITS)
 
+#define	MR_LIVE_LVAL_STACKVAR(n)				\
+	((Word) ((n) << MR_LIVE_LVAL_TAGBITS) + MR_LVAL_TYPE_STACKVAR)
+
+#define	MR_LIVE_LVAL_FRAMEVAR(n)				\
+	((Word) ((n) << MR_LIVE_LVAL_TAGBITS) + MR_LVAL_TYPE_FRAMEVAR)
+
+#define	MR_LIVE_LVAL_R_REG(n)					\
+	((Word) ((n) << MR_LIVE_LVAL_TAGBITS) + MR_LVAL_TYPE_R)
+
 /*-------------------------------------------------------------------------*/
 /*
 ** Definitions for MR_Live_Type
@@ -257,18 +266,18 @@
 
 typedef struct MR_Stack_Layout_User_Proc_Struct {
 	MR_PredFunc		MR_user_pred_or_func;
-	String			MR_user_decl_module;
-	String			MR_user_def_module;
-	String			MR_user_name;
+	ConstString		MR_user_decl_module;
+	ConstString		MR_user_def_module;
+	ConstString		MR_user_name;
 	Integer			MR_user_arity;
 	Integer			MR_user_mode;
 } MR_Stack_Layout_User_Proc;
 
 typedef struct MR_Stack_Layout_Compiler_Proc_Struct {
-	String			MR_comp_type_name;
-	String			MR_comp_type_module;
-	String			MR_comp_def_module;
-	String			MR_comp_pred_name;
+	ConstString		MR_comp_type_name;
+	ConstString		MR_comp_type_module;
+	ConstString		MR_comp_def_module;
+	ConstString		MR_comp_pred_name;
 	Integer			MR_comp_arity;
 	Integer			MR_comp_mode;
 } MR_Stack_Layout_Compiler_Proc;
@@ -309,29 +318,37 @@
 		> MR_FUNCTION)
 
 /*
-** Define a stack layout for a label that you know very little about.
-** It is just a generic entry label, no useful information, except
-** the code address for the label.
+** Define a layout structure for a procedure, containing information
+** for the first two groups of fields.
+**
+** The slot count and the succip location parameters do not have to be
+** supplied for procedures that live on the nondet stack.
+**
+** An unknown slot count should be signalled by a -1 for the slots argument.
+** An unknown succip location should be signalled by MR_LVAL_TYPE_UNKNOWN.
+**
+** For the procedure identification, we always use the same module name
+** for the defining and declaring modules, since procedures whose code
+** is hand-written as C modules cannot be inlined in other Mercury modules.
 */ 
 
-#ifdef MR_USE_STACK_LAYOUTS
-  #define MR_MAKE_STACK_LAYOUT_ENTRY(l) 				\
-  const struct mercury_data__layout__##l##_struct {			\
-	Code	*f1;							\
-	Integer	f2;							\
-	Integer	f3;							\
-	Integer	f4;							\
-	Integer	f5;							\
-  } mercury_data__layout__##l = {					\
-	STATIC(l),							\
-	(Integer) -1, 	/* Unknown determinism */			\
-	(Integer) -1,	/* Unknown number of stack slots */		\
-        (Integer) MR_LVAL_TYPE_UNKNOWN,	/* Unknown succip location */	\
-	(Integer) -1, 	/* The procid component is not present */	\
-  };
-#else
-  #define MR_MAKE_STACK_LAYOUT_ENTRY(l)        
-#endif	/* MR_USE_STACK_LAYOUTS */
+#define MR_MAKE_PROC_LAYOUT(entry, detism, slots, succip_locn,		\
+		pf, module, name, arity, mode) 				\
+	MR_Stack_Layout_Entry mercury_data__layout__##entry = {		\
+		STATIC(entry),						\
+		detism,							\
+		slots,							\
+		succip_locn,						\
+		{{							\
+			pf,						\
+			module,						\
+			module,						\
+			name,						\
+			arity,						\
+			mode						\
+		}},							\
+		NULL							\
+	}
 
 /*
 ** In procedures compiled with execution tracing, three items are stored
@@ -400,57 +417,34 @@
 #endif
 
 /*
-** Define a stack layout for an internal label. Need to supply the
-** label name (l) and the entry label name (e).
-**
-** The only useful information in this structure is the code address
-** and the reference to the entry for this label.
-*/ 
-
-#ifdef MR_USE_STACK_LAYOUTS
-  #define MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e)		\
-  const struct mercury_data__layout__##l##_struct {			\
-	const Word *f1;							\
-	UNKNOWN_INTERNAL_LABEL_FIELD					\
-	Integer f3;							\
-  } mercury_data__layout__##l = {					\
-	(const Word *) &mercury_data__layout__##e,			\
-	UNKNOWN_INTERNAL_LABEL_NUMBER					\
-	(Integer) -1		/* No information about live values */	\
-  };
-#else
-  #define MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e)        
-#endif	/* MR_USE_STACK_LAYOUTS */
-
-/*
 ** Define a stack layout for an internal label.
-** Need to supply the label name (l) and the number (x), eg for
-** label_name_i3, x is 3. It is assumed the entry label for that
-** corresponds to this label is the label name without the _iX suffix.
-**
-** (MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY, above, is a little
-** more general than MR_MAKE_STACK_LAYOUT_INTERNAL. This macro can
-** only describe relationships between labels that have the same
-** base -- MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY can create layouts
-** for internal labels no matter what the name of the entry layout is).
+**
+** The MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY variant allows you to specify
+** the label name (l) and the entry label name (e) independently, which
+** means that it can be used for labels in code fragments which are
+** simultaneously part of several procedures. (Some hand-written code
+** in the library is like this; the different procedures usually differ
+** only in attributes such as the uniqueness of their arguments.)
+**
+** The MR_MAKE_INTERNAL_LAYOUT variant assumes that the internal label
+** is in the procedure named by the entry label.
+**
+** The only useful information in the structures created by these macros
+** is the reference to the procedure layout, which allows you to find the
+** stack frame size and the succip location, thereby enabling stack tracing.
 **
-** The only useful information in this structure is the code address
-** and the reference to the entry for this label.
+** For the native garbage collector, we will to add meaningful live value
+** information as well to these macros.
 */ 
 
-#ifdef MR_USE_STACK_LAYOUTS
-  #define MR_MAKE_STACK_LAYOUT_INTERNAL(e, x)				\
-  const struct mercury_data__layout__##e##_i##x##_struct {		\
-	const Word *f1;							\
-	UNKNOWN_INTERNAL_LABEL_FIELD					\
-	Integer f3;							\
-  } mercury_data__layout__##e##_i##x = {				\
-	(const Word *) &mercury_data__layout__##e,			\
-	UNKNOWN_INTERNAL_LABEL_NUMBER					\
-	(Integer) -1		/* No information about live values */	\
-  };
-#else
-  #define MR_MAKE_STACK_LAYOUT_INTERNAL(l, x)        
-#endif	/* MR_USE_STACK_LAYOUTS */
+#define MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(l, e)			\
+	MR_Stack_Layout_Label mercury_data__layout__##l = {		\
+		&mercury_data__layout__##e,				\
+		UNKNOWN_INTERNAL_LABEL_NUMBER				\
+		(Integer) -1	/* No information about live values */	\
+	}
+
+#define MR_MAKE_INTERNAL_LAYOUT(e, n)					\
+	MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(e##_i##n, e)
 
 #endif /* not MERCURY_STACK_LAYOUT_H */
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.20
diff -u -u -r1.20 mercury_stack_trace.c
--- mercury_stack_trace.c	1998/10/30 04:51:07	1.20
+++ mercury_stack_trace.c	1998/11/01 04:25:09
@@ -194,7 +194,7 @@
 
 	label = MR_lookup_internal_by_addr(success);
 	if (label == NULL) {
-		*problem_ptr = "reached label with no stack trace info";
+		*problem_ptr = "reached unregistered label";
 		return STEP_ERROR_AFTER;
 	}
 
Index: runtime/mercury_stacks.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stacks.h,v
retrieving revision 1.11
diff -u -u -r1.11 mercury_stacks.h
--- mercury_stacks.h	1998/10/27 16:32:16	1.11
+++ mercury_stacks.h	1998/10/30 06:20:56
@@ -88,6 +88,9 @@
   #define MR_NONDET_FIXED_SIZE	5	/* units: words */
 #endif
 
+/* XXX for bootstrapping string__append */
+#define	NONDET_FIXED_SIZE	MR_NONDET_FIXED_SIZE
+
 /*
 ** Code that traverses the nondet stack depends on the relationship
 ** MR_NONDET_TEMP_SIZE < MR_DET_TEMP_SIZE < MR_NONDET_FIXED_SIZE.
Index: runtime/mercury_type_info.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_type_info.c,v
retrieving revision 1.10
diff -u -u -r1.10 mercury_type_info.c
--- mercury_type_info.c	1998/07/22 07:53:29	1.10
+++ mercury_type_info.c	1998/10/30 08:55:31
@@ -113,12 +113,6 @@
 Define_extern_entry(mercury__builtin_unify_pred_2_0);
 Define_extern_entry(mercury__builtin_index_pred_2_0);
 Define_extern_entry(mercury__builtin_compare_pred_3_0);
-Declare_label(mercury__builtin_compare_pred_3_0_i4);
-
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__builtin_unify_pred_2_0)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__builtin_index_pred_2_0)
-MR_MAKE_STACK_LAYOUT_ENTRY(mercury__builtin_compare_pred_3_0)
-MR_MAKE_STACK_LAYOUT_INTERNAL(mercury__builtin_compare_pred_3_0, 4)
 
 BEGIN_MODULE(mercury__builtin_unify_pred_module)
 	init_entry(mercury__builtin_unify_pred_2_0);
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.27
diff -u -u -r1.27 mercury_wrapper.c
--- mercury_wrapper.c	1998/10/16 06:19:12	1.27
+++ mercury_wrapper.c	1998/10/30 09:14:27
@@ -27,7 +27,6 @@
 **	various cleanups that are needed to terminate cleanly.
 */
 
-#define		MR_STACK_TRACE_THIS_MODULE
 #include	"mercury_imp.h"
 
 #include	<stdio.h>
@@ -924,16 +923,11 @@
 Declare_label(global_fail);
 Declare_label(all_done);
 
-MR_MAKE_STACK_LAYOUT_ENTRY(do_interpreter)
-MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(global_success, do_interpreter)
-MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(global_fail, do_interpreter)
-MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(all_done, do_interpreter)
-
 BEGIN_MODULE(interpreter_module)
-	init_entry(do_interpreter);
-	init_label_sl(global_success);
-	init_label_sl(global_fail);
-	init_label_sl(all_done);
+	init_entry_ai(do_interpreter);
+	init_label_ai(global_success);
+	init_label_ai(global_fail);
+	init_label_ai(all_done);
 BEGIN_CODE
 
 Define_entry(do_interpreter);
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/general
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing trial
cvs diff: Diffing util



More information about the developers mailing list