[m-rev.] diff: reduce .c file sizes further

Zoltan Somogyi zs at cs.mu.OZ.AU
Thu Apr 1 14:50:39 AEST 2004


Reduce the size of compiler-generated C source files even further. The
reduction is 3 to 6% in non-debug LLDS grades, but 25 to 35% in debug grades.
Together with my previous change, the size of parse_tree.modules.c has gone
from more than 25 Mb to less than 8 Mb.

The changes to the header files will be committed first, followed some days
later by the changes to the compiler to generate the new macros. This gives
time for people to "cvs update" their workspaces at their own pace before
a change in the installed compiler forces them to do so.

compiler/llds_out.m:
	Group the declarations of common_data structures, so that a single
	mention of the type name can be amortized over the declaration of many
	structures.

	Do not emit macro invocations needed only by time profiling unless
	we are doing time profiling.

	When emitting rvals, look for special cases in which we can emit
	shorter code: references to common_data structures and to
	type_ctor_info structures. Both occur a lot in the data structures
	the compiler generates in debugging grades.

	Record which type names have been declared, so we don't declare them
	twice.

	Convert some affected predicates to state variable syntax.

compiler/layout_out.m:
	When possible, emit a shorthand macro that declares a label as it
	defines its label layout structure.

compiler/rtti_out.m:
	Group the declarations of rtti data structures, so that a single
	mention of the type name can be amortized over the declaration of many
	structures.

compiler/llds.m:
	Put common_data structures into a separate type, to allow them to be
	manipulated independently.

	Add a helper predicate.

compiler/global_data.m:
	Conform to the changed types in llds.m.

compiler/name_mangle.m:
	Add some helper predicates for use in llds_out.m and rtti_out.m.

	Reorder some predicate definitions for consistency with their
	declarations.

compiler/rtti.m:
	Add a helper predicate.

compiler/trace.m:
	Instead of generating long canned code fragments, generate calls to
	macros that expand to those canned code fragments.

library/multi_map.m:
	Add function forms of the predicates in this module, for use in the
	modified compiler modules.

runtime/mercury_misc.h:
runtime/mercury_stack_layout.h:
runtime/mercury_trace_base.h:
runtime/mercury_type_info.h:
	Define the macros that the compiler now generates.

runtime/mercury_goto.h:
	Define macros used to implement the macros in the above four header
	files.

runtime/mercury_bootstrap.h:
	Move the definitions of bool, TRUE and FALSE to the section where they
	are defined only if the user asks for them. This is to avoid conflict
	with the module name "bool".

tests/hard_coded/pragma_import.m:
	Rename bool to MR_bool.

Zoltan.

cvs diff: Diffing .
cvs diff: Diffing analysis
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/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/global_data.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/global_data.m,v
retrieving revision 1.2
diff -u -b -r1.2 global_data.m
--- compiler/global_data.m	8 Mar 2004 09:12:24 -0000	1.2
+++ compiler/global_data.m	29 Mar 2004 21:24:09 -0000
@@ -219,7 +219,7 @@
 			common_data	:: bool,
 			cell_counter	:: counter,	% next cell number
 			type_counter	:: counter,	% next type number
-			cells		:: map(int, comp_gen_c_data),
+			cells		:: map(int, common_data),
 			cell_group_map	:: map(cell_type, cell_type_group)
 					% map cell argument types and then cell
 					% contents to the id of the common cell
@@ -359,8 +359,8 @@
 search_static_cell_offset(Info, DataAddr, Offset, Rval) :-
 	DataAddr = data_addr(Info ^ module_name, DataName),
 	DataName = common(CellNum, _),
-	map__search(Info ^ cells, CellNum, CompGenCData),
-	CompGenCData = common_data(_, _, TypeAndValue),
+	map__search(Info ^ cells, CellNum, CommonData),
+	CommonData = common_data(_, _, TypeAndValue),
 	(
 		TypeAndValue = plain_type_and_value(_, ArgsTypes),
 		list__index0_det(ArgsTypes, Offset, Rval - _)
@@ -382,7 +382,12 @@
 		offset_into_group(Groups, Offset - NumRvalsInGroup, Rval)
 	).
 
-get_static_cells(Info) = map__values(Info ^ cells).
+get_static_cells(Info) =
+	list__map(wrap_common_data, map__values(Info ^ cells)).
+
+:- func wrap_common_data(common_data) = comp_gen_c_data.
+
+wrap_common_data(CommonData) = common_data(CommonData).
 
 rval_type_as_arg(Rval, ExprnOpts, Type) :-
 	natural_type(ExprnOpts ^ unboxed_float, Rval, Type).
Index: compiler/layout_out.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/layout_out.m,v
retrieving revision 1.29
diff -u -b -r1.29 layout_out.m
--- compiler/layout_out.m	8 Mar 2004 09:12:24 -0000	1.29
+++ compiler/layout_out.m	30 Mar 2004 15:07:32 -0000
@@ -177,8 +177,7 @@
 	io__state::di, io__state::uo) is det.
 
 output_layout_decl(LayoutName, !DeclSet, !IO) :-
-	( decl_set_is_member(data_addr(layout_addr(LayoutName)), !.DeclSet)
-	->
+	( decl_set_is_member(data_addr(layout_addr(LayoutName)), !.DeclSet) ->
 		true
 	;
 		output_layout_name_storage_type_name(LayoutName, no, !IO),
@@ -458,26 +457,30 @@
 		output_rval_decls(LocnsTypes0, !DeclSet, !IO),
 		output_rval_decls(VarNums0, !DeclSet, !IO),
 		output_rval_decls(TypeParams0, !DeclSet, !IO),
-		LabelVars = label_has_var_info
+		LabelVars = label_has_var_info,
+		Macro = "MR_DEF_LL"
 	;
 		MaybeVarInfo = no,
-		LabelVars = label_has_no_var_info
+		LabelVars = label_has_no_var_info,
+		Macro = "MR_DEF_LLNVI"
 	),
-	io__write_string("\n", !IO),
 	LayoutName = label_layout(Label, LabelVars),
-	output_layout_name_storage_type_name(LayoutName, yes, !IO),
-	io__write_string(" = {\n", !IO),
-	io__write_string("\t(const MR_Proc_Layout *)\n\t\t&", !IO),
-	output_layout_name(ProcLayoutAddr, !IO),
-	io__write_string(",\n\t", !IO),
+	io__write_string("\n", !IO),
+	io__write_string(Macro, !IO),
+	io__write_string("(", !IO),
+	break_up_local_label(Label, ProcLabel, LabelNum),
+	output_proc_label(ProcLabel, no, !IO),
+	io__write_string(",\n ", !IO),
+	io__write_int(LabelNum, !IO),
+	io__write_string(", ", !IO),
 	(
 		MaybePort = yes(Port),
 		io__write_string(trace_port_to_string(Port), !IO)
 	;
 		MaybePort = no,
-		io__write_string("MR_PORT_NONE", !IO)
+		io__write_string("NONE", !IO)
 	),
-	io__write_string(",\n\t", !IO),
+	io__write_string(", ", !IO),
 	(
 		MaybeIsHidden = yes(yes),
 		io__write_string("MR_TRUE", !IO)
@@ -489,7 +492,7 @@
 		% the value we write here shouldn't matter
 		io__write_string("MR_FALSE", !IO)
 	),
-	io__write_string(",\n\t", !IO),
+	io__write_string(", ", !IO),
 	(
 		MaybeGoalPath = yes(GoalPath),
 		io__write_int(GoalPath, !IO)
@@ -497,23 +500,26 @@
 		MaybeGoalPath = no,
 		io__write_string("0", !IO)
 	),
-	io__write_string(",\n\t", !IO),
 	(
 		MaybeVarInfo = yes(VarInfo),
-		VarInfo = label_var_info(EncodedVarCount,
-			LocnsTypes, VarNums, TypeParams),
+		io__write_string(", ", !IO),
+		VarInfo = label_var_info(EncodedVarCount, LocnsTypes, VarNums,
+			TypeParams),
 		io__write_int(EncodedVarCount, !IO),
-		io__write_string(",\n\t(const void *)", !IO),
+		io__write_string(", ", !IO),
 		output_rval_as_addr(LocnsTypes, !IO),
-		io__write_string(",\n\t(const MR_uint_least16_t *)", !IO),
+		io__write_string(",", !IO),
 		output_rval_as_addr(VarNums, !IO),
-		io__write_string(",\n\t(const MR_Type_Param_Locns *)", !IO),
+		( TypeParams = const(int_const(0)) ->
+			io__write_string(", 0", !IO)
+		;
+			io__write_string(",\n\t", !IO),
 		output_rval_as_addr(TypeParams, !IO)
+		)
 	;
-		MaybeVarInfo = no,
-		io__write_int(-1, !IO)
+		MaybeVarInfo = no
 	),
-	io__write_string("\n};\n", !IO),
+	io__write_string(");\n", !IO),
 	decl_set_insert(data_addr(layout_addr(LayoutName)), !DeclSet).
 
 	% Output the rval in a context in which it is immediately cast to an
@@ -533,21 +539,21 @@
 
 :- func trace_port_to_string(trace_port) = string.
 
-trace_port_to_string(call) =	 	    "MR_PORT_CALL".
-trace_port_to_string(exit) = 		    "MR_PORT_EXIT".
-trace_port_to_string(redo) = 		    "MR_PORT_REDO".
-trace_port_to_string(fail) = 		    "MR_PORT_FAIL".
-trace_port_to_string(exception) = 	    "MR_PORT_EXCEPTION".
-trace_port_to_string(ite_cond) = 	    "MR_PORT_COND".
-trace_port_to_string(ite_then) = 	    "MR_PORT_THEN".
-trace_port_to_string(ite_else) = 	    "MR_PORT_ELSE".
-trace_port_to_string(neg_enter) =   	    "MR_PORT_NEG_ENTER".
-trace_port_to_string(neg_success) = 	    "MR_PORT_NEG_SUCCESS".
-trace_port_to_string(neg_failure) = 	    "MR_PORT_NEG_FAILURE".
-trace_port_to_string(disj) =   	            "MR_PORT_DISJ".
-trace_port_to_string(switch) = 	            "MR_PORT_SWITCH".
-trace_port_to_string(nondet_pragma_first) = "MR_PORT_PRAGMA_FIRST".
-trace_port_to_string(nondet_pragma_later) = "MR_PORT_PRAGMA_LATER".
+trace_port_to_string(call) =	 	    "CALL".
+trace_port_to_string(exit) = 		    "EXIT".
+trace_port_to_string(redo) = 		    "REDO".
+trace_port_to_string(fail) = 		    "FAIL".
+trace_port_to_string(exception) = 	    "EXCEPTION".
+trace_port_to_string(ite_cond) = 	    "COND".
+trace_port_to_string(ite_then) = 	    "THEN".
+trace_port_to_string(ite_else) = 	    "ELSE".
+trace_port_to_string(neg_enter) =   	    "NEG_ENTER".
+trace_port_to_string(neg_success) = 	    "NEG_SUCCESS".
+trace_port_to_string(neg_failure) = 	    "NEG_FAILURE".
+trace_port_to_string(disj) =   	            "DISJ".
+trace_port_to_string(switch) = 	            "SWITCH".
+trace_port_to_string(nondet_pragma_first) = "PRAGMA_FIRST".
+trace_port_to_string(nondet_pragma_later) = "PRAGMA_LATER".
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/llds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.298
diff -u -b -r1.298 llds.m
--- compiler/llds.m	23 Mar 2004 10:52:05 -0000	1.298
+++ compiler/llds.m	30 Mar 2004 12:02:42 -0000
@@ -109,8 +109,20 @@
 	% Global data generated by the compiler. Usually readonly,
 	% with one exception: data containing code addresses must
 	% be initialized.
+
 :- type comp_gen_c_data
 	--->	common_data(
+			common_data
+		)
+	;	rtti_data(
+			rtti_data
+		)
+	;	layout_data(
+			layout_data
+		).
+
+:- type common_data
+	--->	common_data(
 			module_name,		% The basename of this C file.
 			int,			% The id number of the cell.
 			common_cell_type_and_value
@@ -122,12 +134,6 @@
 						% first field of either
 						% plain_type_and_value or
 						% grouped_type_and_value.
-		)
-	;	rtti_data(
-			rtti_data
-		)
-	;	layout_data(
-			layout_data
 		).
 
 :- type comp_gen_c_module
@@ -911,6 +917,8 @@
 				% signed or unsigned
 				% (used for registers, stack slots, etc).
 
+:- pred break_up_local_label(label::in, proc_label::out, int::out) is det.
+
 :- func llds__stack_slot_num_to_lval(code_model, int) = lval.
 
 :- pred llds__wrap_rtti_data(rtti_data::in, comp_gen_c_data::out) is det.
@@ -943,6 +951,14 @@
 :- implementation.
 
 :- import_module require.
+
+break_up_local_label(Label, ProcLabel, LabelNum) :-
+	( Label = local(LabelNumPrime, ProcLabelPrime) ->
+		LabelNum = LabelNumPrime,
+		ProcLabel = ProcLabelPrime
+	;
+		error("break_up_local_label: bad label")
+	).
 
 llds__stack_slot_num_to_lval(CodeModel, SlotNum) =
 	(if CodeModel = model_non then
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.223
diff -u -b -r1.223 llds_out.m
--- compiler/llds_out.m	10 Mar 2004 05:21:53 -0000	1.223
+++ compiler/llds_out.m	31 Mar 2004 03:40:47 -0000
@@ -125,7 +125,9 @@
 	;	float_label(string)
 	;	code_addr(code_addr)
 	;	data_addr(data_addr)
-	;	pragma_c_struct(string).
+	;	pragma_c_struct(string)
+	;	type_info_like_struct(int)
+	;	typeclass_constraint_struct(int).
 
 :- type decl_set.
 
@@ -179,7 +181,7 @@
 :- import_module parse_tree__prog_util.
 
 :- import_module dir, int, char, string, std_util.
-:- import_module set, bintree_set, assoc_list, require.
+:- import_module multi_map, set, bintree_set, assoc_list, require.
 :- import_module varset, term.
 :- import_module library.	% for the version number.
 
@@ -411,11 +413,21 @@
 	io__write_string("\n", !IO),
 
 	gather_c_file_labels(Modules, Labels),
-	list__foldl2(output_c_data_type_def, Datas, !DeclSet, !IO),
+	classify_comp_gen_c_data(Datas, multi_map__init, CommonMap,
+		[], CommonDatas0, [], RttiDatas, [], LayoutDatas),
+	multi_map__to_assoc_list(CommonMap, CommonAssocList),
+	list__foldl2(output_common_decl_group, CommonAssocList, !DeclSet, !IO),
+	output_rtti_data_decl_list(RttiDatas, !DeclSet, !IO),
 	list__foldl2(output_c_label_decl(StackLayoutLabels), Labels,
 		!DeclSet, !IO),
 	list__foldl2(output_comp_gen_c_var, Vars, !DeclSet, !IO),
-	list__foldl2(output_comp_gen_c_data, Datas, !DeclSet, !IO),
+	list__reverse(CommonDatas0, CommonDatas),
+	list__foldl2(output_common_data_defn, CommonDatas, !DeclSet, !IO),
+	list__foldl2(output_rtti_data_defn, RttiDatas, !DeclSet, !IO),
+	order_layout_datas(LayoutDatas, OrderedLayoutDatas),
+	list__foldl2(output_layout_data_defn, OrderedLayoutDatas,
+		!DeclSet, !IO),
+
 	list__foldl2(output_comp_gen_c_module(StackLayoutLabels), Modules,
 		!DeclSet, !IO),
 	list__foldl(output_user_foreign_code, UserForeignCode, !IO),
@@ -431,6 +443,35 @@
 	c_util__output_rl_file(ModuleName, MaybeRLFile, !IO),
 	io__set_output_stream(OutputStream, _, !IO).
 
+:- pred order_layout_datas(list(layout_data)::in, list(layout_data)::out)
+	is det.
+
+order_layout_datas(LayoutDatas0, LayoutDatas) :-
+	order_layout_datas_2(LayoutDatas0, [], ProcLayouts,
+		[], LabelLayouts, [], OtherLayouts),
+	% list__reverse(RevProcLayouts, ProcLayouts),
+	% list__reverse(RevLabelLayouts, LabelLayouts),
+	% list__reverse(RevOtherLayouts, OtherLayouts),
+	list__condense([ProcLayouts, LabelLayouts, OtherLayouts], LayoutDatas).
+
+:- pred order_layout_datas_2(list(layout_data)::in,
+	list(layout_data)::in, list(layout_data)::out,
+	list(layout_data)::in, list(layout_data)::out,
+	list(layout_data)::in, list(layout_data)::out) is det.
+
+order_layout_datas_2([], !ProcLayouts, !LabelLayouts, !OtherLayouts).
+order_layout_datas_2([Layout | Layouts], !ProcLayouts, !LabelLayouts,
+		!OtherLayouts) :-
+	( Layout = proc_layout_data(_, _, _) ->
+		!:ProcLayouts = [Layout | !.ProcLayouts]
+	; Layout = label_layout_data(_, _, _, _, _, _) ->
+		!:LabelLayouts = [Layout | !.LabelLayouts]
+	;
+		!:OtherLayouts = [Layout | !.OtherLayouts]
+	),
+	order_layout_datas_2(Layouts, !ProcLayouts, !LabelLayouts,
+		!OtherLayouts).
+
 :- pred output_c_module_init_list(module_name::in, list(comp_gen_c_module)::in,
 	list(comp_gen_c_data)::in, map(label, data_addr)::in,
 	decl_set::in, decl_set::out, io__state::di, io__state::uo) is det.
@@ -751,6 +792,101 @@
 	io__write_string("_bunch_", !IO),
 	io__write_int(Number, !IO).
 
+:- pred classify_comp_gen_c_data(list(comp_gen_c_data)::in,
+	multi_map(int, common_data)::in,
+	multi_map(int, common_data)::out,
+	list(common_data)::in, list(common_data)::out,
+	list(rtti_data)::in, list(rtti_data)::out,
+	list(layout_data)::in, list(layout_data)::out) is det.
+
+classify_comp_gen_c_data([], !CommonMap, !CommonList, !RttiList, !LayoutList).
+classify_comp_gen_c_data([Data | Datas], !CommonMap, !CommonList,
+		!RttiList, !LayoutList) :-
+	(
+		Data = common_data(CommonData),
+		CommonData = common_data(_ModuleName, _CellNum, TypeAndValue),
+		TypeNum = common_cell_get_type_num(TypeAndValue),
+		multi_map__set(!.CommonMap, TypeNum, CommonData, !:CommonMap),
+		!:CommonList = [CommonData | !.CommonList]
+	;
+		Data = rtti_data(Rtti),
+		!:RttiList = [Rtti | !.RttiList]
+	;
+		Data = layout_data(Layout),
+		!:LayoutList = [Layout | !.LayoutList]
+	),
+	classify_comp_gen_c_data(Datas, !CommonMap, !CommonList,
+		!RttiList, !LayoutList).
+
+:- pred output_common_decl_group(pair(int, list(common_data))::in,
+	decl_set::in, decl_set::out, io::di, io::uo) is det.
+
+output_common_decl_group(TypeNum - CommonDatas, !DeclSet, !IO) :-
+	% ChunkSize should be as large as possible to reduce the size of the
+	% file being generated, but small enough not to overload the fixed
+	% limits of our target C compilers.
+	ChunkSize = 20,
+	% The process of creating the multi_map reverses the order of
+	% CommonDatas, we now undo this reversal.
+	list__chunk(list__reverse(CommonDatas), ChunkSize, CommonDataChunks),
+	list__foldl2(output_common_decl_chunk(TypeNum), CommonDataChunks,
+		!DeclSet, !IO).
+
+:- pred output_common_decl_chunk(int::in, list(common_data)::in,
+	decl_set::in, decl_set::out, io::di, io::uo) is det.
+
+output_common_decl_chunk(TypeNum, CommonDatas, !DeclSet, !IO) :-
+	io__write_string("\n", !IO),
+	globals__io_lookup_bool_option(split_c_files, SplitFiles, !IO),
+	ExportedFromFile = SplitFiles,
+	(
+		CommonDatas = [CommonData | _],
+		CommonData = common_data(ModuleName, _, TypeAndValue)
+	;
+		CommonDatas = [],
+		error("output_common_decl_chunk: empty list")
+	),
+	TypeDeclId = common_type(ModuleName, TypeNum),
+	( decl_set_is_member(TypeDeclId, !.DeclSet) ->
+		true
+	;
+		output_const_term_type(TypeAndValue, ModuleName,
+			"", "", 0, _, !IO),
+		io__write_string("\n", !IO),
+		decl_set_insert(TypeDeclId, !DeclSet)
+	),
+	(
+		ExportedFromFile = yes,
+		io__write_string("const struct ", !IO)
+	;
+		ExportedFromFile = no,
+		io__write_string("static const struct ", !IO)
+	),
+	output_common_cell_type_name(ModuleName, TypeNum, !IO),
+	io__nl(!IO),
+	output_common_decl_chunk_entries(CommonDatas, !DeclSet, !IO).
+
+:- pred output_common_decl_chunk_entries(list(common_data)::in,
+	decl_set::in, decl_set::out, io::di, io::uo) is det.
+
+output_common_decl_chunk_entries([], !DeclSet, !IO) :-
+	error("output_common_decl_chunk_entries: empty list").
+output_common_decl_chunk_entries([CommonData | CommonDatas], !DeclSet, !IO) :-
+	CommonData = common_data(ModuleName, CellNum, TypeAndValue),
+	TypeNum = common_cell_get_type_num(TypeAndValue),
+	VarName = common(CellNum, TypeNum),
+	VarDeclId = data_addr(data_addr(ModuleName, VarName)),
+	output_decl_id(VarDeclId, !IO),
+	decl_set_insert(VarDeclId, !DeclSet),
+	(
+		CommonDatas = [_ | _],
+		io__write_string(",\n", !IO),
+		output_common_decl_chunk_entries(CommonDatas, !DeclSet, !IO)
+	;
+		CommonDatas = [],
+		io__write_string(";\n", !IO)
+	).
+
 	%
 	% output_c_data_type_def outputs the given the type definition.
 	% This is needed because some compilers need the type definition
@@ -761,7 +897,17 @@
 :- pred output_c_data_type_def(comp_gen_c_data::in,
 	decl_set::in, decl_set::out, io__state::di, io__state::uo) is det.
 
-output_c_data_type_def(common_data(ModuleName, CellNum, TypeAndValue),
+output_c_data_type_def(common_data(CommonData), !DeclSet, !IO) :-
+	output_common_data_decl(CommonData, !DeclSet, !IO).
+output_c_data_type_def(rtti_data(RttiData), !DeclSet, !IO) :-
+	output_rtti_data_decl(RttiData, !DeclSet, !IO).
+output_c_data_type_def(layout_data(LayoutData), !DeclSet, !IO) :-
+	output_maybe_layout_data_decl(LayoutData, !DeclSet, !IO).
+
+:- pred output_common_data_decl(common_data::in,
+	decl_set::in, decl_set::out, io__state::di, io__state::uo) is det.
+
+output_common_data_decl(common_data(ModuleName, CellNum, TypeAndValue),
 		!DeclSet, !IO) :-
 	io__write_string("\n", !IO),
 
@@ -787,10 +933,6 @@
 	output_const_term_decl_or_defn(TypeAndValue, ModuleName, CellNum,
 		ExportedFromFile, no, "", "", 0, _, !IO),
 	decl_set_insert(VarDeclId, !DeclSet).
-output_c_data_type_def(rtti_data(RttiData), !DeclSet, !IO) :-
-	output_rtti_data_decl(RttiData, !DeclSet, !IO).
-output_c_data_type_def(layout_data(LayoutData), !DeclSet, !IO) :-
-	output_maybe_layout_data_decl(LayoutData, !DeclSet, !IO).
 
 :- pred output_comp_gen_c_module(map(label, data_addr)::in,
 	comp_gen_c_module::in, decl_set::in, decl_set::out,
@@ -830,7 +972,17 @@
 :- pred output_comp_gen_c_data(comp_gen_c_data::in,
 	decl_set::in, decl_set::out, io__state::di, io__state::uo) is det.
 
-output_comp_gen_c_data(common_data(ModuleName, CellNum, TypeAndValue),
+output_comp_gen_c_data(common_data(CommonData), !DeclSet, !IO) :-
+	output_common_data_defn(CommonData, !DeclSet, !IO).
+output_comp_gen_c_data(rtti_data(RttiData), !DeclSet, !IO) :-
+	output_rtti_data_defn(RttiData, !DeclSet, !IO).
+output_comp_gen_c_data(layout_data(LayoutData), !DeclSet, !IO) :-
+	output_layout_data_defn(LayoutData, !DeclSet, !IO).
+
+:- pred output_common_data_defn(common_data::in,
+	decl_set::in, decl_set::out, io__state::di, io__state::uo) is det.
+
+output_common_data_defn(common_data(ModuleName, CellNum, TypeAndValue),
 		!DeclSet, !IO) :-
 	io__write_string("\n", !IO),
 	Args = common_cell_get_rvals(TypeAndValue),
@@ -850,10 +1002,6 @@
 	output_const_term_decl_or_defn(TypeAndValue, ModuleName, CellNum,
 		ExportedFromFile, yes, "", "", 0, _, !IO),
 	decl_set_insert(VarDeclId, !DeclSet).
-output_comp_gen_c_data(rtti_data(RttiData), !DeclSet, !IO) :-
-	output_rtti_data_defn(RttiData, !DeclSet, !IO).
-output_comp_gen_c_data(layout_data(LayoutData), !DeclSet, !IO) :-
-	output_layout_data_defn(LayoutData, !DeclSet, !IO).
 
 :- pred output_user_foreign_code(user_foreign_code::in,
 	io__state::di, io__state::uo) is det.
@@ -924,16 +1072,43 @@
 	% Declare the stack layout entry for this label, if needed.
 	%
 	( map__search(StackLayoutLabels, Label, DataAddr) ->
-		output_stack_layout_decl(DataAddr, !DeclSet, !IO)
+		(
+			Label = local(LabelNum, ProcLabel),
+			DataAddr = layout_addr(LayoutName),
+			LayoutName = label_layout(Label, LabelVars)
+		->
+			(
+				LabelVars = label_has_var_info,
+				Macro = "MR_DECL_LL"
 	;
-		true
+				LabelVars = label_has_no_var_info,
+				Macro = "MR_DECL_LLNVI"
+			),
+			io__write_string(Macro, !IO),
+			io__write_string("(", !IO),
+			output_proc_label(ProcLabel, no, !IO),
+			io__write_string(", ", !IO),
+			io__write_int(LabelNum, !IO),
+			% The final semicolon is in the macro definition.
+			io__write_string(")\n", !IO),
+			% The macro declares both the label layout structure
+			% and the label.
+			AlreadyDeclaredLabel = yes
+		;
+			output_stack_layout_decl(DataAddr, !DeclSet, !IO),
+			AlreadyDeclaredLabel = no
+		)
+	;
+		AlreadyDeclaredLabel = no
 	),
+	(
+		AlreadyDeclaredLabel = no,
 	%
 	% Declare the label itself.
 	%
 	(
 		Label = exported(_),
-		io__write_string("MR_define_extern_entry(", !IO)
+			DeclMacro = "MR_define_extern_entry("
 	;
 		Label = local(_),
 		% The code for procedures local to a Mercury module
@@ -941,22 +1116,28 @@
 		% generated for that module. However, if we generate
 		% multiple C files, the code in each C file must be
 		% visible to the other C files for that Mercury module.
-		globals__io_lookup_bool_option(split_c_files, SplitFiles, !IO),
+			globals__io_lookup_bool_option(split_c_files,
+				SplitFiles, !IO),
 		( SplitFiles = no ->
-			io__write_string("MR_declare_static(", !IO)
+				DeclMacro = "MR_declare_static("
 		;
-			io__write_string("MR_define_extern_entry(", !IO)
+				DeclMacro = "MR_define_extern_entry("
 		)
 	;
 		Label = c_local(_),
-		io__write_string("MR_declare_local(", !IO)
+			DeclMacro = "MR_declare_local("
 	;
 		Label = local(_, _),
-		io__write_string("MR_declare_label(", !IO)
+			DeclMacro = "MR_declare_label("
 	),
-	decl_set_insert(code_addr(label(Label)), !DeclSet),
+		io__write_string(DeclMacro, !IO),
+		io__write_string("", !IO),
 	output_label(Label, !IO),
-	io__write_string(");\n", !IO).
+		io__write_string(");\n", !IO)
+	;
+		AlreadyDeclaredLabel = yes
+	),
+	decl_set_insert(code_addr(label(Label)), !DeclSet).
 
 :- pred output_stack_layout_decl(data_addr::in, decl_set::in, decl_set::out,
 	io__state::di, io__state::uo) is det.
@@ -2268,7 +2449,7 @@
 	),
 	TypeNum = common_cell_get_type_num(TypeAndValue),
 	output_common_cell_type_name(ModuleName, TypeNum, !IO),
-	io__write_string("\n\t", !IO),
+	io__write_string(" ", !IO),
 	VarDeclId = data_addr(ModuleName, common(CellNum, TypeNum)),
 	output_decl_id(data_addr(VarDeclId), !IO),
 	(
@@ -2323,6 +2504,10 @@
 	{ error("output_decl_id: float_label unexpected") }.
 output_decl_id(pragma_c_struct(_Name)) -->
 	{ error("output_decl_id: pragma_c_struct unexpected") }.
+output_decl_id(type_info_like_struct(_Name)) -->
+	{ error("output_decl_id: type_info_like_struct unexpected") }.
+output_decl_id(typeclass_constraint_struct(_Name)) -->
+	{ error("output_decl_id: class_constraint_struct unexpected") }.
 
 :- pred output_cons_arg_types(list(llds_type)::in, string::in, int::in,
 	io__state::di, io__state::uo) is det.
@@ -2678,15 +2863,17 @@
 	(
 		DataAddr = data_addr(ModuleName, DataVarName),
 		output_data_addr_storage_type_name(ModuleName, DataVarName, no,
-			LaterIndent, !IO)
+			LaterIndent, !IO),
+		io__write_string(";\n", !IO)
 	;
 		DataAddr = rtti_addr(RttiId),
-		output_rtti_id_storage_type_name(RttiId, no, !IO)
+		output_rtti_id_storage_type_name_no_decl(RttiId, no, !IO),
+		io__write_string(";\n", !IO)
 	;
 		DataAddr = layout_addr(LayoutName),
-		output_layout_name_storage_type_name(LayoutName, no, !IO)
-	),
-	io__write_string(";\n", !IO).
+		output_layout_name_storage_type_name(LayoutName, no, !IO),
+		io__write_string(";\n", !IO)
+	).
 
 output_data_addrs_decls([], _, _, !N, !DeclSet, !IO).
 output_data_addrs_decls([DataAddr | DataAddrs], FirstIndent, LaterIndent, !N,
@@ -2784,7 +2971,13 @@
 	io__state::di, io__state::uo) is det.
 
 maybe_output_update_prof_counter(Label, CallerLabel - ContLabelSet, !IO) :-
-	( bintree_set__is_member(Label, ContLabelSet) ->
+	% If ProfileTime is no, the definition of MR_update_prof_current_proc
+	% is empty anyway.
+	globals__io_lookup_bool_option(profile_time, ProfileTime, !IO),
+	(
+		bintree_set__is_member(Label, ContLabelSet),
+		ProfileTime = yes
+	->
 		io__write_string("\tMR_update_prof_current_proc(MR_LABEL(",
 			!IO),
 		output_label(CallerLabel, !IO),
@@ -3343,61 +3536,61 @@
 		io__write_string(")", !IO)
 	).
 
-output_rval(const(Const)) -->
-	output_rval_const(Const).
-output_rval(unop(UnaryOp, Exprn)) -->
-	output_unary_op(UnaryOp),
-	io__write_string("("),
-	{ llds__unop_arg_type(UnaryOp, ArgType) },
-	output_rval_as_type(Exprn, ArgType),
-	io__write_string(")").
-output_rval(binop(Op, X, Y)) -->
+output_rval(const(Const), !IO) :-
+	output_rval_const(Const, !IO).
+output_rval(unop(UnaryOp, Exprn), !IO) :-
+	output_unary_op(UnaryOp, !IO),
+	io__write_string("(", !IO),
+	llds__unop_arg_type(UnaryOp, ArgType),
+	output_rval_as_type(Exprn, ArgType, !IO),
+	io__write_string(")", !IO).
+output_rval(binop(Op, X, Y), !IO) :-
 	(
-		{ Op = array_index(_Type) }
+		Op = array_index(_Type)
 	->
-		io__write_string("("),
-		output_rval_as_type(X, data_ptr),
-		io__write_string(")["),
-		output_rval_as_type(Y, integer),
-		io__write_string("]")
-	;
-		{ c_util__string_compare_op(Op, OpStr) }
-	->
-		io__write_string("(strcmp((char *)"),
-		output_rval_as_type(X, word),
-		io__write_string(", (char *)"),
-		output_rval_as_type(Y, word),
-		io__write_string(")"),
-		io__write_string(" "),
-		io__write_string(OpStr),
-		io__write_string(" "),
-		io__write_string("0)")
-	;
-		( { c_util__float_compare_op(Op, OpStr1) } ->
-			{ OpStr = OpStr1 }
-		; { c_util__float_op(Op, OpStr2) } ->
-			{ OpStr = OpStr2 }
-		;
-			{ fail }
-		)
-	->
-		io__write_string("("),
-		output_rval_as_type(X, float),
-		io__write_string(" "),
-		io__write_string(OpStr),
-		io__write_string(" "),
-		output_rval_as_type(Y, float),
-		io__write_string(")")
+		io__write_string("(", !IO),
+		output_rval_as_type(X, data_ptr, !IO),
+		io__write_string(")[", !IO),
+		output_rval_as_type(Y, integer, !IO),
+		io__write_string("]", !IO)
+	;
+		c_util__string_compare_op(Op, OpStr)
+	->
+		io__write_string("(strcmp((char *)", !IO),
+		output_rval_as_type(X, word, !IO),
+		io__write_string(", (char *)", !IO),
+		output_rval_as_type(Y, word, !IO),
+		io__write_string(")", !IO),
+		io__write_string(" ", !IO),
+		io__write_string(OpStr, !IO),
+		io__write_string(" ", !IO),
+		io__write_string("0)", !IO)
+	;
+		( c_util__float_compare_op(Op, OpStr1) ->
+			OpStr = OpStr1
+		; c_util__float_op(Op, OpStr2) ->
+			OpStr = OpStr2
+		;
+			fail
+		)
+	->
+		io__write_string("(", !IO),
+		output_rval_as_type(X, float, !IO),
+		io__write_string(" ", !IO),
+		io__write_string(OpStr, !IO),
+		io__write_string(" ", !IO),
+		output_rval_as_type(Y, float, !IO),
+		io__write_string(")", !IO)
 	;
 % XXX broken for C == minint
 % (since `NewC is 0 - C' overflows)
-% 		{ Op = (+) },
-% 		{ Y = const(int_const(C)) },
-% 		{ C < 0 }
+% 		Op = (+),
+% 		Y = const(int_const(C)),
+% 		C < 0
 % 	->
-% 		{ NewOp = (-) },
-% 		{ NewC is 0 - C },
-% 		{ NewY = const(int_const(NewC)) },
+% 		NewOp = (-),
+% 		NewC is 0 - C,
+% 		NewY = const(int_const(NewC)),
 % 		io__write_string("("),
 % 		output_rval(X),
 % 		io__write_string(" "),
@@ -3410,89 +3603,103 @@
 		% casts -- there's no difference between signed and
 		% unsigned equality, so if both args are unsigned, we
 		% don't need to cast them to (Integer)
-		{ Op = eq ; Op = ne },
-		{ llds__rval_type(X, XType) },
-		{ XType = word ; XType = unsigned },
-		{ llds__rval_type(Y, YType) },
-		{ YType = word ; YType = unsigned }
-	->
-		io__write_string("("),
-		output_rval(X),
-		io__write_string(" "),
-		output_binary_op(Op),
-		io__write_string(" "),
-		output_rval(Y),
-		io__write_string(")")
-	;
-		{ c_util__unsigned_compare_op(Op, OpStr) }
-	->
-		io__write_string("("),
-		output_rval_as_type(X, unsigned),
-		io__write_string(" "),
-		io__write_string(OpStr),
-		io__write_string(" "),
-		output_rval_as_type(Y, unsigned),
-		io__write_string(")")
-	;
-		io__write_string("("),
-		output_rval_as_type(X, integer),
-		io__write_string(" "),
-		output_binary_op(Op),
-		io__write_string(" "),
-		output_rval_as_type(Y, integer),
-		io__write_string(")")
-	).
-output_rval(mkword(Tag, Exprn)) -->
-	io__write_string("MR_mkword("),
-	output_tag(Tag),
-	io__write_string(", "),
-	output_rval_as_type(Exprn, data_ptr),
-	io__write_string(")").
-output_rval(lval(Lval)) -->
+		( Op = eq ; Op = ne ),
+		( llds__rval_type(X, XType) ),
+		( XType = word ; XType = unsigned ),
+		( llds__rval_type(Y, YType) ),
+		( YType = word ; YType = unsigned )
+	->
+		io__write_string("(", !IO),
+		output_rval(X, !IO),
+		io__write_string(" ", !IO),
+		output_binary_op(Op, !IO),
+		io__write_string(" ", !IO),
+		output_rval(Y, !IO),
+		io__write_string(")", !IO)
+	;
+		c_util__unsigned_compare_op(Op, OpStr)
+	->
+		io__write_string("(", !IO),
+		output_rval_as_type(X, unsigned, !IO),
+		io__write_string(" ", !IO),
+		io__write_string(OpStr, !IO),
+		io__write_string(" ", !IO),
+		output_rval_as_type(Y, unsigned, !IO),
+		io__write_string(")", !IO)
+	;
+		io__write_string("(", !IO),
+		output_rval_as_type(X, integer, !IO),
+		io__write_string(" ", !IO),
+		output_binary_op(Op, !IO),
+		io__write_string(" ", !IO),
+		output_rval_as_type(Y, integer, !IO),
+		io__write_string(")", !IO)
+	).
+output_rval(mkword(Tag, Exprn), !IO) :-
+	globals__io_lookup_bool_option(split_c_files, SplitFiles, !IO),
+	(
+		SplitFiles = no,
+		Exprn = const(data_addr_const(DataAddr, no)),
+		DataAddr = data_addr(_, DataName),
+		DataName = common(CellNum, _TypeNum)
+	->
+		io__write_string("MR_TAG_COMMON(", !IO),
+		io__write_int(Tag, !IO),
+		io__write_string(",", !IO),
+		io__write_int(CellNum, !IO),
+		io__write_string(")", !IO)
+	;
+		io__write_string("MR_mkword(", !IO),
+		output_tag(Tag, !IO),
+		io__write_string(", ", !IO),
+		output_rval_as_type(Exprn, data_ptr, !IO),
+		io__write_string(")", !IO)
+	).
+output_rval(lval(Lval), !IO) :-
 	% if a field is used as an rval, then we need to use
 	% the MR_const_field() macro, not the MR_field() macro,
 	% to avoid warnings about discarding const,
 	% and similarly for MR_mask_field.
-	( { Lval = field(MaybeTag, Rval, FieldNum) } ->
-		( { MaybeTag = yes(Tag) } ->
-			io__write_string("MR_const_field("),
-			output_tag(Tag),
-			io__write_string(", ")
+	( Lval = field(MaybeTag, Rval, FieldNum) ->
+		( MaybeTag = yes(Tag) ->
+			io__write_string("MR_const_field(", !IO),
+			output_tag(Tag, !IO),
+			io__write_string(", ", !IO)
 		;
-			io__write_string("MR_const_mask_field(")
+			io__write_string("MR_const_mask_field(", !IO)
 		),
-		output_rval(Rval),
-		io__write_string(", "),
-		output_rval(FieldNum),
-		io__write_string(")")
+		output_rval(Rval, !IO),
+		io__write_string(", ", !IO),
+		output_rval(FieldNum, !IO),
+		io__write_string(")", !IO)
 	;
-		output_lval(Lval)
+		output_lval(Lval, !IO)
 	).
-output_rval(var(_)) -->
-	{ error("Cannot output a var(_) expression in code") }.
-output_rval(mem_addr(MemRef)) -->
-	(
-		{ MemRef = stackvar_ref(N) },
-		output_llds_type_cast(data_ptr),
-		io__write_string("&MR_stackvar("),
-		io__write_int(N),
-		io__write_string(")")
-	;
-		{ MemRef = framevar_ref(N) },
-		output_llds_type_cast(data_ptr),
-		io__write_string("&MR_framevar("),
-		io__write_int(N),
-		io__write_string(")")
-	;
-		{ MemRef = heap_ref(Rval, Tag, FieldNum) },
-		output_llds_type_cast(data_ptr),
-		io__write_string("&MR_field("),
-		output_tag(Tag),
-		io__write_string(", "),
-		output_rval(Rval),
-		io__write_string(", "),
-		io__write_int(FieldNum),
-		io__write_string(")")
+output_rval(var(_), !IO) :-
+	error("Cannot output a var(_) expression in code").
+output_rval(mem_addr(MemRef), !IO) :-
+	(
+		MemRef = stackvar_ref(N),
+		output_llds_type_cast(data_ptr, !IO),
+		io__write_string("&MR_stackvar(", !IO),
+		io__write_int(N, !IO),
+		io__write_string(")", !IO)
+	;
+		MemRef = framevar_ref(N),
+		output_llds_type_cast(data_ptr, !IO),
+		io__write_string("&MR_framevar(", !IO),
+		io__write_int(N, !IO),
+		io__write_string(")", !IO)
+	;
+		MemRef = heap_ref(Rval, Tag, FieldNum),
+		output_llds_type_cast(data_ptr, !IO),
+		io__write_string("&MR_field(", !IO),
+		output_tag(Tag, !IO),
+		io__write_string(", ", !IO),
+		output_rval(Rval, !IO),
+		io__write_string(", ", !IO),
+		io__write_int(FieldNum, !IO),
+		io__write_string(")", !IO)
 	).
 
 :- pred output_unary_op(unary_op::in, io__state::di, io__state::uo) is det.
@@ -3503,60 +3710,146 @@
 
 :- pred output_rval_const(rval_const::in, io__state::di, io__state::uo) is det.
 
-output_rval_const(int_const(N)) -->
+output_rval_const(int_const(N), !IO) :-
 	% we need to cast to (Integer) to ensure
 	% things like 1 << 32 work when `Integer' is 64 bits
 	% but `int' is 32 bits.
-	output_llds_type_cast(integer),
-	io__write_int(N).
-output_rval_const(float_const(FloatVal)) -->
+	output_llds_type_cast(integer, !IO),
+	io__write_int(N, !IO).
+output_rval_const(float_const(FloatVal), !IO) :-
 	% the cast to (Float) here lets the C compiler
 	% do arithmetic in `float' rather than `double'
 	% if `Float' is `float' not `double'.
-	output_llds_type_cast(float),
-	c_util__output_float_literal(FloatVal).
-output_rval_const(string_const(String)) -->
-	io__write_string("MR_string_const("""),
-	c_util__output_quoted_string(String),
-	{ string__length(String, StringLength) },
-	io__write_string(""", "),
-	io__write_int(StringLength),
-	io__write_string(")").
-output_rval_const(multi_string_const(Length, String)) -->
-	io__write_string("MR_string_const("""),
-	c_util__output_quoted_multi_string(Length, String),
-	io__write_string(""", "),
-	io__write_int(Length),
-	io__write_string(")").
-output_rval_const(true) -->
-	io__write_string("MR_TRUE").
-output_rval_const(false) -->
-	io__write_string("MR_FALSE").
-output_rval_const(code_addr_const(CodeAddress)) -->
-	output_code_addr(CodeAddress).
-output_rval_const(data_addr_const(DataAddr, MaybeOffset)) -->
+	output_llds_type_cast(float, !IO),
+	c_util__output_float_literal(FloatVal, !IO).
+output_rval_const(string_const(String), !IO) :-
+	io__write_string("MR_string_const(""", !IO),
+	c_util__output_quoted_string(String, !IO),
+	string__length(String, StringLength),
+	io__write_string(""", ", !IO),
+	io__write_int(StringLength, !IO),
+	io__write_string(")", !IO).
+output_rval_const(multi_string_const(Length, String), !IO) :-
+	io__write_string("MR_string_const(""", !IO),
+	c_util__output_quoted_multi_string(Length, String, !IO),
+	io__write_string(""", ", !IO),
+	io__write_int(Length, !IO),
+	io__write_string(")", !IO).
+output_rval_const(true, !IO) :-
+	io__write_string("MR_TRUE", !IO).
+output_rval_const(false, !IO) :-
+	io__write_string("MR_FALSE", !IO).
+output_rval_const(code_addr_const(CodeAddress), !IO) :-
+	output_code_addr(CodeAddress, !IO).
+output_rval_const(data_addr_const(DataAddr, MaybeOffset), !IO) :-
 	% Data addresses are all assumed to be of type `MR_Word *';
 	% we need to cast them here to avoid type errors. The offset
 	% is also in MR_Words.
 	(
-		{ MaybeOffset = no },
-		output_llds_type_cast(data_ptr),
-		io__write_string("&"),
-		output_data_addr(DataAddr)
-	;
-		{ MaybeOffset = yes(Offset) },
-		io__write_string("(("),
-		output_llds_type_cast(data_ptr),
-		io__write_string("&"),
-		output_data_addr(DataAddr),
-		io__write_string(") + "),
-		io__write_int(Offset),
-		io__write_string(")")
+		MaybeOffset = no,
+		% The tests for special cases below increase the runtime
+		% of the compiler very slightly, but the use of shorter names
+		% reduces the size of the generated C source file, which has
+		% a considerably longer lifetime. In debugging grades, the
+		% file size difference can be very substantial.
+		globals__io_lookup_bool_option(split_c_files, SplitFiles, !IO),
+		(
+			SplitFiles = no,
+			DataAddr = data_addr(_, DataName),
+			DataName = common(CellNum, _TypeNum)
+		->
+			io__write_string("MR_COMMON(", !IO),
+			io__write_int(CellNum, !IO),
+			io__write_string(")", !IO)
+		;
+			DataAddr = rtti_addr(RttiId),
+			rtti_id_emits_type_ctor_info(RttiId, Ctor),
+			Ctor = rtti_type_ctor(Module, Name, Arity),
+			sym_name_doesnt_need_mangling(Module),
+			name_doesnt_need_mangling(Name)
+		->
+			output_type_ctor_addr(Module, Name, Arity, !IO)
+		;
+			output_llds_type_cast(data_ptr, !IO),
+			io__write_string("&", !IO),
+			output_data_addr(DataAddr, !IO)
+		)
+	;
+		MaybeOffset = yes(Offset),
+		io__write_string("((", !IO),
+		output_llds_type_cast(data_ptr, !IO),
+		io__write_string("&", !IO),
+		output_data_addr(DataAddr, !IO),
+		io__write_string(") + ", !IO),
+		io__write_int(Offset, !IO),
+		io__write_string(")", !IO)
+	).
+output_rval_const(label_entry(Label), !IO) :-
+	io__write_string("MR_ENTRY(", !IO),
+	output_label(Label, !IO),
+	io__write_string(")", !IO).
+
+:- pred output_type_ctor_addr(module_name::in, string::in, int::in,
+	io::di, io::uo) is det.
+
+output_type_ctor_addr(Module0, Name, Arity, !IO) :-
+	( Module0 = unqualified("") ->
+		Module = mercury_public_builtin_module
+	;
+		Module = Module0
+	),
+	% We don't need to mangle the module name, but we do need to
+	% convert it to a C identifier in the standard fashion.
+	ModuleStr = sym_name_mangle(Module),
+	( Arity = 0 ->
+		(
+			ModuleStr = "builtin",
+			( Name = "int" ->
+				Macro = "MR_INT_CTOR_ADDR"
+			; Name = "float" ->
+				Macro = "MR_FLOAT_CTOR_ADDR"
+			; Name = "string" ->
+				Macro = "MR_STRING_CTOR_ADDR"
+			; Name = "character" ->
+				Macro = "MR_CHAR_CTOR_ADDR"
+			;
+				fail
+			)
+		->
+			io__write_string(Macro, !IO)
+		;
+			ModuleStr = "io",
+			Name = "state"
+		->
+			io__write_string("MR_IO_CTOR_ADDR", !IO)
+		;
+			ModuleStr = "bool",
+			Name = "bool"
+		->
+			io__write_string("MR_BOOL_CTOR_ADDR", !IO)
+		;
+			io__write_strings(["MR_CTOR0_ADDR(", ModuleStr, ", ",
+				Name, ")"], !IO)
+		)
+	; Arity = 1 ->
+		(
+			Name = "list",
+			ModuleStr = "list"
+		->
+			io__write_string("MR_LIST_CTOR_ADDR", !IO)
+		;
+			Name = "private_builtin",
+			ModuleStr = "type_info"
+		->
+			io__write_string("MR_TYPE_INFO_CTOR_ADDR", !IO)
+		;
+			io__write_strings(["MR_CTOR1_ADDR(", ModuleStr, ", ",
+				Name, ")"], !IO)
+		)
+	;
+		io__write_strings(["MR_CTOR_ADDR(", ModuleStr, ", ", Name,
+			", ", int_to_string(Arity), ")"], !IO)
 	).
-output_rval_const(label_entry(Label)) -->
-	io__write_string("MR_ENTRY("),
-	output_label(Label),
-	io__write_string(")").
 
 :- pred output_lval_as_word(lval::in, io__state::di, io__state::uo) is det.
 
Index: compiler/name_mangle.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/name_mangle.m,v
retrieving revision 1.6
diff -u -b -r1.6 name_mangle.m
--- compiler/name_mangle.m	24 Mar 2004 02:57:12 -0000	1.6
+++ compiler/name_mangle.m	30 Mar 2004 12:18:55 -0000
@@ -30,8 +30,8 @@
 
 :- pred output_proc_label(proc_label::in, io::di, io::uo) is det.
 
-	% Output a proc label. The boolean controls whether label_prefixs
-	% is added to it.
+	% Output a proc label. The boolean controls whether
+	% mercury_label_prefix is added to it.
 
 :- pred output_proc_label(proc_label::in, bool::in, io::di, io::uo) is det.
 
@@ -49,6 +49,11 @@
 
 :- func sym_name_mangle(sym_name) = string.
 
+	% Succeed iff the given name or sym_name doesn't need mangling.
+
+:- pred name_doesnt_need_mangling(string::in) is semidet.
+:- pred sym_name_doesnt_need_mangling(sym_name::in) is semidet.
+
 	% Produces a string of the form Module__Name.
 
 :- func qualify_name(string, string) = string.
@@ -165,7 +170,7 @@
 		QualifiedMangledTypeName),
 
 	% join it all together
-	string__append_list( [LabelName, "_", FullyQualifiedMangledTypeName,
+	string__append_list([LabelName, "_", FullyQualifiedMangledTypeName,
 		"_", TypeArityString, "_", ModeNumString],
 		ProcLabelString).
 
@@ -179,33 +184,21 @@
 
 %
 % Warning: any changes to the name mangling algorithm here will also
-% require changes to extras/dynamic_linking/name_mangle.m,
-% profiler/demangle.m and util/mdemangle.c.
+% require changes to extras/dynamic_linking/name_mangle.m, profiler/demangle.m
+% and util/mdemangle.c.
 %
 make_pred_or_func_name(DefiningModule, PredOrFunc, DeclaringModule,
 		Name0, Arity, AddPrefix) = LabelName :-
 	DeclaringModuleName = sym_name_mangle(DeclaringModule),
 	DefiningModuleName = sym_name_mangle(DefiningModule),
-	(
-		(
-			Name0 = "main",
-			Arity = 2
-		;
-			string__prefix(Name0, "__")
-		)
-		% The conditions above define which labels are printed without
-		% module qualification.
-	->
+	( dont_module_qualify_name(Name0, Arity) ->
 		LabelName0 = Name0
 	;
 		LabelName0 = qualify_name(DeclaringModuleName, Name0)
 	),
-	(
-		% if this is a specialized version of a predicate
-		% defined in some other module, then it needs both
-		% module prefixes
-		DefiningModule \= DeclaringModule
-	->
+	% If this is a specialized version of a predicate defined
+	% in some other module, then it needs both module prefixes.
+	( DefiningModule \= DeclaringModule ->
 		string__append_list([DefiningModuleName, "__", LabelName0],
 			LabelName1)
 	;
@@ -219,32 +212,30 @@
 		PredOrFunc = predicate,
 		LabelName3 = LabelName2
 	),
-	(
-		AddPrefix = yes
-	->
+	( AddPrefix = yes ->
 		string__append(mercury_label_prefix, LabelName3, LabelName)
 	;
 		LabelName = LabelName3
 	).
 
+	% Define the conditions for which labels are printed
+	% without module qualification.
+:- pred dont_module_qualify_name(string::in, arity::in) is semidet.
+
+dont_module_qualify_name(Name, Arity) :-
+	(
+		Name = "main",
+		Arity = 2
+	;
+		string__prefix(Name, "__")
+	).
+
 %
 % Warning: any changes to the name mangling algorithm here will also
 % require changes to extras/dynamic_linking/name_mangle.m,
 % profiler/demangle.m and util/mdemangle.c.
 %
 
-sym_name_mangle(unqualified(Name)) =
-	name_mangle(Name).
-sym_name_mangle(qualified(ModuleName, PlainName)) = MangledName :-
-	MangledModuleName = sym_name_mangle(ModuleName),
-	MangledPlainName = name_mangle(PlainName),
-	MangledName = qualify_name(MangledModuleName, MangledPlainName).
-
-	% Convert a Mercury predicate name into something that can form
-	% part of a C identifier.  This predicate is necessary because
-	% quoted names such as 'name with embedded spaces' are valid
-	% predicate names in Mercury.
-
 name_mangle(Name) = MangledName :-
 	( string__is_alnum_or_underscore(Name) ->
 		% any names that start with `f_' are changed so that
@@ -259,6 +250,28 @@
 	;
 		MangledName = convert_to_valid_c_identifier(Name)
 	).
+
+sym_name_mangle(unqualified(Name)) =
+	name_mangle(Name).
+sym_name_mangle(qualified(ModuleName, PlainName)) = MangledName :-
+	MangledModuleName = sym_name_mangle(ModuleName),
+	MangledPlainName = name_mangle(PlainName),
+	MangledName = qualify_name(MangledModuleName, MangledPlainName).
+
+	% Convert a Mercury predicate name into something that can form
+	% part of a C identifier.  This predicate is necessary because
+	% quoted names such as 'name with embedded spaces' are valid
+	% predicate names in Mercury.
+
+name_doesnt_need_mangling(Name) :-
+	string__is_alnum_or_underscore(Name),
+	\+ string__append("f_", _Suffix, Name).
+
+sym_name_doesnt_need_mangling(unqualified(Name)) :-
+	name_doesnt_need_mangling(Name).
+sym_name_doesnt_need_mangling(qualified(ModuleName, PlainName)) :-
+	sym_name_doesnt_need_mangling(ModuleName),
+	name_doesnt_need_mangling(PlainName).
 
 :- func convert_to_valid_c_identifier(string) = string.
 
Index: compiler/rtti.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rtti.m,v
retrieving revision 1.46
diff -u -b -r1.46 rtti.m
--- compiler/rtti.m	24 Mar 2004 02:57:13 -0000	1.46
+++ compiler/rtti.m	30 Mar 2004 10:55:48 -0000
@@ -802,6 +802,11 @@
 :- func module_qualify_name_of_ctor_rtti_name(ctor_rtti_name) = bool.
 :- func module_qualify_name_of_tc_rtti_name(tc_rtti_name) = bool.
 
+	% If the given rtti_id is implemented as a single MR_TypeCtorInfo,
+	% return the identity of the type constructor.
+:- pred rtti_id_emits_type_ctor_info(rtti_id::in, rtti_type_ctor::out)
+	is semidet.
+
 :- implementation.
 
 :- import_module backend_libs__name_mangle.
@@ -1876,6 +1881,19 @@
 		no
 	;
 		yes
+	).
+
+rtti_id_emits_type_ctor_info(RttiId, TypeCtor) :-
+	RttiId = ctor_rtti_id(RttiTypeCtor, RttiName),
+	(
+		RttiName = type_ctor_info,
+		TypeCtor = RttiTypeCtor
+	;
+		RttiName = type_info(TypeInfo),
+		TypeInfo = plain_arity_zero_type_info(TypeCtor)
+	;
+		RttiName = pseudo_type_info(PseudoTypeInfo),
+		PseudoTypeInfo = plain_arity_zero_pseudo_type_info(TypeCtor)
 	).
 
 %-----------------------------------------------------------------------------%
Index: compiler/rtti_out.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rtti_out.m,v
retrieving revision 1.44
diff -u -b -r1.44 rtti_out.m
--- compiler/rtti_out.m	1 Apr 2004 04:34:21 -0000	1.44
+++ compiler/rtti_out.m	1 Apr 2004 04:38:53 -0000
@@ -26,7 +26,7 @@
 :- import_module backend_libs__rtti.
 :- import_module ll_backend__llds_out.
 
-:- import_module bool, io.
+:- import_module bool, list, io.
 
 	% Output a C expression holding the address of the C name of
 	% the specified rtti_data, preceded by the string in the first
@@ -39,6 +39,10 @@
 :- pred output_addr_of_rtti_data(rtti_data::in, io__state::di, io__state::uo)
 	is det.
 
+	% Output a C declaration for the rtti_datas.
+:- pred output_rtti_data_decl_list(list(rtti_data)::in,
+	decl_set::in, decl_set::out, io__state::di, io__state::uo) is det.
+
 	% Output a C declaration for the rtti_data.
 :- pred output_rtti_data_decl(rtti_data::in, decl_set::in, decl_set::out,
 	io__state::di, io__state::uo) is det.
@@ -67,6 +71,12 @@
 	% specified by the given rtti_id for use in a declaration or
 	% definition. The bool should be `yes' iff it is for a definition.
 :- pred output_rtti_id_storage_type_name(rtti_id::in, bool::in,
+	decl_set::in, decl_set::out, io__state::di, io__state::uo) is det.
+
+	% Output the C storage class, C type, and C name of the rtti_data
+	% specified by the given rtti_id for use in a declaration or
+	% definition. The bool should be `yes' iff it is for a definition.
+:- pred output_rtti_id_storage_type_name_no_decl(rtti_id::in, bool::in,
 	io__state::di, io__state::uo) is det.
 
 :- implementation.
@@ -85,7 +95,7 @@
 :- import_module parse_tree__prog_data.
 :- import_module parse_tree__prog_out.
 
-:- import_module int, string, list, assoc_list, map.
+:- import_module int, string, assoc_list, map, multi_map.
 :- import_module counter, require, std_util.
 
 %-----------------------------------------------------------------------------%
@@ -119,7 +129,7 @@
 	io__write_string("\n", !IO),
 	RttiId = tc_rtti_id(TCName,
 		base_typeclass_info(InstanceModuleName, InstanceString)),
-	output_rtti_id_storage_type_name(RttiId, yes, !IO),
+	output_rtti_id_storage_type_name(RttiId, yes, !DeclSet, !IO),
 	% XXX It would be nice to avoid generating redundant declarations
 	% of base_typeclass_infos, but currently we don't.
 	io__write_string(" = {\n\t(MR_Code *) ", !IO),
@@ -1231,6 +1241,111 @@
 
 %-----------------------------------------------------------------------------%
 
+:- type data_group --->
+	data_group(
+		data_c_type	:: string,
+		data_is_array	:: bool,
+		data_linkage	:: linkage
+	).
+
+output_rtti_data_decl_list(RttiDatas, !DeclSet, !IO) :-
+	classify_rtti_datas_to_decl(RttiDatas, multi_map__init, GroupMap),
+	multi_map__to_assoc_list(GroupMap, GroupList),
+	list__foldl2(output_rtti_data_decl_group, GroupList, !DeclSet, !IO).
+
+:- pred classify_rtti_datas_to_decl(list(rtti_data)::in,
+	multi_map(data_group, rtti_id)::in,
+	multi_map(data_group, rtti_id)::out) is det.
+
+classify_rtti_datas_to_decl([], !GroupMap).
+classify_rtti_datas_to_decl([RttiData | RttiDatas], !GroupMap) :-
+	( RttiData = pseudo_type_info(type_var(_)) ->
+		% These just get represented as integers,
+		% so we don't need to declare them.
+		% Also rtti_data_to_name/3 does not handle this case.
+		true
+	;
+		rtti_data_to_id(RttiData, RttiId),
+		rtti_id_c_type(RttiId, CType, IsArray),
+		rtti_id_linkage(RttiId, Linkage),
+		Group = data_group(CType, IsArray, Linkage),
+		multi_map__set(!.GroupMap, Group, RttiId, !:GroupMap)
+	),
+	classify_rtti_datas_to_decl(RttiDatas, !GroupMap).
+
+:- pred output_rtti_data_decl_group(pair(data_group, list(rtti_id))::in,
+	decl_set::in, decl_set::out, io::di, io::uo) is det.
+
+output_rtti_data_decl_group(Group - RttiIds, !DeclSet, !IO) :-
+	% ChunkSize should be as large as possible to reduce the size of the
+	% file being generated, but small enough not to overload the fixed
+	% limits of our target C compilers.
+	ChunkSize = 10,
+	% The process of creating the multi_map reverses the order of rtti_ids,
+	% we now undo this reversal.
+	list__chunk(list__reverse(RttiIds), ChunkSize, RttiIdChunks),
+	list__foldl2(output_rtti_data_decl_chunk(Group), RttiIdChunks,
+		!DeclSet, !IO).
+
+:- pred output_rtti_data_decl_chunk(data_group::in, list(rtti_id)::in,
+	decl_set::in, decl_set::out, io::di, io::uo) is det.
+
+output_rtti_data_decl_chunk(Group, RttiIds, !DeclSet, !IO) :-
+	(
+		% Pick a representative RttiId. All the operations we perform
+		% on it below would have the same result regardless of which
+		% one we picked.
+		RttiIds = [RttiId | _]
+	;
+		RttiIds = [],
+		error("output_rtti_data_decl_group: empty list")
+	),
+	Group = data_group(CType, IsArray, Linkage),
+
+	io__nl(!IO),
+	output_rtti_type_decl(RttiId, !DeclSet, !IO),
+	globals__io_get_globals(Globals, !IO),
+	LinkageStr = c_data_linkage_string(Globals, Linkage, yes, no),
+	InclCodeAddr = rtti_id_would_include_code_addr(RttiId),
+	c_data_const_string(Globals, InclCodeAddr, ConstStr),
+
+	io__write_string(LinkageStr, !IO),
+	io__write_string(ConstStr, !IO),
+	c_util__output_quoted_string(CType, !IO),
+	io__nl(!IO),
+
+	output_rtti_data_decl_chunk_entries(IsArray, RttiIds,
+		!DeclSet, !IO).
+
+:- pred output_rtti_data_decl_chunk_entries(bool::in, list(rtti_id)::in,
+	decl_set::in, decl_set::out, io::di, io::uo) is det.
+
+output_rtti_data_decl_chunk_entries(_IsArray, [], !DeclSet, !IO) :-
+	error("output_rtti_data_decl_chunk_entries: empty list").
+output_rtti_data_decl_chunk_entries(IsArray, [RttiId | RttiIds],
+		!DeclSet, !IO) :-
+	DataAddr = rtti_addr(RttiId),
+	decl_set_insert(data_addr(DataAddr), !DeclSet),
+	io__write_string("\t", !IO),
+	output_rtti_id(RttiId, !IO),
+	(
+		IsArray = yes,
+		io__write_string("[]", !IO)
+	;
+		IsArray = no
+	),
+	(
+		RttiIds = [_ | _],
+		io__write_string(",\n", !IO),
+		output_rtti_data_decl_chunk_entries(IsArray, RttiIds,
+			!DeclSet, !IO)
+	;
+		RttiIds = [],
+		io__write_string(";\n", !IO)
+	).
+
+%-----------------------------------------------------------------------------%
+
 output_rtti_data_decl(RttiData, !DeclSet, !IO) :-
 	( RttiData = pseudo_type_info(type_var(_)) ->
 		% These just get represented as integers,
@@ -1248,7 +1363,7 @@
 	io__state::di, io__state::uo) is det.
 
 output_generic_rtti_data_decl(RttiId, !DeclSet, !IO) :-
-	output_rtti_id_storage_type_name(RttiId, no, !IO),
+	output_rtti_id_storage_type_name(RttiId, no, !DeclSet, !IO),
 	io__write_string(";\n", !IO),
 	DataAddr = rtti_addr(RttiId),
 	decl_set_insert(data_addr(DataAddr), !DeclSet).
@@ -1258,12 +1373,17 @@
 
 output_generic_rtti_data_defn_start(RttiId, !DeclSet, !IO) :-
 	io__write_string("\n", !IO),
-	output_rtti_id_storage_type_name(RttiId, yes, !IO),
+	output_rtti_id_storage_type_name(RttiId, yes, !DeclSet, !IO),
 	DataAddr = rtti_addr(RttiId),
 	decl_set_insert(data_addr(DataAddr), !DeclSet).
 
-output_rtti_id_storage_type_name(RttiId, BeingDefined, !IO) :-
-	output_rtti_type_decl(RttiId, !IO),
+output_rtti_id_storage_type_name_no_decl(RttiId, BeingDefined, !IO) :-
+	decl_set_init(DeclSet0),
+	output_rtti_id_storage_type_name(RttiId, BeingDefined, DeclSet0, _,
+		!IO).
+
+output_rtti_id_storage_type_name(RttiId, BeingDefined, !DeclSet, !IO) :-
+	output_rtti_type_decl(RttiId, !DeclSet, !IO),
 	rtti_id_linkage(RttiId, Linkage),
 	globals__io_get_globals(Globals, !IO),
 	LinkageStr = c_data_linkage_string(Globals, Linkage, yes,
@@ -1289,35 +1409,48 @@
 	% depending on what kind of type_info or pseudo_type_info it is,
 	% and also on its arity. We need to declare that C type here.
 
-:- pred output_rtti_type_decl(rtti_id::in, io__state::di, io__state::uo)
-	is det.
+:- pred output_rtti_type_decl(rtti_id::in, decl_set::in, decl_set::out,
+	io__state::di, io__state::uo) is det.
 
-output_rtti_type_decl(RttiId, !IO) :-
+output_rtti_type_decl(RttiId, !DeclSet, !IO) :-
 	(
 		RttiId = ctor_rtti_id(_, RttiName),
 		rtti_type_ctor_template_arity(RttiName, Arity),
 		Arity > max_always_declared_arity_type_ctor
 	->
+		DeclId = type_info_like_struct(Arity),
+		( decl_set_is_member(DeclId, !.DeclSet) ->
+			true
+		;
 		Template =
 "#ifndef MR_TYPE_INFO_LIKE_STRUCTS_FOR_ARITY_%d_GUARD
 #define MR_TYPE_INFO_LIKE_STRUCTS_FOR_ARITY_%d_GUARD
 MR_DECLARE_ALL_TYPE_INFO_LIKE_STRUCTS_FOR_ARITY(%d);
 #endif
 ",
-		io__format(Template, [i(Arity), i(Arity), i(Arity)], !IO)
+			io__format(Template, [i(Arity), i(Arity), i(Arity)],
+				!IO),
+			decl_set_insert(DeclId, !DeclSet)
+		)
 	;
 		RttiId = tc_rtti_id(_, TCRttiName),
 		rtti_type_class_constraint_template_arity(TCRttiName, Arity),
 		Arity > max_always_declared_arity_type_class_constraint
 	->
+		DeclId = typeclass_constraint_struct(Arity),
+		( decl_set_is_member(DeclId, !.DeclSet) ->
+			true
+		;
 		Template =
 "#ifndef MR_TYPECLASS_CONSTRAINT_STRUCT_%d_GUARD
 #define MR_TYPECLASS_CONSTRAINT_STRUCT_%d_GUARD
 MR_DEFINE_TYPECLASS_CONSTRAINT_STRUCT(MR_TypeClassConstraint_%d, %d);
 #endif
 ",
-		io__format(Template, [i(Arity), i(Arity), i(Arity), i(Arity)],
-			!IO)
+			io__format(Template, [i(Arity), i(Arity), i(Arity),
+				i(Arity)], !IO),
+			decl_set_insert(DeclId, !DeclSet)
+		)
 	;
 		true
 	).
@@ -1419,7 +1552,8 @@
 		io__write_string("\t{\n\t", !IO),
 		(
 			SplitFiles = yes,
-			output_rtti_id_storage_type_name(RttiId, no, !IO),
+			output_rtti_id_storage_type_name_no_decl(RttiId, no,
+				!IO),
 			io__write_string(";\n", !IO)
 		;
 			SplitFiles = no
@@ -1436,7 +1570,8 @@
 		io__write_string("\t{\n\t", !IO),
 		(
 			SplitFiles = yes,
-			output_rtti_id_storage_type_name(RttiId, no, !IO),
+			output_rtti_id_storage_type_name_no_decl(RttiId, no,
+				!IO),
 			io__write_string(";\n", !IO)
 		;
 			SplitFiles = no
@@ -1452,7 +1587,8 @@
 		io__write_string("\t{\n\t", !IO),
 		(
 			SplitFiles = yes,
-			output_rtti_id_storage_type_name(RttiId, no, !IO),
+			output_rtti_id_storage_type_name_no_decl(RttiId, no,
+				!IO),
 			io__write_string(";\n", !IO)
 		;
 			SplitFiles = no
Index: compiler/trace.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/trace.m,v
retrieving revision 1.62
diff -u -b -r1.62 trace.m
--- compiler/trace.m	23 Mar 2004 10:52:13 -0000	1.62
+++ compiler/trace.m	31 Mar 2004 04:53:31 -0000
@@ -514,10 +514,8 @@
 	trace__stackref_to_string(EventNumLval, EventNumStr),
 	trace__stackref_to_string(CallNumLval, CallNumStr),
 	trace__stackref_to_string(CallDepthLval, CallDepthStr),
-	string__append_list([
-		"\t\t", EventNumStr, " = MR_trace_event_number;\n",
-		"\t\t", CallNumStr, " = MR_trace_incr_seq();\n",
-		"\t\t", CallDepthStr, " = MR_trace_incr_depth();\n"
+	string__append_list(["\t\tMR_trace_fill_std_slots(",
+		EventNumStr, ", ", CallNumStr, ", ", CallDepthStr, ");\n"
 	], FillThreeSlots),
 	(
 		MaybeIoSeqSlot = yes(IoSeqLval),
@@ -623,20 +621,18 @@
 		MaybeFromFullSlot = TraceInfo ^ from_full_lval,
 		trace__call_depth_slot(CodeModel, CallDepthLval),
 		trace__stackref_to_string(CallDepthLval, CallDepthStr),
-		string__append_list([
-			"MR_trace_reset_depth(", CallDepthStr, ");\n"
-		], ResetDepthStmt),
 		(
 			MaybeFromFullSlot = yes(_),
-			ResetFromFullStmt = "MR_trace_from_full = MR_FALSE;\n"
+			MacroStr = "MR_trace_reset_depth_from_shallow"
 		;
 			MaybeFromFullSlot = no,
-			ResetFromFullStmt = "MR_trace_from_full = MR_TRUE;\n"
+			MacroStr = "MR_trace_reset_depth_from_full"
 		),
+		string__append_list([
+			MacroStr, "(", CallDepthStr, ");\n"
+		], ResetStmt),
 		TraceCode = node([
-			c_code(ResetFromFullStmt, live_lvals_info(set__init))
-				- "",
-			c_code(ResetDepthStmt, live_lvals_info(set__init))
+			c_code(ResetStmt, live_lvals_info(set__init))
 				- ""
 		])
 	;
@@ -829,16 +825,8 @@
 
 	set__list_to_set(VarInfoList, VarInfoSet),
 	LayoutLabelInfo = layout_label_info(VarInfoSet, TvarDataMap),
-	LabelStr = layout_out__make_label_layout_name(Label),
-	DeclStmt = "\t\tMR_Code *MR_jumpaddr;\n",
-	SaveStmt = "\t\tMR_save_transient_registers();\n",
-	RestoreStmt = "\t\tMR_restore_transient_registers();\n",
-	GotoStmt = "\t\tif (MR_jumpaddr != NULL) MR_GOTO(MR_jumpaddr);\n",
-	string__append_list([
-		"\t\tMR_jumpaddr = MR_trace(\n",
-		"\t\t\t(const MR_Label_Layout *)\n",
-		"\t\t\t&", LabelStr, ");\n"],
-		CallStmt),
+	LabelStr = llds_out__label_to_c_string(Label, no),
+	string__append_list(["\t\tMR_EVENT(", LabelStr, ")\n"], TraceStmt),
 	code_info__add_trace_layout_for_label(Label, Context, Port, HideEvent,
 		Path, LayoutLabelInfo, !CI),
 	(
@@ -860,8 +848,6 @@
 	;
 		true
 	),
-	string__append_list([DeclStmt, SaveStmt, CallStmt, RestoreStmt,
-		GotoStmt], TraceStmt),
 	TraceCode =
 		node([
 			label(Label)
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/aditi
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/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
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/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/stream
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing java
cvs diff: Diffing java/library
cvs diff: Diffing java/runtime
cvs diff: Diffing library
Index: library/multi_map.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/multi_map.m,v
retrieving revision 1.12
diff -u -b -r1.12 multi_map.m
--- library/multi_map.m	15 Mar 2004 23:49:33 -0000	1.12
+++ library/multi_map.m	29 Mar 2004 16:09:48 -0000
@@ -31,6 +31,7 @@
 
 	% Initialize an empty multi_map.
 :- pred multi_map__init(multi_map(_, _)::uo) is det.
+:- func multi_map__init = multi_map(_, _).
 
 	% Check whether a multi_map is empty.
 :- pred multi_map__is_empty(multi_map(_, _)::in) is semidet.
@@ -48,6 +49,7 @@
 
 	% Search multi_map for key, but abort if search fails.
 :- pred multi_map__lookup(multi_map(K, V)::in, K::in, list(V)::out) is det.
+:- func multi_map__lookup(multi_map(K, V), K) = list(V).
 
 	% Search multi_map for key.
 :- pred multi_map__nondet_lookup(multi_map(K, V)::in, K::in, V::out) is nondet.
@@ -64,6 +66,7 @@
 	% Abort if the key already exists.
 :- pred multi_map__det_insert(multi_map(K, V)::in, K::in, V::in,
 	multi_map(K, V)::out) is det.
+:- func multi_map__det_insert(multi_map(K, V), K, V) = multi_map(K, V).
 
 	% Update (add) the value corresponding to a given key
 	% Fail if the key doesn't already exist.
@@ -74,55 +77,68 @@
 	% Abort if the key doesn't already exist.
 :- pred multi_map__det_update(multi_map(K, V)::in, K::in, V::in,
 	multi_map(K, V)::out) is det.
+:- func multi_map__det_update(multi_map(K, V), K, V) = multi_map(K, V).
 
 	% Update (replace) the value corresponding to a given key
 	% Abort if the key doesn't already exist.
 :- pred multi_map__det_replace(multi_map(K, V)::in, K::in, list(V)::in,
 	multi_map(K, V)::out) is det.
+:- func multi_map__det_replace(multi_map(K, V), K, list(V)) = multi_map(K, V).
 
 	% Update (add) value if the key is already present, otherwise
 	% insert new key and value.
 :- pred multi_map__set(multi_map(K, V)::in, K::in, V::in, multi_map(K, V)::out)
 	is det.
+:- func multi_map__set(multi_map(K, V), K, V) = multi_map(K, V).
 
 	% Given a multi_map, return a list of all the keys in the multi_map
 :- pred multi_map__keys(multi_map(K, _V)::in, list(K)::out) is det.
+:- func multi_map__keys(multi_map(K, _V)) = list(K).
 
 	% Given a multi_map, return a list of all the data values in the
 	% multi_map
 :- pred multi_map__values(multi_map(_K, V)::in, list(V)::out) is det.
+:- func multi_map__values(multi_map(_K, V)) = list(V).
 
 	% convert a multi_map to an association list
 :- pred multi_map__to_flat_assoc_list(multi_map(K, V)::in,
 	assoc_list(K, V)::out) is det.
+:- func multi_map__to_flat_assoc_list(multi_map(K, V)) = assoc_list(K, V).
 
 	% convert an association list to a multi_map
 :- pred multi_map__from_flat_assoc_list(assoc_list(K, V)::in,
 	multi_map(K, V)::out) is det.
+:- func multi_map__from_flat_assoc_list(assoc_list(K, V)) = multi_map(K, V).
 
 	% convert a multi_map to an association list, with all the
 	% values for each key in one element of the association list.
 :- pred multi_map__to_assoc_list(multi_map(K, V)::in,
 	assoc_list(K, list(V))::out) is det.
+:- func multi_map__to_assoc_list(multi_map(K, V)) = assoc_list(K, list(V)).
 
 	% convert an association list with all the values for each
 	% key in one element of the list to a multi_map
 :- pred multi_map__from_assoc_list(assoc_list(K, list(V))::in,
 	multi_map(K, V)::out) is det.
+:- func multi_map__from_assoc_list(assoc_list(K, list(V))) = multi_map(K, V).
 
 	% convert a sorted association list to a multi_map
 :- pred multi_map__from_sorted_assoc_list(assoc_list(K, list(V))::in,
 	multi_map(K, V)::out) is det.
+:- func multi_map__from_sorted_assoc_list(assoc_list(K, list(V)))
+	= multi_map(K, V).
 
 	% delete a key and data from a multi_map
 	% if the key is not present, leave the multi_map unchanged
 :- pred multi_map__delete(multi_map(K, V)::in, K::in, multi_map(K, V)::out)
 	is det.
+:- func multi_map__delete(multi_map(K, V), K) = multi_map(K, V).
 
 	% delete a data value from a key in a multi_map
 	% if the key is not present, leave the multi_map unchanged
 :- pred multi_map__delete(multi_map(K, V)::in, K::in, V::in,
 	multi_map(K, V)::out) is det.
+:- func multi_map__delete(multi_map(K, V), K, V) = multi_map(K, V).
 
 	% delete a key-value pair from a multi_map and return the value.
 	% fail if the key is not present
@@ -136,40 +152,51 @@
 
 	% Count the number of elements (keys) in the multi_map.
 :- pred multi_map__count(multi_map(K, V)::in, int::out) is det.
+:- func multi_map__count(multi_map(K, V)) = int.
 
 	% Count the number of data elements in the multi_map.
 :- pred multi_map__all_count(multi_map(K, V)::in, int::out) is det.
+:- func multi_map__all_count(multi_map(K, V)) = int.
 
 	% Convert a pair of lists (which must be of the same length)
 	% to a multi_map.
 :- pred multi_map__from_corresponding_lists(list(K)::in, list(V)::in,
 	multi_map(K, V)::out) is det.
+:- func multi_map__from_corresponding_lists(list(K), list(V))
+	= multi_map(K, V).
 
 	% Convert a pair of lists (which must be of the same length)
 	% to a multi_map.
 :- pred multi_map__from_corresponding_list_lists(list(K)::in, list(list(V))::in,
 	multi_map(K, V)::out) is det.
+:- func multi_map__from_corresponding_list_lists(list(K), list(list(V)))
+	= multi_map(K, V).
 
 	% For multi_map__merge(MultiMapA, MultiMapB, MultiMap).
 :- pred multi_map__merge(multi_map(K, V)::in, multi_map(K, V)::in,
 	multi_map(K, V)::out) is det.
+:- func multi_map__merge(multi_map(K, V), multi_map(K, V))
+	= multi_map(K, V).
 
 	% multi_map__select takes a multi_map and a set of keys and returns
 	% a multi_map containing the keys in the set and their corresponding
 	% values.
 :- pred multi_map__select(multi_map(K, V)::in, set(K)::in,
 	multi_map(K, V)::out) is det.
+:- func multi_map__select(multi_map(K, V), set(K)) = multi_map(K, V).
 
 	% Given a list of keys, produce a list of their values in a
 	% specified multi_map.
 :- pred multi_map__apply_to_list(list(K)::in, multi_map(K, V)::in,
 	list(V)::out) is det.
+:- func multi_map__apply_to_list(list(K), multi_map(K, V)) = list(V).
 
 	% Declaratively, a NOP.
 	% Operationally, a suggestion that the implemention
 	% optimize the representation of the multi_map in the expectation
 	% of a number of lookups but few or no modifications.
 :- pred multi_map__optimize(multi_map(K, V)::in, multi_map(K, V)::out) is det.
+:- func multi_map__optimize(multi_map(K, V)) = multi_map(K, V).
 
 	% Remove the smallest item from the multi_map, fail if
 	% the multi_map is empty.
@@ -220,7 +247,7 @@
 
 multi_map__update(MultiMap0, Key, Value, MultiMap) :-
 	map__search(MultiMap0, Key, Values0),
-	Values = [Value|Values0],
+	Values = [Value | Values0],
 	map__update(MultiMap0, Key, Values, MultiMap).
 
 multi_map__det_update(MultiMap0, Key, Value, MultiMap) :-
@@ -231,7 +258,7 @@
 
 multi_map__set(MultiMap0, Key, Value, MultiMap) :-
 	( map__search(MultiMap0, Key, Values0) ->
-		Values = [Value|Values0],
+		Values = [Value | Values0],
 		map__set(MultiMap0, Key, Values, MultiMap)
 	;
 		map__det_insert(MultiMap0, Key, [Value], MultiMap)
@@ -304,7 +331,7 @@
 :- pred multi_map__count_list(list(A)::in, int::in, int::out) is det.
 
 multi_map__count_list([], X, X).
-multi_map__count_list([_A|As], Count0, Count) :-
+multi_map__count_list([_A | As], Count0, Count) :-
 	Count1 = Count0 + 1,
 	multi_map__count_list(As, Count1, Count).
 
@@ -355,7 +382,7 @@
 	assoc_list(K, list(V))::in, assoc_list(K, list(V))::out) is det.
 
 multi_map__assoc_list_merge([], ListB, ListB).
-multi_map__assoc_list_merge([A|ListA], [], [A|ListA]).
+multi_map__assoc_list_merge([A | ListA], [], [A | ListA]).
 multi_map__assoc_list_merge([(KeyA - DataA) | ListA], [(KeyB - DataB) | ListB],
 		[(Key - Data) | List]) :-
 	compare(Res, KeyA, KeyB),
@@ -391,14 +418,87 @@
 %-----------------------------------------------------------------------------%
 
 multi_map__apply_to_list([], _, []).
-multi_map__apply_to_list([K|Keys], MultiMap, Values) :-
-	map__apply_to_list([K|Keys], MultiMap, Values0),
+multi_map__apply_to_list([K | Keys], MultiMap, Values) :-
+	map__apply_to_list([K | Keys], MultiMap, Values0),
 	list__condense(Values0, Values).
 
 %-----------------------------------------------------------------------------%
 
 multi_map__remove_smallest(MultiMap0, Key, Values, MultiMap) :-
 	map__remove_smallest(MultiMap0, Key, Values, MultiMap).
+
+%-----------------------------------------------------------------------------%
+
+% Functional versions.
+
+multi_map__init = M :-
+	multi_map__init(M).
+
+multi_map__lookup(MultiMap, Key) = Value :-
+	multi_map__lookup(MultiMap, Key, Value).
+
+multi_map__det_insert(MultiMap0, Key, Value) = MultiMap :-
+	multi_map__det_insert(MultiMap0, Key, Value, MultiMap).
+
+multi_map__det_update(MultiMap0, Key, Value) = MultiMap :-
+	multi_map__det_update(MultiMap0, Key, Value, MultiMap).
+
+multi_map__det_replace(MultiMap0, Key, Value) = MultiMap :-
+	multi_map__det_replace(MultiMap0, Key, Value, MultiMap).
+
+multi_map__set(MultiMap0, Key, Value) = MultiMap :-
+	multi_map__set(MultiMap0, Key, Value, MultiMap).
+
+multi_map__keys(MultiMap) = Keys :-
+	multi_map__keys(MultiMap, Keys).
+
+multi_map__values(MultiMap) = Valyes :-
+	multi_map__values(MultiMap, Valyes).
+
+multi_map__to_flat_assoc_list(MultiMap) = AssocList :-
+	multi_map__to_flat_assoc_list(MultiMap, AssocList).
+
+multi_map__from_flat_assoc_list(AssocList) = MultiMap :-
+	multi_map__from_flat_assoc_list(AssocList, MultiMap).
+
+multi_map__to_assoc_list(MultiMap) = AssocList :-
+	multi_map__to_assoc_list(MultiMap, AssocList).
+
+multi_map__from_assoc_list(AssocList) = MultiMap :-
+	multi_map__from_assoc_list(AssocList, MultiMap).
+
+multi_map__from_sorted_assoc_list(AssocList) = MultiMap :-
+	multi_map__from_sorted_assoc_list(AssocList, MultiMap).
+
+multi_map__delete(MultiMap0, Key) = MultiMap :-
+	multi_map__delete(MultiMap0, Key, MultiMap).
+
+multi_map__delete(MultiMap0, Key, Value) = MultiMap :-
+	multi_map__delete(MultiMap0, Key, Value, MultiMap).
+
+multi_map__count(MultiMap0) = Count :-
+	multi_map__count(MultiMap0, Count).
+
+multi_map__all_count(MultiMap0) = Count :-
+	multi_map__all_count(MultiMap0, Count).
+
+multi_map__from_corresponding_lists(Keys, Values) = MultiMap :-
+	multi_map__from_corresponding_lists(Keys, Values, MultiMap).
+
+multi_map__from_corresponding_list_lists(Keys, Values) = MultiMap :-
+	multi_map__from_corresponding_list_lists(Keys, Values, MultiMap).
+
+multi_map__merge(MultiMapA, MultiMapB) = MultiMap :-
+	multi_map__merge(MultiMapA, MultiMapB, MultiMap).
+
+multi_map__select(MultiMap, KeySet) = NewMultiMap :-
+	multi_map__select(MultiMap, KeySet, NewMultiMap).
+
+multi_map__apply_to_list(Keys, MultiMap) = Values :-
+	multi_map__apply_to_list(Keys, MultiMap, Values).
+
+multi_map__optimize(MultiMap0) = MultiMap :-
+	multi_map__optimize(MultiMap0, MultiMap).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
Index: runtime/mercury_bootstrap.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_bootstrap.h,v
retrieving revision 1.34
diff -u -b -r1.34 mercury_bootstrap.h
--- runtime/mercury_bootstrap.h	26 May 2003 10:24:54 -0000	1.34
+++ runtime/mercury_bootstrap.h	30 Mar 2004 13:16:59 -0000
@@ -26,33 +26,6 @@
 #ifndef MR_NO_BACKWARDS_COMPAT
 
 /*
-** bool, TRUE and FALSE appear in the generated code.
-** Once the installed compilers no longer generate these, they should
-** be moved into the `#ifndef MR_NO_BACKWARDS_COMPAT' section.
-*/
-#ifdef IN_GCC
-  /*
-  ** We need to make sure that we pick up GCC's definition of bool, 
-  ** to ensure that we don't define `bool' below.  Otherwise we get
-  ** conflicts because some declarations use the <stdbool.h> definition
-  ** of bool (an enum), and some use our definition (a #define for char)
-  */
-  #include "config.h"
-  #include "system.h"
-#endif
-
-#ifndef bool
-#define bool			char
-#endif
-
-#ifndef TRUE
-#define TRUE			MR_TRUE
-#endif
-#ifndef FALSE
-#define FALSE			MR_FALSE
-#endif
-
-/* 
 ** For a long time the Mercury C types were defined as Char, Float,
 ** Integer, Word, etc.  There will doubtless be lots of C code in
 ** libraries that relies upon these names.  
@@ -122,6 +95,31 @@
 ** To enable it, you must explicitly define MR_EXTRA_BACKWARDS_COMPAT.
 */
 #ifdef	MR_EXTRA_BACKWARDS_COMPAT
+
+/*
+** bool, TRUE and FALSE used to appear in the generated code.
+*/
+#ifdef IN_GCC
+  /*
+  ** We need to make sure that we pick up GCC's definition of bool, 
+  ** to ensure that we don't define `bool' below.  Otherwise we get
+  ** conflicts because some declarations use the <stdbool.h> definition
+  ** of bool (an enum), and some use our definition (a #define for char)
+  */
+  #include "config.h"
+  #include "system.h"
+#endif
+
+#ifndef bool
+#define bool			char
+#endif
+
+#ifndef TRUE
+#define TRUE			MR_TRUE
+#endif
+#ifndef FALSE
+#define FALSE			MR_FALSE
+#endif
 
 #define	COMPARE_EQUAL		MR_COMPARE_EQUAL
 #define	COMPARE_LESS		MR_COMPARE_LESS
Index: runtime/mercury_goto.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_goto.h,v
retrieving revision 1.38
diff -u -b -r1.38 mercury_goto.h
--- runtime/mercury_goto.h	12 Nov 2003 17:06:52 -0000	1.38
+++ runtime/mercury_goto.h	29 Mar 2004 22:28:46 -0000
@@ -16,13 +16,79 @@
 #include "mercury_label.h"	/* for MR_insert_{entry,internal}_label() */
 #include "mercury_dummy.h"	/* for MR_dummy_identify_function() */
 
+/*
+** Definitions for constructing the names of entry and internal labels,
+** and the names of their layout structures.
+*/
+
 #define MR_entry(label)		MR_PASTE2(_entry_,label)
 #define MR_skip(label)		MR_PASTE2(skip_,label)
 
-#define MR_PROC_LAYOUT(label)	(const MR_Proc_Layout *) (MR_Word) \
-				&(MR_PASTE2(mercury_data__proc_layout__,label))
-#define MR_LABEL_LAYOUT(label) 	(const MR_Label_Layout *) (MR_Word) \
-				&(MR_PASTE2(mercury_data__label_layout__,label))
+#define	MR_add_prefix(label)						\
+	MR_PASTE2(mercury__, label)
+
+#define	MR_label_name(proc_label, label)				\
+	MR_PASTE3(proc_label, _i, label)
+
+#define	MR_proc_entry_user_name_base(mod, name, arity, mode)		\
+	MR_PASTE7(mod, __, name, _, arity, _, mode)
+#define	MR_proc_entry_uci_name_base(mod, name, type, arity, mode)	\
+	MR_PASTE9(name, _, mod, __, type, _, arity, _, mode)
+
+#define	MR_proc_entry_user_name(mod, name, arity, mode)			\
+	MR_PASTE2(mercury__,						\
+		MR_proc_entry_user_name_base(mod, name, arity, mode))
+#define	MR_proc_entry_uci_name(mod, name, type, arity, mode)		\
+	MR_PASTE2(mercury__,						\
+		MR_proc_entry_uci_name_base(mod, name, type, arity, mode))
+
+#define	MR_proc_entry_user_name_str(mod, name, arity, mode)		\
+	MR_STRINGIFY(MR_proc_entry_user_name(mod, name, arity, mode))
+#define	MR_proc_entry_uci_name_str(mod, name, type, arity, mode)	\
+	MR_STRINGIFY(MR_proc_entry_uci_name(mod, name, type, arity, mode))
+
+#define	MR_proc_layout_user_name(mod, name, arity, mode)		\
+	MR_PASTE2(mercury_data__proc_layout__,				\
+		MR_proc_entry_user_name(mod, name, arity, mode))
+#define	MR_proc_layout_uci_name(mod, name, type, arity, mode)		\
+	MR_PASTE2(mercury_data__proc_layout__,				\
+		MR_proc_entry_uci_name(mod, name, type, arity, mode))
+
+#define	MR_label_user_name_base(mod, name, a, mode, num)		\
+	MR_label_name(MR_proc_entry_user_name_base(mod, name, a, mode), \
+		num)
+#define	MR_label_uci_name_base(mod, name, type, a, mode, num)		\
+	MR_label_name(MR_proc_entry_uci_name_base(mod, name, type, a, mode), \
+		num)
+
+#define	MR_label_user_name(mod, name, a, mode, num)			\
+	MR_label_name(MR_proc_entry_user_name(mod, name, a, mode), 	\
+		num)
+#define	MR_label_uci_name(mod, name, type, a, mode, num)		\
+	MR_label_name(MR_proc_entry_uci_name(mod, name, type, a, mode), \
+		num)
+
+#define	MR_label_user_name_str(mod, name, arity, mode, num)		\
+	MR_STRINGIFY(MR_label_user_name(mod, name, arity, mode, num))
+#define	MR_label_uci_name_str(mod, name, type, arity, mode, num)	\
+	MR_STRINGIFY(MR_label_uci_name(mod, name, type, arity, mode, num))
+
+#define	MR_label_layout_user_name(mod, name, a, mode, num)		\
+	MR_PASTE2(mercury_data__label_layout__,				\
+		MR_label_user_name(mod, name, a, mode, num))
+#define	MR_label_layout_uci_name(mod, name, type, a, mode, num)		\
+	MR_PASTE2(mercury_data__label_layout__,				\
+		MR_label_uci_name(mod, name, type, a, mode, num))
+
+#define MR_PROC_LAYOUT_NAME(label)					\
+	MR_PASTE2(mercury_data__proc_layout__,label)
+#define MR_LABEL_LAYOUT_NAME(label)					\
+	MR_PASTE2(mercury_data__label_layout__,label)
+
+#define MR_PROC_LAYOUT(label)						\
+	((const MR_Proc_Layout *) (MR_Word) &MR_PROC_LAYOUT_NAME(label))
+#define MR_LABEL_LAYOUT(label) 						\
+	((const MR_Label_Layout *) (MR_Word) &MR_LABEL_LAYOUT_NAME(label))
 
 /*
 ** Passing the name of a label to MR_insert_{internal,entry}_label
@@ -43,19 +109,18 @@
 #endif
 
 /*
-** Taking the address of a label can inhibit gcc's optimization,
-** because it assumes that anything can jump there.
-** Therefore we want to do it only if we're debugging,
-** or if we need the label address for profiling or
+** Taking the address of a label can inhibit gcc's optimization, because it
+** assumes that anything can jump there. Therefore we want to do it only if
+** we're debugging, or if we need the label address for profiling or for
 ** accurate garbage collection.
 **
 ** The versions of the macros below with the _ai, _an or _sl suffix always
-** insert the label into the label table, the difference between them being that
-** the _ai and _an variants do not include a layout structure. If the label
-** *has* a layout structure, use the _sl variant. The difference between the
-** _ai and the _an variants is that the latter always inserts the name of the
-** label as well. This is intended for a small number of labels that are
-** frequently needed in debugging, e.g. do_fail.
+** insert the label into the label table, the difference between them being
+** that the _ai and _an variants do not include a layout structure. If the
+** label *has* a layout structure, use the _sl variant. The difference between
+** the _ai and the _an variants is that the latter always inserts the name
+** of the label as well. This is intended for a small number of labels that
+** are frequently needed in debugging, e.g. do_fail.
 */
 
 #define MR_make_label_ai(n, a, l)		MR_insert_internal(n, a, NULL)
@@ -90,7 +155,7 @@
 
 /*
 ** Note that for the MLDS back-end, the calls to MR_init_entry(),
-** which eventually expand to make_entry(), are only output if
+** which eventually expand to MR_make_entry(), are only output if
 ** the right compiler options are enabled.  So if you change the
 ** condition of this `#ifdef', and you want your changes to apply
 ** to the MLDS back-end too, you may also need to change the
@@ -506,8 +571,8 @@
   	)
   */
 
-
-  /* Since we're jumping into and out of the middle of functions,
+  /*
+  ** Since we're jumping into and out of the middle of functions,
   ** we need to make sure that gcc thinks that (1) the function's address
   ** is used (otherwise it may optimize the whole function away) and
   ** (2) the `return' statement is reachable (otherwise its dataflow
@@ -555,7 +620,6 @@
   /* body of module goes between MR_BEGIN_CODE and MR_END_MODULE */
   #define MR_END_MODULE } }
 
-
   #if defined(MR_USE_ASM_LABELS)
     #define MR_declare_entry(label)		\
 	extern void label(void) __asm__("_entry_" MR_STRINGIFY(label))
@@ -592,6 +656,10 @@
 	MR_PRETEND_ADDRESS_IS_USED(&&label); \
 	MR_make_entry_sl(MR_STRINGIFY(label), label, label)
 
+    #define MR_pretend_address_is_used(label)			\
+	MR_PRETEND_ADDRESS_IS_USED(&&label);
+    #define MR_entry_addr_wrapper(label)
+
     #define MR_ENTRY(label) 		(&label)
 
     #ifndef MR_JUMP
@@ -714,6 +782,7 @@
 		MR_GOTO_LABEL(label);	\
 	}				\
 	static MR_Code* label(void) {
+
   #define MR_init_local(label)		MR_make_local(MR_STRINGIFY(label),    \
 		  				label, label)
   #define MR_init_local_ai(label)	MR_make_local_ai(MR_STRINGIFY(label), \
@@ -728,6 +797,7 @@
 		MR_GOTO_LABEL(label);	\
 	}				\
 	static MR_Code* label(void) {
+
   #define MR_init_label(label)		MR_make_label(MR_STRINGIFY(label),    \
 		  				label, label)
   #define MR_init_label_ai(label)	MR_make_label_ai(MR_STRINGIFY(label), \
@@ -750,6 +820,132 @@
   #define MR_GOTO_LABEL(label) 	MR_GOTO(MR_LABEL(label))
 
 #endif /* !defined(MR_USE_GCC_NONLOCAL_GOTOS) */
+
+#define	MR_decl_user_entry(mod, name, arity, mode) \
+	MR_declare_entry(MR_proc_entry_user_name(mod, name, arity, mode))
+#define	MR_decl_uci_entry(mod, name, type, arity, mode) \
+	MR_declare_entry(MR_proc_entry_uci_name(mod, name, type, arity, mode))
+#define	MR_decl_user_static(mod, name, arity, mode) \
+	MR_declare_static(MR_proc_entry_user_name(mod, name, arity, mode))
+#define	MR_decl_uci_static(mod, name, type, arity, mode) \
+	MR_declare_static(MR_proc_entry_uci_name(mod, name, type, arity, mode))
+
+#define	MR_def_user_extern_entry(mod, name, arity, mode) \
+	MR_define_extern_entry( \
+		MR_proc_entry_user_name(mod, name, arity, mode))
+#define	MR_def_uci_extern_entry(mod, name, type, arity, mode) \
+	MR_define_extern_entry( \
+		MR_proc_entry_uci_name(mod, name, type, arity, mode))
+#define	MR_def_user_entry(mod, name, arity, mode) \
+	MR_define_entry(MR_proc_entry_user_name(mod, name, arity, mode))
+#define	MR_def_uci_entry(mod, name, type, arity, mode) \
+	MR_define_entry(MR_proc_entry_uci_name(mod, name, type, arity, mode))
+#define	MR_def_user_static(mod, name, arity, mode) \
+	MR_define_static(MR_proc_entry_user_name(mod, name, arity, mode))
+#define	MR_def_uci_static(mod, name, type, arity, mode) \
+	MR_define_static(MR_proc_entry_uci_name(mod, name, type, arity, mode))
+
+#if defined(MR_INSERT_LABELS) || defined(MR_MPROF_PROFILE_CALLS)
+  #define MR_need_insert_entry(ai)		1
+#else
+  #define MR_need_insert_entry(ai)		ai
+#endif
+
+#if defined(MR_INSERT_LABELS)
+  #define MR_need_insert_internal(ai)		1
+#else
+  #define MR_need_insert_internal(ai)		ai
+#endif
+
+#if defined(MR_INSERT_ENTRY_LABEL_NAMES)
+  #define MR_need_entry_label_names(an)		1
+#else
+  #define MR_need_entry_label_names(an)		an
+#endif
+
+#if defined(MR_INSERT_INTERNAL_LABEL_NAMES)
+  #define MR_need_internal_label_names(an)	1
+#else
+  #define MR_need_internal_label_names(an)	an
+#endif
+
+#define	MR_init_entry_select(str, addr, layout, ai, an, sl)		\
+  	( MR_need_insert_entry(ai) ?					\
+		MR_insert_entry_label(					\
+			MR_need_entry_label_names(an) ? str : NULL,	\
+			addr, sl ? layout : NULL)			\
+		: (void) 0 )
+
+#define	MR_init_internal_select(str, addr, layout, ai, an, sl)		\
+  	( MR_need_insert_internal(ai) ?					\
+		MR_insert_internal_label(				\
+			MR_need_internal_label_names(an) ? str : NULL,	\
+			addr, sl ? layout : NULL)			\
+		: (void) 0 )
+
+#define MR_init_user_entry_select(mod, name, arity, mode, ai, an, sl)	\
+  	MR_pretend_address_is_used(					\
+		MR_proc_entry_user_name(mod, name, arity, mode))	\
+  	MR_init_entry_select(						\
+		MR_proc_entry_user_name_str(mod, name, arity, mode),	\
+		MR_entry_addr_wrapper(					\
+			MR_proc_entry_user_name(mod, name, arity, mode)),\
+		MR_proc_layout_user_name(mod, name, arity, mode),	\
+		ai, an, sl)
+
+#define MR_init_uci_entry_select(mod, name, type, arity, mode, ai, an, sl) \
+  	MR_pretend_address_is_used(					\
+		MR_proc_entry_uci_name(mod, name, type, arity, mode))	\
+  	MR_init_entry_select(						\
+		MR_proc_entry_uci_name_str(mod, name, type, arity, mode), \
+		MR_entry_addr_wrapper(					\
+			MR_proc_entry_uci_name(mod, name, type, arity, mode)),\
+		MR_proc_layout_uci_name(mod, name, type, arity, mode),	\
+		ai, an, sl)
+
+#define MR_init_user_label_select(mod, name, arity, mode, num, ai, an, sl) \
+  	MR_init_label_select(						\
+		MR_label_user_name_str(mod, name, arity, mode, num),	\
+		MR_entry_addr_wrapper(					\
+			MR_label_user_name(mod, name, arity, mode, num)),\
+		MR_label_layout_user_name(mod, name, arity, mode, num),	\
+		ai, an, sl)
+
+#define MR_init_uci_label_select(mod, name, type, arity, mode, num, ai, an, sl)\
+  	MR_init_label_select(						\
+		MR_label_uci_name_str(mod, name, type, arity, mode, num), \
+		MR_entry_addr_wrapper(					\
+			MR_label_uci_name(mod, name, type, arity, mode, num)),\
+		MR_label_layout_uci_name(mod, name, type, arity, mode, num), \
+		ai, an, sl)
+
+#define	MR_init_user_entry_ai(mod, name, arity, mode)			\
+	MR_init_user_entry_select(mod, name, arity, mode, 1, 0, 0)
+#define	MR_init_user_entry_an(mod, name, arity, mode)			\
+	MR_init_user_entry_select(mod, name, arity, mode, 1, 1, 0)
+#define	MR_init_user_entry_sl(mod, name, arity, mode)			\
+	MR_init_user_entry_select(mod, name, arity, mode, 0, 0, 1)
+
+#define	MR_init_uci_entry_ai(mod, name, type, arity, mode)		\
+	MR_init_uci_entry_select(mod, name, type, arity, mode, 1, 0, 0)
+#define	MR_init_uci_entry_an(mod, name, type, arity, mode)		\
+	MR_init_uci_entry_select(mod, name, type, arity, mode, 1, 1, 0)
+#define	MR_init_uci_entry_sl(mod, name, type, arity, mode)		\
+	MR_init_uci_entry_select(mod, name, type, arity, mode, 0, 0, 1)
+
+#define	MR_init_user_local_ai(mod, name, arity, mode, num)		\
+	MR_init_user_local_select(mod, name, arity, mode, num, 1, 0, 0)
+#define	MR_init_user_local_an(mod, name, arity, mode, num)		\
+	MR_init_user_local_select(mod, name, arity, mode, num, 1, 1, 0)
+#define	MR_init_user_local_sl(mod, name, arity, mode, num)		\
+	MR_init_user_local_select(mod, name, arity, mode, num, 0, 0, 1)
+
+#define	MR_init_uci_local_ai(mod, name, type, arity, mode, num)		\
+	MR_init_uci_local_select(mod, name, type, arity, mode, num, 1, 0, 0)
+#define	MR_init_uci_local_an(mod, name, type, arity, mode, num)		\
+	MR_init_uci_local_select(mod, name, type, arity, mode, num, 1, 1, 0)
+#define	MR_init_uci_local_sl(mod, name, type, arity, mode, num)		\
+	MR_init_uci_local_select(mod, name, type, arity, mode, num, 0, 0, 1)
 
 /* definitions for computed gotos */
 
Index: runtime/mercury_misc.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_misc.h,v
retrieving revision 1.23
diff -u -b -r1.23 mercury_misc.h
--- runtime/mercury_misc.h	2 Dec 2002 11:25:47 -0000	1.23
+++ runtime/mercury_misc.h	30 Mar 2004 15:09:00 -0000
@@ -43,4 +43,15 @@
 
 extern	void	MR_perform_registered_exception_cleanups(void);
 
+/*
+** These macro are shorthands to allow reductions in the size of compiler
+** generated C source files.
+*/
+
+#define	MR_COMMON(cellnum)					\
+	((MR_Word *) &MR_PASTE2(mercury_common_, cellnum))
+
+#define	MR_TAG_COMMON(tag, cellnum)				\
+	(MR_mkword(MR_mktag(tag), MR_COMMON(cellnum)))
+
 #endif /* not MERCURY_MISC_H */
Index: runtime/mercury_stack_layout.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stack_layout.h,v
retrieving revision 1.75
diff -u -b -r1.75 mercury_stack_layout.h
--- runtime/mercury_stack_layout.h	12 Mar 2004 06:02:06 -0000	1.75
+++ runtime/mercury_stack_layout.h	30 Mar 2004 15:07:04 -0000
@@ -34,6 +34,7 @@
 #include "mercury_tags.h"
 #include "mercury_type_info.h"			/* for MR_PseudoTypeInfo */
 #include "mercury_proc_id.h"			/* for MR_Proc_Id */
+#include "mercury_goto.h"			/* for MR_PROC_LAYOUT etc */
 
 /*-------------------------------------------------------------------------*/
 /*
@@ -414,6 +415,43 @@
 
 #define MR_MAKE_INTERNAL_LAYOUT(entry, labelnum)			\
 	MR_MAKE_INTERNAL_LAYOUT_WITH_ENTRY(entry##_i##labelnum, entry)
+
+/*
+** These macros are used as shorthands in generated C source files.
+** The first two arguments are the entry label name and the label number;
+** the others are the fields of MR_Label_Layouts.
+*/
+
+#define	MR_DEF_LL(e, ln, port, h, path, vc, lt, vn, tv)			\
+	static const MR_Label_Layout 					\
+		MR_LABEL_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)) \
+	= {								\
+		MR_PROC_LAYOUT(MR_add_prefix(e)),			\
+		MR_PASTE2(MR_PORT_, port),				\
+		(h), (path), (vc),					\
+		((const void *) lt),					\
+		((const MR_uint_least16_t *) vn),			\
+		((const MR_Type_Param_Locns *) tv)			\
+	}
+
+#define	MR_DEF_LLNVI(e, ln, port, h, path)				\
+	static const MR_Label_Layout_No_Var_Info			\
+		MR_LABEL_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)) \
+	= {								\
+		MR_PROC_LAYOUT(MR_add_prefix(e)),			\
+		MR_PASTE2(MR_PORT_, port),				\
+		(h), (path), -1						\
+	}
+
+#define MR_DECL_LL(e, ln)						\
+	MR_declare_label(MR_label_name(MR_add_prefix(e), ln));		\
+	static const MR_Label_Layout 					\
+		MR_LABEL_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)); \
+
+#define MR_DECL_LLNVI(e, ln)						\
+	MR_declare_label(MR_label_name(MR_add_prefix(e), ln));		\
+	static const MR_Label_Layout_No_Var_Info			\
+		MR_LABEL_LAYOUT_NAME(MR_label_name(MR_add_prefix(e), ln)); \
 
 /*-------------------------------------------------------------------------*/
 /*
Index: runtime/mercury_trace_base.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_trace_base.h,v
retrieving revision 1.39
diff -u -b -r1.39 mercury_trace_base.h
--- runtime/mercury_trace_base.h	17 Mar 2004 00:34:04 -0000	1.39
+++ runtime/mercury_trace_base.h	30 Mar 2004 15:00:16 -0000
@@ -55,8 +55,21 @@
 
 #define MR_trace_incr_seq()		((MR_Word) ++MR_trace_call_seqno)
 #define MR_trace_incr_depth()		((MR_Word) ++MR_trace_call_depth)
-#define MR_trace_reset_depth(d)		(MR_trace_call_depth = \
-						(MR_Unsigned) (d))
+
+#define	MR_trace_fill_std_slots(s1, s2, s3)			\
+	(((s1) = MR_trace_event_number),			\
+	((s2) = MR_trace_incr_seq()),				\
+	((s3) = MR_trace_incr_depth()))				\
+
+#define MR_trace_reset_depth(d)					\
+	(MR_trace_call_depth = (MR_Unsigned) (d))
+
+#define MR_trace_reset_depth_from_full(d)			\
+	((MR_trace_call_depth = (MR_Unsigned) (d)),		\
+	(MR_trace_from_full = MR_TRUE))
+#define MR_trace_reset_depth_from_shallow(d)			\
+	((MR_trace_call_depth = (MR_Unsigned) (d)),		\
+	(MR_trace_from_full = MR_FALSE))
 
 /*
 ** MR_trace is called from Mercury modules compiled with tracing.
@@ -396,5 +409,19 @@
 MR_declare_entry(MR_do_trace_redo_fail_deep);
 
 #endif	/* !MR_HIGHLEVEL_CODE */
+
+/*
+** The compiler emits the following macro at each trace event.
+*/
+
+#define	MR_EVENT(label)							\
+	{								\
+		MR_Code *MR_jumpaddr;					\
+		MR_save_transient_registers();				\
+		MR_jumpaddr = MR_trace((const MR_Label_Layout *)	\
+			&MR_LABEL_LAYOUT_NAME(MR_add_prefix(label)));	\
+		MR_restore_transient_registers();			\
+		if (MR_jumpaddr != NULL) MR_GOTO(MR_jumpaddr);		\
+	}
 
 #endif /* MERCURY_TRACE_BASE_H */
Index: runtime/mercury_type_info.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_type_info.h,v
retrieving revision 1.111
diff -u -b -r1.111 mercury_type_info.h
--- runtime/mercury_type_info.h	19 Feb 2004 07:54:43 -0000	1.111
+++ runtime/mercury_type_info.h	30 Mar 2004 13:00:56 -0000
@@ -1379,6 +1379,35 @@
     MR_DEFINE_TYPE_CTOR_INFO_FLAG(m, n, a, cr,                          \
         MR_DEFAULT_TYPE_CTOR_INFO_FLAG)
 
+/*
+** The macros below are used to reduce the sizes of compiler-generated
+** .c files, especially in debug grades.
+*/
+
+#define MR_CTOR_ADDR(m, n, a)                                           \
+    (MR_Word *) &MR_TYPE_CTOR_INFO_NAME(m, n, a)
+#define MR_CTOR0_ADDR(m, n)                                             \
+    (MR_Word *) &MR_TYPE_CTOR_INFO_NAME(m, n, 0)
+#define MR_CTOR1_ADDR(m, n)                                             \
+    (MR_Word *) &MR_TYPE_CTOR_INFO_NAME(m, n, 1)
+
+#define MR_INT_CTOR_ADDR                                                \
+    (MR_Word *) &MR_TYPE_CTOR_INFO_NAME(builtin, int, 0)
+#define MR_FLOAT_CTOR_ADDR                                              \
+    (MR_Word *) &MR_TYPE_CTOR_INFO_NAME(builtin, float, 0)
+#define MR_CHAR_CTOR_ADDR                                               \
+    (MR_Word *) &MR_TYPE_CTOR_INFO_NAME(builtin, character, 0)
+#define MR_STRING_CTOR_ADDR                                             \
+    (MR_Word *) &MR_TYPE_CTOR_INFO_NAME(builtin, string, 0)
+#define MR_IO_CTOR_ADDR                                                 \
+    (MR_Word *) &MR_TYPE_CTOR_INFO_NAME(io, state, 0)
+#define MR_BOOL_CTOR_ADDR                                               \
+    (MR_Word *) &MR_TYPE_CTOR_INFO_NAME(bool, bool, 0)
+#define MR_LIST_CTOR_ADDR                                               \
+    (MR_Word *) &MR_TYPE_CTOR_INFO_NAME(list, list, 1)
+#define MR_TYPE_INFO_CTOR_ADDR                                          \
+    (MR_Word *) &MR_TYPE_CTOR_INFO_NAME(private_builtin, type_info, 1)
+
 /*---------------------------------------------------------------------------*/
 
 /*
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 samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
Index: tests/hard_coded/pragma_import.m
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/hard_coded/pragma_import.m,v
retrieving revision 1.4
diff -u -b -r1.4 pragma_import.m
--- tests/hard_coded/pragma_import.m	5 Dec 2000 02:10:57 -0000	1.4
+++ tests/hard_coded/pragma_import.m	31 Mar 2004 04:40:06 -0000
@@ -57,8 +57,8 @@
 	typedef MR_Integer Int;
 	void cfoo(Int, Int *, MR_Float, MR_Float *, MR_String, MR_String *);
 	Int cbar(Int, Int *);
-	bool cbaz(Int, Int *, Int *);
-	bool cquux(Int, Int *);
+	MR_bool cbaz(Int, Int *, Int *);
+	MR_bool cquux(Int, Int *);
 ").
 
 :- pragma c_code("
@@ -74,13 +74,13 @@
 	return a1 + *a2;
 }
 
-bool cbaz(Int a1, Int *a2, Int *a3) {
+MR_bool cbaz(Int a1, Int *a2, Int *a3) {
 	*a2 = a1 + 1;
 	*a3 = a1 + 2;
 	return a1 + *a2 + *a3 > 0;
 }
 
-bool cquux(Int a1, Int *a2) {
+MR_bool cquux(Int a1, Int *a2) {
 	*a2 = a1 + 1;
 	return a1 + *a2 > 0;
 }
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/recompilation
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 util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list