[m-dev.] for review: deep profiling changes [part 1/3]

Thomas Conway conway at cs.mu.OZ.AU
Sat Feb 26 15:24:29 AEDT 2000


Hi

Zoltan, I think you'll want to look closely at this, and I guess
Fergus will too.

-- 
 Thomas Conway )O+     Every sword has two edges.
     Mercurian            <conway at cs.mu.oz.au>


Add support for deep profiling.
See comments in runtime/mercury_prof_deep.{c,h} and compiler/profiling.m

Outstanding issues:
	This change does not include the browser for deep profiles.

	Linkage! The stuff for deciding the linkage of static data seems
	to be a bit of a mess. There are two mechanisms - one of which
	is described in the source as redundant, but is actually useful,
	and one described as the replacement which doesn't quite do the
	right thing.

	I'm not certain that deep profiling works correctly with
	exceptions. Untested at this stage, so probably needs a bit of
	tweaking.

	Typeclasses are not fully addressed.

	In the absence of a browser, I haven't added to the NEWS file
	yet. Hopefully, I'll be able to add the browser in a week or so,
	and will do so then.

compiler/*.m:
	Add a new lvalue `global/2' which denotes a global variable.

	Add a new rvalue `c_func/4' which denotes a call to a function in C.

	If deep profiling is enabled, add a pointer to the MR_SCCId in the
	MR_Stack_Layout_Entry structures, and add pointers to the
	MR_Stack_Layout_Entry structures for the unify, index and compare
	preds in the type_ctor_layout strcutures.

	If we are in a grade that uses stack layouts, then include a
	pointer to the MR_Stack_Layout_Proc_Id generated for the procedure
	in any closure layouts we construct, rather than making one as we
	go. This is necessary with deep profiling enabled because otherwise
	we can't get our hands on the correct MR_SCCId for the closure.

	Generate static MR_SCCId structures which include the info about
	the call-sites in the SCC.

	Modify the code generator to emit updates of the
	MR_prof_current_scc and MR_prof_current_proc pointers before
	and after calls, and in procedure prologues and epilogues.

	Modify the code generator so that when we export procedures, we
	update the deep profiling pointers appropriately.

library/array.m:
library/builtin.m:
library/exception.m:
library/private_builtin.m:
library/std_util.m:
	Add hand-written structures for deep profiling for hand-defined
	procedures.

runtime/Mmakefile:
	Include the two new files: mercury_prof_deep.{c,h}.

runtime/mercury_ho_call.h:
	Make the MR_Stack_Layout_Proc_Id member of MR_Closure_Layout
	be a pointer rather than a member.

runtime/mercury_ho_call.c:
	Add hand written deep profiling structures for unify, index and
	compare. Include support for deep profiling in them.

runtime/mercury_prof.c:
	Export a couple of functions used by mercury_prof_deep.c.
	Modify stuff to work with deep profiling.

runtime/mercury_prof.h:
	Conditionally define a few things on MR_PROFILE_DEEP.

runtime/mercury_stack_layout.h:
	Include a pointer to the MR_SCCId structure in the Proc_Id layouts.

runtime/mercury_type_info.h:
	Add pointers to the MR_Stack_Layout_Entry structures for unify,
	index and compare to MR_TypeCtorInfo.

runtime/mercury_wrapper.c:
	Add hand-written deep profiling structures for do_interpreter, and
	modify the code to support deep profiling.
	Add program_entry_layout - a pointer to the MR_Stack_Layout_Entry
	for the program entry point.


Index: compiler/base_type_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/base_type_info.m,v
retrieving revision 1.32
diff -u -r1.32 base_type_info.m
--- compiler/base_type_info.m	2000/02/08 06:59:23	1.32
+++ compiler/base_type_info.m	2000/02/25 23:37:58
@@ -158,6 +158,20 @@
 		_Status, Elim, Procs, HldsDefn),
 	base_type_info__construct_pred_addrs(Procs, Elim, ModuleInfo, 
 		PredAddrArgs),
+
+	module_info_globals(ModuleInfo, Globals),
+	globals__lookup_bool_option(Globals, profile_deep, DeepProfiling),
+	( DeepProfiling = yes ->
+		map((pred(proc(PredId, ProcId)::in, ProcLayout::out) is det :-
+		    code_util__make_local_entry_label(ModuleInfo,
+				PredId, ProcId, no, Entry),
+		    ProcLayout = yes(const(data_addr_const(
+		    		data_addr(ModuleName, proc_layout(Entry)))))
+		), Procs, ProcLayouts)
+	;
+		ProcLayouts = []
+	),
+
 	ArityArg = yes(const(int_const(TypeArity))),
 
 /******
@@ -169,7 +183,6 @@
 ******/
 	Exported = yes,
 
-	module_info_globals(ModuleInfo, Globals),
 	globals__lookup_bool_option(Globals, type_layout, TypeLayoutOption),
 	(
 		TypeLayoutOption = yes
@@ -186,7 +199,7 @@
 		VersionArg = yes(const(int_const(
 			type_ctor_info_rtti_version))),
 		list__append(PredAddrArgs, [TypeCtorArg, FunctorsArg, LayoutArg,
-			ModuleArg, NameArg, VersionArg], FinalArgs)
+			ModuleArg, NameArg, VersionArg|ProcLayouts], FinalArgs)
 	;
 		FinalArgs = PredAddrArgs
 	),
Index: compiler/call_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/call_gen.m,v
retrieving revision 1.137
diff -u -r1.137 call_gen.m
--- compiler/call_gen.m	1999/11/15 00:42:08	1.137
+++ compiler/call_gen.m	2000/02/25 23:38:02
@@ -57,7 +57,7 @@
 
 :- import_module hlds_module, hlds_data, code_util, rl.
 :- import_module arg_info, type_util, mode_util, unify_proc, instmap.
-:- import_module trace, globals, options.
+:- import_module trace, globals, options, profiling.
 :- import_module std_util, bool, int, tree, map.
 :- import_module varset, require, string.
 
@@ -83,6 +83,20 @@
 		% Move the input arguments to their registers.
 	code_info__setup_call(ArgsInfos, caller, SetupCode),
 
+		% If deep profiling is enabled, then we need to
+		% emit code to update the position pointers, before
+		% and after (down below) the call.
+	code_info__get_globals(Globals),
+	{ globals__lookup_bool_option(Globals, profile_deep, DeepProfiling) },
+	{ goal_info_get_context(GoalInfo, Context) },
+	{ PPId = proc(PredId, ModeId) },
+	(
+		{ DeepProfiling = yes },
+		profiling__pre_call_update(PPId, Context, ProfilingEntryCode)
+	;
+		{ DeepProfiling = no },
+		{ ProfilingEntryCode = empty }
+	),
 	trace__prepare_for_call(TraceCode),
 
 		% Figure out what locations are live at the call point,
@@ -112,7 +126,6 @@
 	code_info__make_entry_label(ModuleInfo, PredId, ModeId, yes, Address),
 	code_info__get_next_label(ReturnLabel),
 	{ call_gen__call_comment(CodeModel, CallComment) },
-	{ goal_info_get_context(GoalInfo, Context) },
 	{ CallCode = node([
 		call(Address, label(ReturnLabel), ReturnLiveLvalues, Context,
 			CallModel)
@@ -121,6 +134,15 @@
 			- "continuation label"
 	]) },
 
+	(
+		{ DeepProfiling = yes },
+		profiling__post_call_update(ProfilingExitCode)
+	;
+		{ DeepProfiling = no },
+		{ ProfilingExitCode = empty }
+	),
+
+	call_gen__rebuild_registers(ArgsInfos),
 	call_gen__handle_failure(CodeModel, FailHandlingCode),
 
 	{ Code =
@@ -128,9 +150,13 @@
 		tree(FlushCode,
 		tree(SetupCode,
 		tree(TraceCode,
+		tree(ProfilingEntryCode,
 		tree(LiveCode,
 		tree(CallCode,
-		     FailHandlingCode))))))
+			% We must update the profiling pointers before
+			% we handle the failure of the call.
+		tree(ProfilingExitCode,
+		     FailHandlingCode))))))))
 	}.
 
 %---------------------------------------------------------------------------%
@@ -185,6 +211,19 @@
 		% the immediate arguments twice.
 	call_gen__generic_call_setup(GenericCall, InVars, OutVars, SetupCode),
 
+	code_info__get_globals(Globals),
+	{ globals__lookup_bool_option(Globals, profile_deep, DeepProfiling) },
+	{ goal_info_get_context(GoalInfo, Context) },
+	(
+		{ DeepProfiling = yes },
+		{ ClosureRval = lval(reg(r, 1)) },
+		profiling__pre_ho_call_update(ClosureRval, Context,
+			ProfilingEntryCode)
+	;
+		{ DeepProfiling = no },
+		{ ProfilingEntryCode = empty }
+	),
+
 	trace__prepare_for_call(TraceCode),
 
 		% We must update the code generator state to reflect
@@ -196,7 +235,6 @@
 		ReturnLiveLvalues),
 
 	code_info__get_next_label(ReturnLabel),
-	{ goal_info_get_context(GoalInfo, Context) },
 	{ CallCode = node([
 		livevals(LiveVals)
 			- "",
@@ -207,6 +245,14 @@
 			- "Continuation label"
 	]) },
 
+	(
+		{ DeepProfiling = yes },
+		profiling__post_call_update(ProfilingExitCode)
+	;
+		{ DeepProfiling = no },
+		{ ProfilingExitCode = empty }
+	),
+
 	call_gen__handle_failure(CodeModel, FailHandlingCode),
 
 	{ Code =
@@ -215,8 +261,10 @@
 		tree(ImmediateCode,
 		tree(SetupCode,
 		tree(TraceCode,
+		tree(ProfilingEntryCode,
 		tree(CallCode,
-		     FailHandlingCode))))))
+		tree(ProfilingExitCode,
+		     FailHandlingCode))))))))
 	}.
 
 	% The registers before the first input argument are all live.
Index: compiler/code_exprn.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_exprn.m,v
retrieving revision 1.61
diff -u -r1.61 code_exprn.m
--- compiler/code_exprn.m	2000/01/14 01:10:12	1.61
+++ compiler/code_exprn.m	2000/02/25 23:38:06
@@ -628,6 +628,11 @@
 	code_exprn__add_rval_reg_dependencies(Rval1).
 code_exprn__add_rval_reg_dependencies(mem_addr(MemRef)) -->
 	code_exprn__add_mem_ref_reg_dependencies(MemRef).
+code_exprn__add_rval_reg_dependencies(c_func(_, _, Args, _)) -->
+	list__foldl(lambda([Arg::in, Exprn0::in, Exprn::out] is det, (
+		Arg = _Type - Rval,
+		code_exprn__add_rval_reg_dependencies(Rval, Exprn0, Exprn)
+	)), Args).
 
 :- pred code_exprn__add_mem_ref_reg_dependencies(mem_ref,
 	exprn_info, exprn_info).
@@ -701,6 +706,11 @@
 	code_exprn__rem_rval_reg_dependencies(Rval1).
 code_exprn__rem_rval_reg_dependencies(mem_addr(MemRef)) -->
 	code_exprn__rem_mem_ref_reg_dependencies(MemRef).
+code_exprn__rem_rval_reg_dependencies(c_func(_, _, Args, _)) -->
+	list__foldl(lambda([Arg::in, Exprn0::in, Exprn::out] is det, (
+		Arg = _Type - Rval,
+		code_exprn__rem_rval_reg_dependencies(Rval, Exprn0, Exprn)
+	)), Args).
 
 :- pred code_exprn__rem_mem_ref_reg_dependencies(mem_ref,
 	exprn_info, exprn_info).
Index: compiler/code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_gen.m,v
retrieving revision 1.73
diff -u -r1.73 code_gen.m
--- compiler/code_gen.m	2000/02/10 04:37:29	1.73
+++ compiler/code_gen.m	2000/02/25 23:38:09
@@ -48,6 +48,7 @@
 :- pred generate_proc_code(pred_info::in, proc_info::in,
 	proc_id::in, pred_id::in, module_info::in, globals::in,
 	global_data::in, global_data::out, int::in, int::out,
+	scc_info::in, scc_info::out,
 	c_procedure::out) is det.
 
 		% Translate a HLDS goal to LLDS.
@@ -62,7 +63,7 @@
 
 :- import_module call_gen, unify_gen, ite_gen, switch_gen, disj_gen.
 :- import_module par_conj_gen, pragma_c_gen, commit_gen.
-:- import_module continuation_info, trace, options, hlds_out.
+:- import_module profiling, continuation_info, trace, options, hlds_out.
 :- import_module code_aux, middle_rec, passes_aux, llds_out.
 :- import_module code_util, type_util, mode_util, goal_util.
 :- import_module prog_data, prog_out, instmap.
@@ -134,32 +135,36 @@
 		[]
 	),
 	{ module_info_get_cell_count(ModuleInfo0, CellCount0) },
+	{ module_info_get_scc_info(ModuleInfo0, SCCInfo0) },
 	globals__io_get_globals(Globals),
 	{ generate_proc_list_code(ProcIds, PredId, PredInfo, ModuleInfo0,
 		Globals, GlobalData0, GlobalData, CellCount0, CellCount,
-		[], Code) },
-	{ module_info_set_cell_count(ModuleInfo0, CellCount, ModuleInfo) }.
+		SCCInfo0, SCCInfo, [], Code) },
+	{ module_info_set_cell_count(ModuleInfo0, CellCount, ModuleInfo1) },
+	{ module_info_set_scc_info(ModuleInfo1, SCCInfo, ModuleInfo) }.
 
 	% Translate all the procedures of a HLDS predicate to LLDS.
 
 :- pred generate_proc_list_code(list(proc_id)::in, pred_id::in, pred_info::in,
 	module_info::in, globals::in, global_data::in, global_data::out,
-	int::in, int::out, list(c_procedure)::in, list(c_procedure)::out)
-	is det.
+	int::in, int::out, scc_info::in, scc_info::out,
+	list(c_procedure)::in, list(c_procedure)::out) is det.
 
 generate_proc_list_code([], _PredId, _PredInfo, _ModuleInfo, _Globals,
-		GlobalData, GlobalData, CellCount, CellCount, Procs, Procs).
+		GlobalData, GlobalData, CellCount, CellCount,
+		SCCInfo, SCCInfo, Procs, Procs).
 generate_proc_list_code([ProcId | ProcIds], PredId, PredInfo, ModuleInfo0,
 		Globals, GlobalData0, GlobalData, CellCount0, CellCount,
-		Procs0, Procs) :-
+		SCCInfo0, SCCInfo, Procs0, Procs) :-
 	pred_info_procedures(PredInfo, ProcInfos),
 	map__lookup(ProcInfos, ProcId, ProcInfo),
 	generate_proc_code(PredInfo, ProcInfo, ProcId, PredId, ModuleInfo0,
 		Globals, GlobalData0, GlobalData1, CellCount0, CellCount1,
+		SCCInfo0, SCCInfo1,
 		Proc),
 	generate_proc_list_code(ProcIds, PredId, PredInfo, ModuleInfo0,
 		Globals, GlobalData1, GlobalData, CellCount1, CellCount,
-		[Proc | Procs0], Procs).
+		SCCInfo1, SCCInfo, [Proc | Procs0], Procs).
 
 %---------------------------------------------------------------------------%
 
@@ -181,7 +186,8 @@
 %---------------------------------------------------------------------------%
 
 generate_proc_code(PredInfo, ProcInfo, ProcId, PredId, ModuleInfo, Globals,
-		GlobalData0, GlobalData, CellCount0, CellCount, Proc) :-
+		GlobalData0, GlobalData, CellCount0, CellCount,
+		SCCInfo0, SCCInfo, Proc) :-
 	proc_info_interface_determinism(ProcInfo, Detism),
 	proc_info_interface_code_model(ProcInfo, CodeModel),
 	proc_info_goal(ProcInfo, Goal),
@@ -209,15 +215,25 @@
 		% needed for model_non procedures only if we are doing
 		% execution tracing.
 	code_info__init(SaveSuccip, Globals, PredId, ProcId, ProcInfo,
-		FollowVars, ModuleInfo, CellCount0, OutsideResumePoint,
-		TraceSlotInfo, CodeInfo0),
+		FollowVars, ModuleInfo, CellCount0, SCCInfo0,
+		OutsideResumePoint, TraceSlotInfo, CodeInfo0),
 
+		% If we're doing deep profiling, we need to reserve
+		% stack slots for saving the current proc and current scc.
+	globals__lookup_bool_option(Globals, profile_deep, ProfDetail),
+	( ProfDetail = yes ->
+		profiling__setup(CodeInfo0, CodeInfo1)
+	;
+		CodeInfo1 = CodeInfo0
+	),
+
 		% Generate code for the procedure.
 	generate_category_code(CodeModel, Goal, OutsideResumePoint,
 		TraceSlotInfo, CodeTree, MaybeTraceCallLabel, FrameInfo,
-		CodeInfo0, CodeInfo),
+		CodeInfo1, CodeInfo),
 	code_info__get_max_reg_in_use_at_trace(MaxTraceReg, CodeInfo, _),
 	code_info__get_cell_count(CellCount, CodeInfo, _),
+	code_info__get_scc_info(SCCInfo, CodeInfo, _),
 
 		% Turn the code tree into a list.
 	tree__flatten(CodeTree, FragmentList),
@@ -243,9 +259,29 @@
 		code_info__get_layout_info(InternalMap, CodeInfo, _),
 		code_util__make_local_entry_label(ModuleInfo, PredId, ProcId,
 			no, EntryLabel),
-		ProcLayout = proc_layout_info(EntryLabel, Detism, TotalSlots,
-			MaybeSuccipSlot, MaybeTraceCallLabel, MaxTraceReg,
-			TraceSlotInfo, ForceProcId, InternalMap),
+		( ProfDetail = yes ->
+			SCCInfo = scc_info(SCCIdMap, _SCCDataMap),
+			( map__search(SCCIdMap, proc(PredId, ProcId), SCCId) ->
+				SCCId = scc_id(SCCModuleName, SCCIdNum),
+				SCCIdRval = const(data_addr_const(
+					data_addr(SCCModuleName,
+							scc_id(SCCIdNum))))
+			;
+					% If the pred_proc_id wasn't in
+					% the map, then make the scc_id be
+					% a null pointer since this must be
+					% a leaf procedure.
+				SCCIdRval = const(int_const(0))
+			),
+			MSCCId = yes(SCCIdRval)
+		;
+			MSCCId = no
+		),
+		pred_info_import_status(PredInfo, ImportStatus),
+		ProcLayout = proc_layout_info(ImportStatus, EntryLabel, Detism,
+			MSCCId, TotalSlots, MaybeSuccipSlot,
+			MaybeTraceCallLabel, MaxTraceReg, TraceSlotInfo,
+			ForceProcId, InternalMap),
 		global_data_add_new_proc_layout(GlobalData0,
 			proc(PredId, ProcId), ProcLayout, GlobalData1)
 	;
@@ -390,6 +426,8 @@
 	{ Goal = _ - GoalInfo },
 	{ goal_info_get_context(GoalInfo, BodyContext) },
 	code_info__get_maybe_trace_info(MaybeTraceInfo),
+	code_info__get_globals(Globals),
+	{ globals__lookup_bool_option(Globals, profile_deep, ProfD) },
 	( { MaybeTraceInfo = yes(TraceInfo) } ->
 		trace__generate_external_event_code(call, TraceInfo,
 			BodyContext, TraceCallLabel, _TypeInfos,
@@ -400,6 +438,11 @@
 			FrameInfo, EntryCode),
 		code_gen__generate_exit(model_semi, FrameInfo, TraceSlotInfo,
 			BodyContext, RestoreDeallocCode, ExitCode),
+		( { ProfD = yes } ->
+			profiling__failure_epilogue(ProfFail)
+		;
+			{ ProfFail = empty }
+		),
 
 		code_info__generate_resume_point(ResumePoint, ResumeCode),
 		{ code_info__resume_point_vars(ResumePoint, ResumeVarList) },
@@ -415,11 +458,12 @@
 			tree(BodyCode,
 			tree(ExitCode,
 			tree(ResumeCode,
+			tree(ProfFail,
 			tree(TraceFailCode,
 			tree(RestoreDeallocCode,
-			     FailCode)))))))
+			     FailCode))))))))
 		}
-	;
+	; % XXX ProfD = yes -> ....
 		{ MaybeTraceCallLabel = no },
 		code_gen__generate_goal(model_semi, Goal, BodyCode),
 		code_gen__generate_entry(model_semi, Goal, ResumePoint,
@@ -440,6 +484,8 @@
 generate_category_code(model_non, Goal, ResumePoint, TraceSlotInfo, Code,
 		MaybeTraceCallLabel, FrameInfo) -->
 	code_info__get_maybe_trace_info(MaybeTraceInfo),
+	code_info__get_globals(Globals),
+	{ globals__lookup_bool_option(Globals, profile_deep, ProfD) },
 	{ Goal = _ - GoalInfo },
 	{ goal_info_get_context(GoalInfo, BodyContext) },
 	( { MaybeTraceInfo = yes(TraceInfo) } ->
@@ -453,6 +499,12 @@
 		code_gen__generate_exit(model_non, FrameInfo, TraceSlotInfo,
 			BodyContext, _, ExitCode),
 
+		( { ProfD = yes } ->
+			profiling__failure_epilogue(ProfFail)
+		;
+			{ ProfFail = empty }
+		),
+
 		code_info__generate_resume_point(ResumePoint, ResumeCode),
 		{ code_info__resume_point_vars(ResumePoint, ResumeVarList) },
 		{ set__list_to_set(ResumeVarList, ResumeVars) },
@@ -477,11 +529,12 @@
 			tree(BodyCode,
 			tree(ExitCode,
 			tree(ResumeCode,
+			tree(ProfFail,
 			tree(TraceFailCode,
 			tree(DiscardTraceTicketCode,
-			     FailCode)))))))
+			     FailCode))))))))
 		}
-	;
+	; % XXX ProfD = yes -> ....
 		{ MaybeTraceCallLabel = no },
 		code_gen__generate_goal(model_non, Goal, BodyCode),
 		code_gen__generate_entry(model_non, Goal, ResumePoint,
@@ -563,6 +616,12 @@
 	;
 		{ TraceFillCode = empty }
 	),
+	code_info__get_globals(Globals),
+	( { globals__lookup_bool_option(Globals, profile_deep, yes) } ->
+		profiling__prologue(Profiling)
+	;
+		{ Profiling = empty }
+	),
 
 	{ predicate_module(ModuleInfo, PredId, ModuleName) },
 	{ predicate_name(ModuleInfo, PredId, PredName) },
@@ -629,7 +688,8 @@
 		tree(AllocCode,
 		tree(SaveSuccipCode,
 		tree(TraceFillCode,
-		     EndComment)))))
+		tree(Profiling,
+		     EndComment))))))
 	}.
 
 %---------------------------------------------------------------------------%
@@ -761,6 +821,13 @@
 			{ TraceExitCode = empty },
 			{ TypeInfoLvals = [] }
 		),
+		code_info__get_globals(Globals),
+		{ globals__lookup_bool_option(Globals, profile_deep, ProfD) },
+		( { ProfD = yes } ->
+			profiling__success_epilogue(ProfSucc)
+		;
+			{ ProfSucc = empty }
+		),
 
 			% Find out which locations should be mentioned
 			% in the success path livevals(...) annotation,
@@ -778,8 +845,9 @@
 			]) },
 			{ AllSuccessCode =
 				tree(TraceExitCode,
+				tree(ProfSucc,
 				tree(RestoreDeallocCode,
-				     SuccessCode))
+				     SuccessCode)))
 			}
 		;
 			{ CodeModel = model_semi },
@@ -791,8 +859,9 @@
 			]) },
 			{ AllSuccessCode =
 				tree(TraceExitCode,
+				tree(ProfSucc,
 				tree(RestoreDeallocCode,
-				     SuccessCode))
+				     SuccessCode)))
 			}
 		;
 			{ CodeModel = model_non },
@@ -810,7 +879,8 @@
 			{ AllSuccessCode =
 				tree(SetupRedoCode,
 				tree(TraceExitCode,
-				     SuccessCode))
+				tree(ProfSucc,
+				     SuccessCode)))
 			}
 		),
 		{ ExitCode =
Index: compiler/code_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_info.m,v
retrieving revision 1.247
diff -u -r1.247 code_info.m
--- compiler/code_info.m	2000/02/10 01:59:49	1.247
+++ compiler/code_info.m	2000/02/25 23:38:16
@@ -38,6 +38,7 @@
 
 :- import_module code_util, code_exprn, llds_out, prog_out.
 :- import_module arg_info, type_util, mode_util, options.
+:- import_module profiling.
 
 :- import_module term, varset.
 :- import_module set, stack.
@@ -66,9 +67,10 @@
 		% outermost resumption point, and info about the non-fixed
 		% stack slots used for tracing purposes.
 :- pred code_info__init(bool, globals, pred_id, proc_id, proc_info,
-	follow_vars, module_info, int, resume_point_info,
+	follow_vars, module_info, int, scc_info, resume_point_info,
 	trace_slot_info, code_info).
-:- mode code_info__init(in, in, in, in, in, in, in, in, out, out, out) is det.
+:- mode code_info__init(in, in, in, in, in, in, in, in, in,
+	out, out, out) is det.
 
 		% Get the globals table.
 :- pred code_info__get_globals(globals, code_info, code_info).
@@ -135,6 +137,12 @@
 	code_info, code_info).
 :- mode code_info__get_layout_info(out, in, out) is det.
 
+:- pred code_info__get_scc_info(scc_info, code_info, code_info).
+:- mode code_info__get_scc_info(out, in, out) is det.
+
+:- pred code_info__set_scc_info(scc_info, code_info, code_info).
+:- mode code_info__set_scc_info(in, in, out) is det.
+
 		% Get the global static data structures that have
 		% been created during code generation and which do
 		% not have to be scanned by llds_common, since they
@@ -207,10 +215,18 @@
 	code_info, code_info).
 :- mode code_info__get_temp_content_map(out, in, out) is det.
 
+:- pred code_info__get_maybe_profiling_info(maybe(profiling_info),
+		code_info, code_info).
+:- mode code_info__get_maybe_profiling_info(out, in, out) is det.
+
 :- pred code_info__set_temp_content_map(map(lval, slot_contents),
 	code_info, code_info).
 :- mode code_info__set_temp_content_map(in, in, out) is det.
 
+:- pred code_info__set_maybe_profiling_info(maybe(profiling_info),
+		code_info, code_info).
+:- mode code_info__set_maybe_profiling_info(in, in, out) is det.
+
 :- pred code_info__set_non_common_static_data(list(comp_gen_c_data),
 	code_info, code_info).
 :- mode code_info__set_non_common_static_data(in, in, out) is det.
@@ -310,6 +326,14 @@
 				% which would make it impossible to describe
 				% to gc what the slot contains after the end
 				% of the branched control structure.
+		profiling_info :: maybe(profiling_info),
+				% Information about where in the stack frame
+				% for the current procedure, the data for
+				% updating the accurate profiling structures
+				% is stored.
+		scc_info :: scc_info,
+				% Information about SCCs, etc used for
+				% accurate profiling.
 		comp_gen_c_data :: list(comp_gen_c_data),
 				% Static data structures created for this
 				% procedure which do not need to be scanned
@@ -329,7 +353,8 @@
 %---------------------------------------------------------------------------%
 
 code_info__init(SaveSuccip, Globals, PredId, ProcId, ProcInfo, FollowVars,
-		ModuleInfo, CellCount, ResumePoint, TraceSlotInfo, CodeInfo) :-
+		ModuleInfo, CellCount, SCCInfo,
+		ResumePoint, TraceSlotInfo, CodeInfo) :-
 	proc_info_get_initial_instmap(ProcInfo, ModuleInfo, InstMap),
 	proc_info_liveness_info(ProcInfo, Liveness),
 	proc_info_headvars(ProcInfo, HeadVars),
@@ -383,6 +408,8 @@
 		LayoutMap,
 		0,
 		TempContentMap,
+		no,
+		SCCInfo,
 		[],
 		-1
 	),
@@ -450,6 +477,10 @@
 
 code_info__get_temp_content_map(CI^temp_contents, CI, CI).
 
+code_info__get_maybe_profiling_info(CI^profiling_info, CI, CI).
+
+code_info__get_scc_info(CI^scc_info, CI, CI).
+
 code_info__get_non_common_static_data(CI^comp_gen_c_data, CI, CI).
 
 code_info__get_max_reg_in_use_at_trace(CI^max_reg_used, CI, CI).
@@ -482,6 +513,10 @@
 
 code_info__set_temp_content_map(CM, CI, CI^temp_contents := CM).
 
+code_info__set_maybe_profiling_info(PI, CI, CI^profiling_info := PI).
+
+code_info__set_scc_info(SI, CI, CI^scc_info := SI).
+
 code_info__set_non_common_static_data(CG, CI, CI^comp_gen_c_data := CG).
 
 code_info__set_max_reg_in_use_at_trace(MR, CI, CI^max_reg_used := MR).
@@ -595,6 +630,18 @@
 :- pred code_info__succip_is_used(code_info, code_info).
 :- mode code_info__succip_is_used(in, out) is det.
 
+:- type profiling_info
+	--->	profiling_info(
+			lval,	% current scc_id slot
+			lval	% current proc_num slot
+		).
+
+:- pred code_info__get_profiling_info(profiling_info, code_info, code_info).
+:- mode code_info__get_profiling_info(out, in, out) is det.
+
+:- pred code_info__set_profiling_info(profiling_info, code_info, code_info).
+:- mode code_info__set_profiling_info(in, in, out) is det.
+
 :- pred code_info__add_trace_layout_for_label(label, term__context,
 	trace_port, goal_path, layout_label_info, code_info, code_info).
 :- mode code_info__add_trace_layout_for_label(in, in, in,in,  in, in, out)
@@ -794,6 +841,15 @@
 	},
 	code_info__set_layout_info(Internals).
 
+code_info__get_profiling_info(PI) -->
+	code_info__get_maybe_profiling_info(MPI),
+	(
+		{ MPI = yes(PI) }
+	;
+		{ MPI = no },
+		{ error("code_info__get_profiling_info: no profiling_info") }
+	).
+
 code_info__add_resume_layout_for_label(Label, LayoutInfo) -->
 	code_info__get_layout_info(Internals0),
 	{ Resume = yes(LayoutInfo) },
@@ -822,6 +878,9 @@
 	{ map__select(TempContentMap, TempsInUse, TempsInUseContentMap) },
 	{ map__to_assoc_list(TempsInUseContentMap, Temps) }.
 
+code_info__set_profiling_info(PI) -->
+	code_info__set_maybe_profiling_info(yes(PI)).
+
 code_info__add_non_common_static_data(NonCommonData) -->
 	code_info__get_non_common_static_data(NonCommonDatas0),
 	code_info__set_non_common_static_data(
@@ -878,11 +937,11 @@
 code_info__reset_to_position(position_info(PosCI), CurCI, NextCI) :-
 		% The static fields in PosCI and CurCI should be identical.
 	PosCI  = code_info(_,  _,  _,  _,  _,  _,  _,  _, 
-		LA, LB, LC, LD, LE, LF, _,  _,  _,  _,  _,  _,  _,  _ ),
+		LA, LB, LC, LD, LE, LF, _,  _,  _,  _,  _,  _, _, _, _, _),
 	CurCI  = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
-		_,  _,  _,  _,  _,  _,  PA, PB, PC, PD, PE, PF, PG, PH),
+		_,  _,  _,  _,  _,  _,  PA, PB, PC, PD, PE, PF, PG, PH, PI, PJ),
 	NextCI = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
-		LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG, PH).
+		LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF, PG, PH, PI, PJ).
 
 code_info__reset_resume_known(BranchStart) -->
 	{ BranchStart = position_info(BranchStartCI) },
@@ -2328,12 +2387,16 @@
 	% point), or that it would be more efficient to put the two labels
 	% in the other order (e.g. because the code after the resumption point
 	% needs most of the variables in their stack slots).
+	%
+	% If deep profiling is enabled, we need to reset both the current
+	% proc (in case we get a SIG_PROF) and the current scc, so that
+	% subsquent calls get hung off the right point.
 
 code_info__generate_resume_point(ResumePoint, Code) -->
 	(
 		{ ResumePoint = orig_only(Map1, Addr1) },
 		{ extract_label_from_code_addr(Addr1, Label1) },
-		{ Code = node([
+		{ AdjustCode = node([
 			label(Label1) -
 				"orig only failure continuation"
 		]) },
@@ -2341,7 +2404,7 @@
 	;
 		{ ResumePoint = stack_only(Map1, Addr1) },
 		{ extract_label_from_code_addr(Addr1, Label1) },
-		{ Code = node([
+		{ AdjustCode = node([
 			label(Label1) -
 				"stack only failure continuation"
 		]) },
@@ -2364,7 +2427,7 @@
 				"orig failure continuation after stack"
 		]) },
 		code_info__set_var_locations(Map2),
-		{ Code = tree(Label1Code, tree(PlaceCode, Label2Code)) }
+		{ AdjustCode = tree(Label1Code, tree(PlaceCode, Label2Code)) }
 	;
 		{ ResumePoint = orig_and_stack(Map1, Addr1, Map2, Addr2) },
 		{ extract_label_from_code_addr(Addr1, Label1) },
@@ -2382,8 +2445,18 @@
 		]) },
 		code_info__set_var_locations(Map2),
 		code_info__generate_resume_layout(Label2, Map2),
-		{ Code = tree(Label1Code, tree(PlaceCode, Label2Code)) }
-	).
+		{ AdjustCode = tree(Label1Code, tree(PlaceCode, Label2Code)) }
+	),
+	code_info__get_globals(Globals),
+	{ globals__lookup_bool_option(Globals, profile_deep, ProfDeep) },
+	(
+		{ ProfDeep = no },
+		{ ResetCode = empty }
+	;
+		{ ProfDeep = yes },
+		profiling__post_failure_code(ResetCode)
+	),
+	{ Code = tree(AdjustCode, ResetCode) }.
 
 :- pred extract_label_from_code_addr(code_addr::in, label::out) is det.
 
Index: compiler/code_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_util.m,v
retrieving revision 1.116
diff -u -r1.116 code_util.m
--- compiler/code_util.m	2000/01/16 04:34:35	1.116
+++ compiler/code_util.m	2000/02/25 23:38:18
@@ -54,6 +54,9 @@
 :- pred code_util__make_proc_label(module_info, pred_id, proc_id, proc_label).
 :- mode code_util__make_proc_label(in, in, in, out) is det.
 
+:- pred code_util__make_proc_layout_ref(pred_proc_id, module_info, rval).
+:- mode code_util__make_proc_layout_ref(in, in, out) is det.
+
 :- pred code_util__make_uni_label(module_info, type_id, proc_id, proc_label).
 :- mode code_util__make_uni_label(in, in, in, out) is det.
 
@@ -168,6 +171,12 @@
 :- pred code_util__lvals_in_lval(lval, list(lval)).
 :- mode code_util__lvals_in_lval(in, out) is det.
 
+	% code_util__stackref_to_string(Lval, String)
+	% converts an lvalue to a string, which in C code will
+	% refer to that lval. This is only defined for
+	% {,non}det-stack lvalues.
+:- pred code_util__stackref_to_string(lval::in, string::out) is det.
+
 %---------------------------------------------------------------------------%
 
 :- implementation.
@@ -321,7 +330,7 @@
 			Module = ModuleName
 		),
 		ProcLabel = special_proc(Module, "__Unify__", TypeModule,
-			TypeName, Arity, UniModeNum)
+			TypeName, Arity, UniModeNum) % XXX
 	;
 		error("code_util__make_uni_label: unqualified type_id")
 	).
@@ -952,7 +961,14 @@
 	list__append(Lvals1, Lvals2, Lvals).
 code_util__lvals_in_rval(mem_addr(MemRef), Lvals) :-
 	code_util__lvals_in_mem_ref(MemRef, Lvals).
+code_util__lvals_in_rval(c_func(_, _, Args, _), Lvals) :-
+	list__map(lambda([Arg::in, ArgLvals::out] is det, (
+		Arg = _Type - Rval,
+		code_util__lvals_in_rval(Rval, ArgLvals)
+	)), Args, LvalsList),
+	list__condense(LvalsList, Lvals).
 
+
 code_util__lvals_in_lval(reg(_, _), []).
 code_util__lvals_in_lval(stackvar(_), []).
 code_util__lvals_in_lval(framevar(_), []).
@@ -977,6 +993,7 @@
 	list__append(Lvals1, Lvals2, Lvals).
 code_util__lvals_in_lval(lvar(_), []).
 code_util__lvals_in_lval(temp(_, _), []).
+code_util__lvals_in_lval(global(_, _), []).
 code_util__lvals_in_lval(mem_ref(Rval), Lvals) :-
 	code_util__lvals_in_rval(Rval, Lvals).
 
@@ -987,5 +1004,29 @@
 code_util__lvals_in_mem_ref(framevar_ref(_), []).
 code_util__lvals_in_mem_ref(heap_ref(Rval, _, _), Lvals) :-
 	code_util__lvals_in_rval(Rval, Lvals).
+
+%-----------------------------------------------------------------------------%
+
+code_util__make_proc_layout_ref(PPId, ModuleInfo, Rval) :-
+	PPId = proc(PredId, ProcId),
+	code_util__make_proc_label(ModuleInfo, PredId, ProcId,
+			ProcLabel),
+	pred_module(PPId, ModuleInfo, ModuleName),
+	Rval = const(data_addr_const(data_addr(ModuleName,
+			proc_layout(local(ProcLabel))))).
+
+%-----------------------------------------------------------------------------%
+
+code_util__stackref_to_string(Lval, LvalStr) :-
+	( Lval = stackvar(Slot) ->
+		string__int_to_string(Slot, SlotString),
+		string__append_list(["detstackvar(", SlotString, ")"], LvalStr)
+	; Lval = framevar(Slot) ->
+		string__int_to_string(Slot, SlotString),
+		string__append_list(["framevar(", SlotString, ")"], LvalStr)
+	;
+		error("non-stack lval in stackref_to_string")
+	).
+
 
 %-----------------------------------------------------------------------------%
Index: compiler/continuation_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/continuation_info.m,v
retrieving revision 1.31
diff -u -r1.31 continuation_info.m
--- compiler/continuation_info.m	2000/02/16 02:15:35	1.31
+++ compiler/continuation_info.m	2000/02/25 23:38:20
@@ -61,8 +61,12 @@
 	%
 :- type proc_layout_info
 	--->	proc_layout_info(
+			import_status,	% So we know whether or not to
+					% export the proc layout or not.
 			label,		% The entry label.
 			determinism,	% Determines which stack is used.
+			maybe(rval),	% SCC id for this procedure
+					% ('no' if not profiling)
 			int,		% Number of stack slots.
 			maybe(int),	% Location of succip on stack.
 			maybe(label),	% If the trace level is not none,
@@ -234,6 +238,7 @@
 	--->	ticket			% a ticket (trail pointer)
 	;	ticket_counter		% a copy of the ticket counter
 	;	trace_data
+	;	profiling_data		% data for detailed profiling
 	;	sync_term		% a syncronization term used
 					% at the end of par_conjs.
 					% see par_conj_gen.m for details.
@@ -338,7 +343,8 @@
 
 		% Get all the continuation info from the call instructions.
 	global_data_get_proc_layout(GlobalData0, PredProcId, ProcLayoutInfo0),
-	ProcLayoutInfo0 = proc_layout_info(A, B, C, D, E, F, G, H, Internals0),
+	ProcLayoutInfo0 = proc_layout_info(A, B, C, D, E, F, G, H, I, J,
+				Internals0),
 	GetCallInfo = lambda([Instr::in, Call::out] is semidet, (
 		Instr = call(Target, label(ReturnLabel), LiveInfo, Context, _)
 			- _Comment,
@@ -350,7 +356,8 @@
 	list__foldl(continuation_info__process_continuation(WantReturnInfo),
 		Calls, Internals0, Internals),
 
-	ProcLayoutInfo = proc_layout_info(A, B, C, D, E, F, G, H, Internals),
+	ProcLayoutInfo = proc_layout_info(A, B, C, D, E, F, G, H, I, J,
+		Internals),
 	global_data_update_proc_layout(GlobalData0, PredProcId, ProcLayoutInfo,
 		GlobalData).
 
@@ -732,12 +739,14 @@
 continuation_info__live_value_type(lval(reg(_, _)), unwanted).
 continuation_info__live_value_type(lval(stackvar(_)), unwanted).
 continuation_info__live_value_type(lval(framevar(_)), unwanted).
+continuation_info__live_value_type(lval(global(_, _)), unwanted).	% XXX
 continuation_info__live_value_type(lval(mem_ref(_)), unwanted).	% XXX
 continuation_info__live_value_type(ticket, unwanted). % XXX we may need to
 					% modify this, if the GC is going
 					% to garbage-collect the trail.
 continuation_info__live_value_type(ticket_counter, unwanted).
 continuation_info__live_value_type(sync_term, unwanted).
+continuation_info__live_value_type(profiling_data, unwanted).
 continuation_info__live_value_type(trace_data, unwanted).
 
 %-----------------------------------------------------------------------------%
Index: compiler/dependency_graph.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dependency_graph.m,v
retrieving revision 1.45
diff -u -r1.45 dependency_graph.m
--- compiler/dependency_graph.m	2000/02/21 01:41:29	1.45
+++ compiler/dependency_graph.m	2000/02/25 23:38:22
@@ -598,7 +598,7 @@
 
 dependency_graph__build_aditi_scc_info([]) --> [].
 dependency_graph__build_aditi_scc_info([SCC | SCCs]) -->
-	aditi_scc_info_get_module_info(ModuleInfo),
+	dependency_graph__aditi_scc_info_get_module_info(ModuleInfo),
 	(
 		{ list__member(PredProcId, SCC) },
 		{ PredProcId = proc(PredId, _) },
@@ -614,16 +614,16 @@
 	),
 	dependency_graph__build_aditi_scc_info(SCCs).	
 
-:- pred dependency_graph__process_aditi_pred_proc_id(scc_id::in, 
+:- pred dependency_graph__process_aditi_pred_proc_id(aditi_scc_id::in, 
 	pred_proc_id::in, aditi_scc_info::in, aditi_scc_info::out) is det.
 
 dependency_graph__process_aditi_pred_proc_id(SCCid, PredProcId) -->
-	aditi_scc_info_get_module_info(ModuleInfo),
+	dependency_graph__aditi_scc_info_get_module_info(ModuleInfo),
 	{ module_info_pred_proc_info(ModuleInfo, PredProcId, 
 		PredInfo, ProcInfo) },
 	dependency_graph__process_aditi_proc_info(SCCid, PredInfo, ProcInfo).
 
-:- pred dependency_graph__process_aditi_proc_info(scc_id::in, pred_info::in, 
+:- pred dependency_graph__process_aditi_proc_info(aditi_scc_id::in, pred_info::in, 
 	proc_info::in, aditi_scc_info::in, aditi_scc_info::out) is det.
 
 dependency_graph__process_aditi_proc_info(CurrSCC, PredInfo, ProcInfo) -->
@@ -718,9 +718,9 @@
 		error("dependency_graph__merge_aditi_sccs: SCC dependency relation is cyclic")
 	).
 
-:- pred dependency_graph__merge_aditi_sccs_2(list(scc_id)::in,
-	eqvclass(scc_id)::in, set(scc_id)::in, set(scc_id)::in,
-	relation(scc_id)::in, scc_pred_map::in, 
+:- pred dependency_graph__merge_aditi_sccs_2(list(aditi_scc_id)::in,
+	eqvclass(aditi_scc_id)::in, set(aditi_scc_id)::in,
+	set(aditi_scc_id)::in, relation(aditi_scc_id)::in, scc_pred_map::in, 
 	aditi_dependency_ordering::in, aditi_dependency_ordering::out) is det.
 
 dependency_graph__merge_aditi_sccs_2([], _, _, _, _, _, Ordering, Ordering).
@@ -746,8 +746,8 @@
 		NoMergeSCCs, SCCRel, SCCPreds, Ordering1, Ordering).
 
 	% Find the SCCs called from a given SCC.
-:- pred dependency_graph__get_called_scc_ids(scc_id::in, relation(scc_id)::in,
-		set(scc_id)::out) is det.
+:- pred dependency_graph__get_called_scc_ids(aditi_scc_id::in,
+		relation(aditi_scc_id)::in, set(aditi_scc_id)::out) is det.
 
 dependency_graph__get_called_scc_ids(SCCid, SCCRel, CalledSCCSet) :-
 	relation__lookup_element(SCCRel, SCCid, SCCidKey),
@@ -758,11 +758,13 @@
 
 	% Go over the list of SCCs finding all those which 
 	% can be merged into a given SCC.
-:- pred dependency_graph__do_merge_aditi_sccs(scc_id::in, set(scc_id)::in, 
-		set(scc_id)::in, list(scc_id)::in, list(scc_id)::out, 
-		scc_pred_map::in, relation(scc_id)::in, 
-		eqvclass(scc_id)::in, eqvclass(scc_id)::out, 
-		aditi_scc::in, aditi_scc::out) is det.
+:- pred dependency_graph__do_merge_aditi_sccs(aditi_scc_id::in,
+set(aditi_scc_id)::in, 
+		set(aditi_scc_id)::in, list(aditi_scc_id)::in,
+		list(aditi_scc_id)::out, scc_pred_map::in,
+		relation(aditi_scc_id)::in, eqvclass(aditi_scc_id)::in,
+		eqvclass(aditi_scc_id)::out, aditi_scc::in,
+		aditi_scc::out) is det.
 
 dependency_graph__do_merge_aditi_sccs(_, _, _, [], [], 
 		_, _, Eqv, Eqv, SubModule, SubModule).
@@ -831,20 +833,20 @@
 :- type aditi_scc_info
 	---> aditi_scc_info(
 		module_info,
-		map(pred_proc_id, scc_id),
+		map(pred_proc_id, aditi_scc_id),
 		scc_pred_map,
 		set(pred_proc_id),		% all local Aditi preds
-		relation(scc_id),
-		set(scc_id),			% SCCs which can't be merged
+		relation(aditi_scc_id),
+		set(aditi_scc_id),		% SCCs which can't be merged
 						% into their parents.
-		scc_id				% current SCC.
+		aditi_scc_id			% current SCC.
 	).
 
 		% For each SCC, a list of all preds in SCC, and a list
 		% of entry-points of the SCC.
-:- type scc_pred_map ==	map(scc_id, pair(list(pred_proc_id))).
+:- type scc_pred_map ==	map(aditi_scc_id, pair(list(pred_proc_id))).
 
-:- type scc_id == int.
+:- type aditi_scc_id == int.
 
 :- type scc == list(pred_proc_id).
 
@@ -859,13 +861,13 @@
 	AditiInfo = aditi_scc_info(ModuleInfo, PredSCC, SCCPred, 
 			AditiPreds, SCCDep, NoMergeSCCs, 0).
 
-:- pred aditi_scc_info_get_module_info(module_info::out,
+:- pred dependency_graph__aditi_scc_info_get_module_info(module_info::out,
 		aditi_scc_info::in, aditi_scc_info::out) is det.
 
-aditi_scc_info_get_module_info(Module, Info, Info) :-
+dependency_graph__aditi_scc_info_get_module_info(Module, Info, Info) :-
 	Info = aditi_scc_info(Module, _, _, _, _, _, _).
 
-:- pred aditi_scc_info_add_no_merge_scc(scc_id::in,
+:- pred aditi_scc_info_add_no_merge_scc(aditi_scc_id::in,
 		aditi_scc_info::in, aditi_scc_info::out) is det.
 
 aditi_scc_info_add_no_merge_scc(SCCid, Info0, Info) :-
@@ -874,7 +876,7 @@
 	Info = aditi_scc_info(A, B, C, D, E, NoMerge, G).
 
 :- pred aditi_scc_info_add_scc(list(pred_proc_id)::in, 
-		dependency_ordering::in, scc_id::out,
+		dependency_ordering::in, aditi_scc_id::out,
 		aditi_scc_info::in, aditi_scc_info::out) is det.
 
 aditi_scc_info_add_scc(SCC, HigherSCCs, SCCid, Info0, Info) :-
@@ -935,10 +937,11 @@
 
 	% An SCC cannot be merged into its parents if one of its
 	% procedures is called as an aggregate query.
-:- pred handle_higher_order_args(list(prog_var)::in, bool::in, scc_id::in,
-	multi_map(prog_var, pred_proc_id)::in, map(pred_proc_id, scc_id)::in,
-	relation(scc_id)::in, relation(scc_id)::out,
-	set(scc_id)::in, set(scc_id)::out) is det.
+:- pred handle_higher_order_args(list(prog_var)::in, bool::in, aditi_scc_id::in,
+	multi_map(prog_var, pred_proc_id)::in, map(pred_proc_id,
+	aditi_scc_id)::in, relation(aditi_scc_id)::in,
+	relation(aditi_scc_id)::out, set(aditi_scc_id)::in,
+	set(aditi_scc_id)::out) is det.
 	
 handle_higher_order_args([], _, _, _, _, SCCRel, SCCRel, NoMerge, NoMerge).
 handle_higher_order_args([Arg | Args], IsAgg, SCCid, Map, PredSCC, 
@@ -953,10 +956,10 @@
 	handle_higher_order_args(Args, IsAgg, SCCid, Map, PredSCC, 
 		SCCRel1, SCCRel, NoMerge1, NoMerge).
 
-:- pred handle_higher_order_arg(map(pred_proc_id, scc_id)::in, bool::in,
-		scc_id::in, pred_proc_id::in,
-		relation(scc_id)::in, relation(scc_id)::out,
-		set(scc_id)::in, set(scc_id)::out) is det.
+:- pred handle_higher_order_arg(map(pred_proc_id, aditi_scc_id)::in, bool::in,
+		aditi_scc_id::in, pred_proc_id::in,
+		relation(aditi_scc_id)::in, relation(aditi_scc_id)::out,
+		set(aditi_scc_id)::in, set(aditi_scc_id)::out) is det.
 
 handle_higher_order_arg(PredSCC, IsAgg, SCCid, PredProcId,
 		SCCRel0, SCCRel, NoMerge0, NoMerge) :-
Index: compiler/dupelim.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dupelim.m,v
retrieving revision 1.45
diff -u -r1.45 dupelim.m
--- compiler/dupelim.m	2000/01/14 01:10:16	1.45
+++ compiler/dupelim.m	2000/02/25 23:38:24
@@ -402,6 +402,9 @@
 		Lval1 = temp(_, _),
 		Lval = Lval1
 	;
+		Lval1 = global(_, _),
+		Lval = Lval1
+	;
 		Lval1 = stackvar(_),
 		Lval = Lval1
 	;
@@ -466,6 +469,14 @@
 	;
 		Rval1 = mem_addr(_),
 		Rval = Rval1
+	;
+		Rval1 = c_func(RetType, FuncName, Args0, Static),
+		list__map(lambda([Arg0::in, Arg::out] is det, (
+			Arg0 = Type - ArgRval0,
+			Arg = Type - ArgRval,
+			standardize_rval(ArgRval0, ArgRval)
+		)), Args0, Args),
+		Rval = c_func(RetType, FuncName, Args, Static)
 	).
 
 %-----------------------------------------------------------------------------%
@@ -685,6 +696,10 @@
 		Lval2 = Lval1,
 		Lval = Lval1
 	;
+		Lval1 = global(_, _),
+		Lval2 = Lval1,
+		Lval = Lval1
+	;
 		Lval1 = stackvar(_),
 		Lval2 = Lval1,
 		Lval = Lval1
@@ -744,6 +759,10 @@
 	;
 		Rval1 = var(_),
 		error("var in most_specific_rval")
+	;
+		Rval1 = c_func(_, _, _, _),
+		Rval2 = Rval1,
+		Rval = Rval1
 	;
 		Rval1 = create(_, _, _, _, _, _, _),
 		Rval2 = Rval1,
Index: compiler/export.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/export.m,v
retrieving revision 1.32
diff -u -r1.32 export.m
--- compiler/export.m	2000/02/16 06:05:52	1.32
+++ compiler/export.m	2000/02/25 23:38:25
@@ -122,6 +122,10 @@
 	% #if FUNCTION
 	%	Word retval;
 	% #endif
+	% #if MR_PROFILE_DEEP
+	%	MR_ProcCallProfile	*saved_current_proc;
+	%	MR_SCCInstance		*saved_current_scc;
+	% #endif
 	%
 	%		/* save the registers that our C caller may be using */
 	%	save_regs_to_mem(c_regs);
@@ -132,6 +136,15 @@
 	%		/* init_engine() etc.)				  */
 	%	restore_registers();
 	%	<copy input arguments from Mercury__Arguments into registers>
+	% #ifdef MR_PROFILE_DEEP
+	%		/* If we're doing profiling, hook the callback 	  */
+	%		/* into the profiling call-tree.		  */  
+	%	saved_current_proc = MR_prof_current_proc;
+	%	saved_current_scc = MR_prof_current_scc;
+	%	MR_prof_current_proc = MR_prof_c_calls_mercury(
+	%		&mercury_data__stack_layout__<label of called proc>);
+	%	MR_prof_current_scc = MR_scc_from_current_proc();
+	% #endif
 	%		/* save the registers which may be clobbered      */
 	%		/* by the C function call MR_call_engine().       */
 	%	save_transient_registers();
@@ -142,6 +155,14 @@
 	%		/* clobbered by the return from the C function    */
 	%		/* MR_call_engine()				  */
 	%	restore_transient_registers();
+	%
+	% #ifdef MR_PROFILE_DEEP
+	%		/* restore the current_proc and current_scc	  */
+	%		/* variables.					  */
+	%	MR_prof_current_scc = saved_current_scc;
+	%	MR_prof_current_proc = saved_current_proc;
+	% #endif
+	%
 	% #if SEMIDET
 	%	if (!r1) {
 	%		restore_regs_from_mem(c_regs);
@@ -177,6 +198,7 @@
 	
 	code_util__make_proc_label(Module, PredId, ProcId, ProcLabel),
 	llds_out__get_proc_label(ProcLabel, yes, ProcLabelString),
+	llds_out__make_stack_layout_name(local(ProcLabel), LayoutName),
 
 	( Exported = yes ->
 		DeclareString = "Declare_entry"
@@ -184,29 +206,46 @@
 		DeclareString = "Declare_static"
 	),
 
-	string__append_list([	"\n",
-				DeclareString, "(", ProcLabelString, ");\n",
-				"\n",
-				C_RetType, "\n", 
-				C_Function, "(", ArgDecls, ")\n{\n",
-				"#if NUM_REAL_REGS > 0\n",
-				"\tWord c_regs[NUM_REAL_REGS];\n",
-				"#endif\n",
-				MaybeDeclareRetval,
-				"\n",
-				"\tsave_regs_to_mem(c_regs);\n", 
-				"\trestore_registers();\n", 
-				InputArgs,
-				"\tsave_transient_registers();\n",
-				"\t(void) MR_call_engine(ENTRY(",
-					ProcLabelString, "), FALSE);\n",
-				"\trestore_transient_registers();\n",
-				MaybeFail,
-				OutputArgs,
-				"\trestore_regs_from_mem(c_regs);\n", 
-				MaybeSucceed,
-				"}\n\n"],
-				Code),
+	string__append_list([
+		"\n",
+		DeclareString, "(", ProcLabelString, ");\n",
+		"\n",
+		C_RetType, "\n", 
+		C_Function, "(", ArgDecls, ")\n{\n",
+		"#if NUM_REAL_REGS > 0\n",
+		"\tWord c_regs[NUM_REAL_REGS];\n",
+		"#endif\n",
+		MaybeDeclareRetval,
+		"\n",
+		"#if MR_PROFILE_DEEP\n",
+		"\tMR_ProcCallProfile	*saved_current_proc;\n",
+		"\tMR_SCCInstance	*saved_current_scc;\n",
+		"#endif\n",
+		"\tsave_regs_to_mem(c_regs);\n", 
+		"\trestore_registers();\n", 
+		InputArgs,
+		"#ifdef MR_PROFILE_DEEP\n",
+		"\tsaved_current_proc = MR_prof_current_proc;\n",
+		"\tsaved_current_scc = MR_prof_current_scc;\n",
+		"\tMR_prof_current_proc = MR_prof_c_calls_mercury(\n",
+		"\t\t&", LayoutName, ");\n",
+		"\tMR_prof_current_scc = MR_scc_from_current_proc();\n",
+		"#endif\n",
+		"\tsave_transient_registers();\n",
+		"\t(void) MR_call_engine(ENTRY(",
+			ProcLabelString, "), FALSE);\n",
+		"\trestore_transient_registers();\n",
+		"#ifdef MR_PROFILE_DEEP\n",
+		"\tMR_prof_current_scc = saved_current_scc;\n",
+		"\tMR_prof_current_proc = ",
+			"saved_current_proc;\n",
+		"#endif\n",
+		MaybeFail,
+		OutputArgs,
+		"\trestore_regs_from_mem(c_regs);\n", 
+		MaybeSucceed,
+		"}\n\n"
+	], Code),
 
 	export__to_c(Preds, ExportedProcs, Module, TheRest),
 	ExportedProcsCode = [Code|TheRest].
Index: compiler/exprn_aux.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/exprn_aux.m,v
retrieving revision 1.38
diff -u -r1.38 exprn_aux.m
--- compiler/exprn_aux.m	2000/01/14 01:10:18	1.38
+++ compiler/exprn_aux.m	2000/02/25 23:38:27
@@ -313,6 +313,12 @@
 	list__append(Vars0, Vars1, Vars).
 exprn_aux__vars_in_rval(mem_addr(MemRef), Vars) :-
 	exprn_aux__vars_in_mem_ref(MemRef, Vars).
+exprn_aux__vars_in_rval(c_func(_, _, Args, _), Vars) :-
+	list__map(lambda([Pair::in, Vars0::out] is det, (
+		Pair = (_ - Rval),
+		exprn_aux__vars_in_rval(Rval, Vars0)
+	)), Args, VarsList),
+	list__condense(VarsList, Vars).
 
 exprn_aux__vars_in_lval(reg(_, _), []).
 exprn_aux__vars_in_lval(temp(_, _), []).
@@ -323,6 +329,7 @@
 exprn_aux__vars_in_lval(sp, []).
 exprn_aux__vars_in_lval(stackvar(_), []).
 exprn_aux__vars_in_lval(framevar(_), []).
+exprn_aux__vars_in_lval(global(_, _), []).
 exprn_aux__vars_in_lval(succip(Rval), Vars) :-
 	exprn_aux__vars_in_rval(Rval, Vars).
 exprn_aux__vars_in_lval(redoip(Rval), Vars) :-
@@ -408,6 +415,15 @@
 		exprn_aux__substitute_lval_in_mem_ref(OldLval, NewLval,
 			MemRef0, MemRef),
 		Rval = mem_addr(MemRef)
+	;
+		Rval0 = c_func(RetType, Func, Args0, Static),
+		list__map(lambda([Arg0::in, Arg::out] is det, (
+			Arg0 = Type - ArgRval0,
+			Arg = Type - ArgRval,
+			exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
+				ArgRval0, ArgRval)
+		)), Args0, Args),
+		Rval = c_func(RetType, Func, Args, Static)
 	).
 
 :- pred exprn_aux__substitute_lval_in_mem_ref(lval, lval, mem_ref, mem_ref).
@@ -472,6 +488,9 @@
 		Lval0 = framevar(N),
 		Lval = framevar(N)
 	;
+		Lval0 = global(Typ, Glob),
+		Lval = global(Typ, Glob)
+	;
 		Lval0 = succip(Rval0),
 		exprn_aux__substitute_lval_in_rval(OldLval, NewLval,
 			Rval0, Rval),
@@ -585,6 +604,15 @@
 			exprn_aux__substitute_rval_in_mem_ref(OldRval, NewRval,
 				MemRef1, MemRef2),
 			Rval = mem_addr(MemRef2)
+		;
+			Rval0 = c_func(RetType, Func, Args0, Static),
+			list__map(lambda([Arg0::in, Arg::out] is det, (
+				Arg0 = Type - ArgRval0,
+				Arg = Type - ArgRval,
+				exprn_aux__substitute_rval_in_rval(OldRval,
+					NewRval, ArgRval0, ArgRval)
+			)), Args0, Args),
+			Rval = c_func(RetType, Func, Args, Static)
 		)
 	).
 
@@ -637,6 +665,9 @@
 		Lval0 = framevar(N),
 		Lval = framevar(N)
 	;
+		Lval0 = global(Typ, Glob),
+		Lval = global(Typ, Glob)
+	;
 		Lval0 = succip(Rval0),
 		exprn_aux__substitute_rval_in_rval(OldRval, NewRval,
 			Rval0, Rval),
@@ -857,6 +888,8 @@
 	list__append(DataAddrs1, DataAddrs2, DataAddrs).
 exprn_aux__rval_addrs(mem_addr(Rval), CodeAddrs, DataAddrs) :-
 	exprn_aux__mem_ref_addrs(Rval, CodeAddrs, DataAddrs).
+exprn_aux__rval_addrs(c_func(_, _, Args, _), CodeAddrs, DataAddrs) :-
+	exprn_aux__arg_ref_addrs(Args, CodeAddrs, DataAddrs).
 
 	% give an lval, return a list of the code and data addresses
 	% that are referenced by that lval
@@ -885,6 +918,7 @@
 	list__append(CodeAddrs1, CodeAddrs2, CodeAddrs),
 	list__append(DataAddrs1, DataAddrs2, DataAddrs).
 exprn_aux__lval_addrs(lvar(_Var), [], []).
+exprn_aux__lval_addrs(global(_, _), [], []).
 exprn_aux__lval_addrs(temp(_, _), [], []).
 exprn_aux__lval_addrs(mem_ref(Rval), CodeAddrs, DataAddrs) :-
 	exprn_aux__rval_addrs(Rval, CodeAddrs, DataAddrs).
@@ -916,6 +950,17 @@
 exprn_aux__mem_ref_addrs(framevar_ref(_), [], []).
 exprn_aux__mem_ref_addrs(heap_ref(Rval, _, _), CodeAddrs, DataAddrs) :-
 	exprn_aux__rval_addrs(Rval, CodeAddrs, DataAddrs).
+
+:- pred exprn_aux__arg_ref_addrs(list(pair(llds_type, rval)),
+		list(code_addr), list(data_addr)).
+:- mode exprn_aux__arg_ref_addrs(in, out, out) is det.
+
+exprn_aux__arg_ref_addrs([], [], []).
+exprn_aux__arg_ref_addrs([_Type - Rval|Args], CodeAddrs, DataAddrs) :-
+	exprn_aux__rval_addrs(Rval, CodeAddrs0, DataAddrs0),
+	exprn_aux__arg_ref_addrs(Args, CodeAddrs1, DataAddrs1),
+	list__append(CodeAddrs0, CodeAddrs1, CodeAddrs),
+	list__append(DataAddrs0, DataAddrs1, DataAddrs).
 
 	% give a list of maybe(rval), return a list of the code and data
 	% addresses that are reference by that list
Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.88
diff -u -r1.88 handle_options.m
--- compiler/handle_options.m	2000/01/10 05:26:18	1.88
+++ compiler/handle_options.m	2000/02/25 23:38:33
@@ -368,6 +368,7 @@
 
 	% Deep profiling requires `procid' stack layouts
 	option_implies(profile_deep, procid_stack_layout, bool(yes)),
+	option_implies(profile_deep, middle_rec, bool(no)),
 
 	% --no-reorder-conj implies --no-deforestation.
 	option_neg_implies(reorder_conj, deforestation, bool(no)),
Index: compiler/hlds_module.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_module.m,v
retrieving revision 1.50
diff -u -r1.50 hlds_module.m
--- compiler/hlds_module.m	2000/01/13 06:15:41	1.50
+++ compiler/hlds_module.m	2000/02/25 23:38:33
@@ -86,6 +86,43 @@
 	% map from proc to a list of unused argument numbers.
 :- type unused_arg_info == map(pred_proc_id, list(int)).
 
+:- type scc_info
+	--->	scc_info(
+			map(pred_proc_id, scc_id),
+				% To which scc does each proc belong?
+				% Leaf procedures are not assigned an
+				% scc_id.
+			map(scc_id, scc_data)
+				% for each scc, keep track of call site
+				% numbers for first order calls,
+				% higher order calls, and class method
+				% calls, and store the info about each
+				% call site for the static SCCId structures.
+		).
+
+:- type scc_data
+	--->	scc_data(
+			int,
+			list(first_order_call),
+			int,
+			list(higher_order_call),
+			int,
+			list(class_method_call),
+			may_call_mercury
+		).
+
+:- type first_order_call
+	--->	first_order_call(pred_proc_id, pred_proc_id, term__context).
+
+:- type higher_order_call
+	--->	higher_order_call(pred_proc_id, term__context).
+
+:- type class_method_call
+	--->	class_method_call(pred_proc_id, pred_proc_id, term__context).
+
+:- type scc_id
+	--->	scc_id(module_name, int).
+
 	% List of procedures for which there are user-requested type
 	% specializations, and a list of predicates which should be
 	% processed by higher_order.m to ensure the production of those
@@ -222,6 +259,12 @@
 :- pred module_info_set_cell_count(module_info, int, module_info).
 :- mode module_info_set_cell_count(in, in, out) is det.
 
+:- pred module_info_get_scc_info(module_info, scc_info).
+:- mode module_info_get_scc_info(in, out) is det.
+
+:- pred module_info_set_scc_info(module_info, scc_info, module_info).
+:- mode module_info_set_scc_info(in, in, out) is det.
+
 :- pred module_add_imported_module_specifiers(list(module_specifier),
 		module_info, module_info).
 :- mode module_add_imported_module_specifiers(in, in, out) is det.
@@ -572,6 +615,7 @@
 			instance_table,
 			superclass_table,
 			assertion_table,
+			scc_info,
 			ctor_field_table,
 			int		% cell count, passed into code_info
 					% and used to generate unique label
@@ -637,6 +681,9 @@
 
 	map__init(ClassTable),
 	map__init(InstanceTable),
+	map__init(PredProcSCCs),
+	map__init(SCCCallSites),
+	SCCInfo = scc_info(PredProcSCCs, SCCCallSites),
 	map__init(SuperClassTable),
 
 	% the builtin modules are automatically imported
@@ -653,7 +700,7 @@
 	ModuleInfo = module(ModuleSubInfo, PredicateTable, Requests,
 		UnifyPredMap, QualifierInfo, Types, Insts, Modes, Ctors,
 		ClassTable, SuperClassTable, InstanceTable, AssertionTable,
-		FieldNameTable, 0).
+		SCCInfo, FieldNameTable, 0).
 
 %-----------------------------------------------------------------------------%
 
@@ -824,9 +871,10 @@
 % J			class_table,
 % K			instance_table,
 % L			superclass_table,
-% M			assertion_table
-% N			ctor_field_table,
-% O			int		% cell count, passed into code_info
+% M			assertion_table,
+% N			scc_info,
+% O			ctor_field_table,
+% P			int		% cell count, passed into code_info
 %					% and used to generate unique label
 %					% numbers for constant terms in the
 %					% generated C code
@@ -837,113 +885,120 @@
 	% Various predicates which access the module_info data structure.
 
 module_info_get_sub_info(MI0, A) :-
-	MI0 = module(A, _, _, _, _, _, _, _, _, _, _, _, _, _, _).
+	MI0 = module(A, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _).
 
 module_info_get_predicate_table(MI0, B) :-
-	MI0 = module(_, B, _, _, _, _, _, _, _, _, _, _, _, _, _).
+	MI0 = module(_, B, _, _, _, _, _, _, _, _, _, _, _, _, _, _).
 
 module_info_get_proc_requests(MI0, C) :-
-	MI0 = module(_, _, C, _, _, _, _, _, _, _, _, _, _, _, _).
+	MI0 = module(_, _, C, _, _, _, _, _, _, _, _, _, _, _, _, _).
 
 module_info_get_special_pred_map(MI0, D) :-
-	MI0 = module(_, _, _, D, _, _, _, _, _, _, _, _, _, _, _).
+	MI0 = module(_, _, _, D, _, _, _, _, _, _, _, _, _, _, _, _).
 
 module_info_get_partial_qualifier_info(MI0, E) :-
-	MI0 = module(_, _, _, _, E, _, _, _, _, _, _, _, _, _, _).
+	MI0 = module(_, _, _, _, E, _, _, _, _, _, _, _, _, _, _, _).
 
 module_info_types(MI0, F) :-
-	MI0 = module(_, _, _, _, _, F, _, _, _, _, _, _, _, _, _).
+	MI0 = module(_, _, _, _, _, F, _, _, _, _, _, _, _, _, _, _).
 
 module_info_insts(MI0, G) :-
-	MI0 = module(_, _, _, _, _, _, G, _, _, _, _, _, _, _, _).
+	MI0 = module(_, _, _, _, _, _, G, _, _, _, _, _, _, _, _, _).
 
 module_info_modes(MI0, H) :-
-	MI0 = module(_, _, _, _, _, _, _, H, _, _, _, _, _, _, _).
+	MI0 = module(_, _, _, _, _, _, _, H, _, _, _, _, _, _, _, _).
 
 module_info_ctors(MI0, I) :-
-	MI0 = module(_, _, _, _, _, _, _, _, I, _, _, _, _, _, _).
+	MI0 = module(_, _, _, _, _, _, _, _, I, _, _, _, _, _, _, _).
 
 module_info_classes(MI0, J) :-
-	MI0 = module(_, _, _, _, _, _, _, _, _, J, _, _, _, _, _).
+	MI0 = module(_, _, _, _, _, _, _, _, _, J, _, _, _, _, _, _).
 
 module_info_instances(MI0, K) :-
-	MI0 = module(_, _, _, _, _, _, _, _, _, _, K, _, _, _, _).
+	MI0 = module(_, _, _, _, _, _, _, _, _, _, K, _, _, _, _, _).
 
 module_info_superclasses(MI0, L) :-
-	MI0 = module(_, _, _, _, _, _, _, _, _, _, _, L, _, _, _).
+	MI0 = module(_, _, _, _, _, _, _, _, _, _, _, L, _, _, _, _).
 
 module_info_assertion_table(MI0, M) :-
-	MI0 = module(_, _, _, _, _, _, _, _, _, _, _, _, M, _, _).
+	MI0 = module(_, _, _, _, _, _, _, _, _, _, _, _, M, _, _, _).
+
+module_info_get_scc_info(MI0, N) :-
+	MI0 = module(_, _, _, _, _, _, _, _, _, _, _, _, _, N, _, _).
 
-module_info_ctor_field_table(MI0, N) :-
-	MI0 = module(_, _, _, _, _, _, _, _, _, _, _, _, _, N, _).
+module_info_ctor_field_table(MI0, O) :-
+	MI0 = module(_, _, _, _, _, _, _, _, _, _, _, _, _, _, O, _).
 
-module_info_get_cell_count(MI0, O) :-
-	MI0 = module(_, _, _, _, _, _, _, _, _, _, _, _, _, _, O).
+module_info_get_cell_count(MI0, P) :-
+	MI0 = module(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, P).
 
 %-----------------------------------------------------------------------------%
 
 	% Various predicates which modify the module_info data structure.
 
 module_info_set_sub_info(MI0, A, MI) :-
-	MI0 = module(_, B, C, D, E, F, G, H, I, J, K, L, M, N, O),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O).
+	MI0 = module(_, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
 
 module_info_set_predicate_table(MI0, B, MI) :-
-	MI0 = module(A, _, C, D, E, F, G, H, I, J, K, L, M, N, O),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O).
+	MI0 = module(A, _, C, D, E, F, G, H, I, J, K, L, M, N, O, P),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
 
 module_info_set_proc_requests(MI0, C, MI) :-
-	MI0 = module(A, B, _, D, E, F, G, H, I, J, K, L, M, N, O),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O).
+	MI0 = module(A, B, _, D, E, F, G, H, I, J, K, L, M, N, O, P),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
 
 module_info_set_special_pred_map(MI0, D, MI) :-
-	MI0 = module(A, B, C, _, E, F, G, H, I, J, K, L, M, N, O),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O).
+	MI0 = module(A, B, C, _, E, F, G, H, I, J, K, L, M, N, O, P),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
 
 module_info_set_partial_qualifier_info(MI0, E, MI) :-
-	MI0 = module(A, B, C, D, _, F, G, H, I, J, K, L, M, N, O),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O).
+	MI0 = module(A, B, C, D, _, F, G, H, I, J, K, L, M, N, O, P),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
 
 module_info_set_types(MI0, F, MI) :-
-	MI0 = module(A, B, C, D, E, _, G, H, I, J, K, L, M, N, O),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O).
+	MI0 = module(A, B, C, D, E, _, G, H, I, J, K, L, M, N, O, P),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
 
 module_info_set_insts(MI0, G, MI) :-
-	MI0 = module(A, B, C, D, E, F, _, H, I, J, K, L, M, N, O),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O).
+	MI0 = module(A, B, C, D, E, F, _, H, I, J, K, L, M, N, O, P),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
 
 module_info_set_modes(MI0, H, MI) :-
-	MI0 = module(A, B, C, D, E, F, G, _, I, J, K, L, M, N, O),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O).
+	MI0 = module(A, B, C, D, E, F, G, _, I, J, K, L, M, N, O, P),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
 
 module_info_set_ctors(MI0, I, MI) :-
-	MI0 = module(A, B, C, D, E, F, G, H, _, J, K, L, M, N, O),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O).
+	MI0 = module(A, B, C, D, E, F, G, H, _, J, K, L, M, N, O, P),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
 
 module_info_set_classes(MI0, J, MI) :-
-	MI0 = module(A, B, C, D, E, F, G, H, I, _, K, L, M, N, O),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O).
+	MI0 = module(A, B, C, D, E, F, G, H, I, _, K, L, M, N, O, P),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
 
 module_info_set_instances(MI0, K, MI) :-
-	MI0 = module(A, B, C, D, E, F, G, H, I, J, _, L, M, N, O),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O).
+	MI0 = module(A, B, C, D, E, F, G, H, I, J, _, L, M, N, O, P),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
 
 module_info_set_superclasses(MI0, L, MI) :-
-	MI0 = module(A, B, C, D, E, F, G, H, I, J, K, _, M, N, O),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O).
+	MI0 = module(A, B, C, D, E, F, G, H, I, J, K, _, M, N, O, P),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
 
 module_info_set_assertion_table(MI0, M, MI) :-
-	MI0 = module(A, B, C, D, E, F, G, H, I, J, K, L, _, N, O),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O).
+	MI0 = module(A, B, C, D, E, F, G, H, I, J, K, L, _, N, O, P),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
 
-module_info_set_ctor_field_table(MI0, N, MI) :-
-	MI0 = module(A, B, C, D, E, F, G, H, I, J, K, L, M, _, O),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O).
-
-module_info_set_cell_count(MI0, O, MI) :-
-	MI0 = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, _),
-	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O).
+module_info_set_scc_info(MI0, N, MI) :-
+	MI0 = module(A, B, C, D, E, F, G, H, I, J, K, L, M, _, O, P),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
+
+module_info_set_ctor_field_table(MI0, O, MI) :-
+	MI0 = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, _, P),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
+
+module_info_set_cell_count(MI0, P, MI) :-
+	MI0 = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, _),
+	MI  = module(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/hlds_pred.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_pred.m,v
retrieving revision 1.72
diff -u -r1.72 hlds_pred.m
--- compiler/hlds_pred.m	2000/02/16 02:15:36	1.72
+++ compiler/hlds_pred.m	2000/02/25 23:38:39
@@ -71,6 +71,12 @@
 :- pred invalid_proc_id(proc_id).
 :- mode invalid_proc_id(out) is det.
 
+:- pred pred_has_local_code(pred_proc_id, module_info).
+:- mode pred_has_local_code(in, in) is semidet.
+
+:- pred pred_module(pred_proc_id, module_info, module_name).
+:- mode pred_module(in, in, out) is det.
+
 :- type pred_info.
 :- type proc_info.
 
@@ -709,6 +715,15 @@
 invalid_pred_id(-1).
 
 invalid_proc_id(-1).
+
+pred_has_local_code(proc(PredId, ProcId), ModuleInfo) :-
+	module_info_pred_info(ModuleInfo, PredId, PredInfo),
+	pred_info_non_imported_procids(PredInfo, ProcIds),
+	list__member(ProcId, ProcIds).
+
+pred_module(proc(PredId, _ProcId), ModuleInfo, Name) :-
+	module_info_pred_info(ModuleInfo, PredId, PredInfo),
+	pred_info_module(PredInfo, Name).
 
 status_is_exported(imported(_),			no).
 status_is_exported(abstract_imported,		no).
Index: compiler/inlining.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/inlining.m,v
retrieving revision 1.84
diff -u -r1.84 inlining.m
--- compiler/inlining.m	1999/10/25 03:48:59	1.84
+++ compiler/inlining.m	2000/02/25 23:38:41
@@ -265,7 +265,8 @@
 			{ NumUses = 1 }
 		),
 		% Don't inline recursive predicates
-		{ \+ goal_calls(CalledGoal, PredProcId) },
+		{ PredProcId = proc(PredId, _ProcId) },
+		{ \+ goal_calls_pred_id(CalledGoal, PredId) },
 
 		% Under no circumstances inline model_non pragma c codes.
 		% The resulting code would not work properly.
Index: compiler/jumpopt.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/jumpopt.m,v
retrieving revision 1.51
diff -u -r1.51 jumpopt.m
--- compiler/jumpopt.m	2000/01/14 01:10:20	1.51
+++ compiler/jumpopt.m	2000/02/25 23:38:47
@@ -741,6 +741,13 @@
 	jumpopt__short_labels_lval(Lval0, Instrmap, Lval).
 jumpopt__short_labels_rval(var(_), _, _) :-
 	error("var rval in jumpopt__short_labels_rval").
+jumpopt__short_labels_rval(c_func(RetType, Name, TypeRvals0, Static),
+		Instrmap, c_func(RetType, Name, TypeRvals, Static)) :-
+	list__map(lambda([Pair0::in, Pair::out] is det, (
+		Pair0 = Type - RVal0,
+		jumpopt__short_labels_rval(RVal0, Instrmap, RVal),
+		Pair = Type - RVal
+	)), TypeRvals0, TypeRvals).
 jumpopt__short_labels_rval(
 		create(Tag, Rvals0, ArgTypes, StatDyn, Cell, Type, Reuse0),
 		Instrmap,
@@ -816,6 +823,7 @@
 jumpopt__short_labels_lval(hp, _, hp).
 jumpopt__short_labels_lval(sp, _, sp).
 jumpopt__short_labels_lval(temp(T, N), _, temp(T, N)).
+jumpopt__short_labels_lval(global(N, T), _, global(N, T)).
 jumpopt__short_labels_lval(stackvar(N), _, stackvar(N)).
 jumpopt__short_labels_lval(framevar(N), _, framevar(N)).
 jumpopt__short_labels_lval(succip(Rval0), Instrmap, succip(Rval)) :-
Index: compiler/lambda.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/lambda.m,v
retrieving revision 1.60
diff -u -r1.60 lambda.m
--- compiler/lambda.m	2000/02/08 15:07:53	1.60
+++ compiler/lambda.m	2000/02/25 23:38:47
@@ -129,7 +129,10 @@
 lambda__process_pred(PredId, ModuleInfo0, ModuleInfo) :-
 	module_info_pred_info(ModuleInfo0, PredId, PredInfo),
 	pred_info_procids(PredInfo, ProcIds),
-	lambda__process_procs(PredId, ProcIds, ModuleInfo0, ModuleInfo).
+	lambda__process_procs(PredId, ProcIds, ModuleInfo0, ModuleInfo1),
+		% Processing lambdas changes the call graph, so we'd
+		% better invalidate the dependency_info.
+	module_info_clobber_dependency_info(ModuleInfo1, ModuleInfo).
 
 :- pred lambda__process_procs(pred_id, list(proc_id), module_info, module_info).
 :- mode lambda__process_procs(in, in, in, out) is det.
Index: compiler/livemap.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/livemap.m,v
retrieving revision 1.46
diff -u -r1.46 livemap.m
--- compiler/livemap.m	2000/01/14 01:10:21	1.46
+++ compiler/livemap.m	2000/02/25 23:38:47
@@ -455,6 +455,11 @@
 	error("var rval should not propagate to the optimizer").
 livemap__make_live_in_rval(mem_addr(MemRef), Live0, Live) :-
 	livemap__make_live_in_mem_ref(MemRef, Live0, Live).
+livemap__make_live_in_rval(c_func(_, _, Args, _), Live0, Live) :-
+	list__foldl(lambda([Arg::in, Live1::in, Live2::out] is det, (
+		Arg = _Type - Rval,
+		livemap__make_live_in_rval(Rval, Live1, Live2)
+	)), Args, Live0, Live).
 
 :- pred livemap__make_live_in_mem_ref(mem_ref, lvalset, lvalset).
 :- mode livemap__make_live_in_mem_ref(in, in, out) is det.
Index: compiler/llds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.257
diff -u -r1.257 llds.m
--- compiler/llds.m	2000/02/10 04:37:30	1.257
+++ compiler/llds.m	2000/02/25 23:38:51
@@ -129,7 +129,12 @@
 			proc_label		% The id of the procedure
 						% whose table this variable
 						% represents.
-		).
+		)
+	;	scc_id_counter(
+			module_name,
+			int
+		)
+	.
 
 	% Global data generated by the compiler. Usually readonly,
 	% with one exception: data containing code addresses must
@@ -645,6 +650,9 @@
 	;	sp		% Virtual machine register point to the
 				% top of det stack.
 
+	;	global(llds_type, string)
+				% A global variable
+
 	;	temp(reg_type, int)
 				% A local temporary register.
 				% These temporary registers are actually
@@ -788,15 +796,33 @@
 
 	;	binop(binary_op, rval, rval)
 
-	;	mem_addr(mem_ref).
+	;	mem_addr(mem_ref)
 		% The address of a word in the heap, the det stack or
 		% the nondet stack.
 
+	;	c_func(
+			llds_type,			% return type
+			string,				% name
+			list(pair(llds_type, rval)),	% arguments
+			staticly_evaluable		% static or dynamic?
+		)
+		% calls some arbitary C function with the given rvals as
+		% arguments.
+	.
+
 :- type static_or_dynamic
 	--->	must_be_static
 	;	can_be_either
 	;	must_be_dynamic.
 
+	% For c_func rvals, staticly_evaluable tells the compiler whether
+	% the value of the function can be determined at compile time, or
+	% whether it needs to be defered till runtime.
+:- type staticly_evaluable
+	--->	static
+	;	dynamic
+	.
+
 	% Values of this type specify the C types and therefore the sizes
 	% of the arguments of a create rval.
 	%
@@ -848,6 +874,7 @@
 
 :- type data_name
 	--->	common(int)
+	;	scc_id(int)
 	;	type_ctor(base_data, string, arity)
 			% base_data, type name, type arity
 	;	base_typeclass_info(class_id, string)
@@ -1052,6 +1079,7 @@
 llds__lval_type(lvar(_), _) :-
 	error("lvar unexpected in llds__lval_type").
 llds__lval_type(mem_ref(_), word).
+llds__lval_type(global(Type, _), Type).
 
 llds__rval_type(lval(Lval), Type) :-
 	llds__lval_type(Lval, Type).
@@ -1078,6 +1106,7 @@
 llds__rval_type(binop(BinOp, _, _), Type) :-
 	llds__binop_return_type(BinOp, Type).
 llds__rval_type(mem_addr(_), data_ptr).
+llds__rval_type(c_func(RetType, _, _, _), RetType).
 
 llds__const_type(true, bool).
 llds__const_type(false, bool).
Index: compiler/llds_common.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_common.m,v
retrieving revision 1.28
diff -u -r1.28 llds_common.m
--- compiler/llds_common.m	2000/02/10 04:37:38	1.28
+++ compiler/llds_common.m	2000/02/25 23:38:52
@@ -310,6 +310,16 @@
 		Rval0 = mem_addr(MemRef0),
 		llds_common__process_mem_ref(MemRef0, MemRef, Info0, Info),
 		Rval = mem_addr(MemRef)
+	;
+		Rval0 = c_func(RetType, FuncName, Args0, Staticness),
+		list__map_foldl(lambda([Arg0::in, Arg::out,
+				Info1::in, Info2::out] is det, (
+			Arg0 = Type - ArgRval0,
+			llds_common__process_rval(ArgRval0, ArgRval, Info1,
+				Info2),
+			Arg = Type - ArgRval
+		)), Args0, Args, Info0, Info),
+		Rval = c_func(RetType, FuncName, Args, Staticness)
 	).
 
 :- pred llds_common__process_mem_ref(mem_ref::in, mem_ref::out,
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.135
diff -u -r1.135 llds_out.m
--- compiler/llds_out.m	2000/02/10 04:37:32	1.135
+++ compiler/llds_out.m	2000/02/25 23:39:00
@@ -706,16 +706,17 @@
 	io__write_string("\n"),
 	{ DataAddr = data_addr(data_addr(ModuleName, VarName)) },
 
-	{ linkage(VarName, Linkage) },
-	{
-		( Linkage = extern, ExportedFromModule = yes
-		; Linkage = static, ExportedFromModule = no
-		)
-	->
-		true
-	;
-		error("linkage mismatch")
-	},
+	%globals__io_lookup_bool_option(profile_deep, ProfileDeep),
+	%{ linkage(VarName, ProfileDeep, Linkage) },
+	%{
+	%	( Linkage = extern, ExportedFromModule = yes
+	%	; Linkage = static, ExportedFromModule = no
+	%	)
+	%->
+	%	true
+	%;
+	%	error("linkage mismatch")
+	%},
 
 		% The code for data local to a Mercury module
 		% should normally be visible only within the C file
@@ -784,6 +785,15 @@
 	{ DataAddr = data_addr(ModuleName, tabling_pointer(ProcLabel)) },
 	{ decl_set_insert(DeclSet0, data_addr(DataAddr), DeclSet) }.
 
+output_comp_gen_c_var(scc_id_counter(ModuleName, SCCNum),
+		DeclSet, DeclSet) -->
+	{ llds_out__sym_name_mangle(ModuleName, MangledModuleName) },
+	io__write_string("\nInteger mercury_var__"),
+	io__write_string(MangledModuleName),
+	io__write_string("__scc_id__"),
+	io__write_int(SCCNum),
+	io__write_string(" = 0;\n").
+
 :- pred output_comp_gen_c_data_list(list(comp_gen_c_data)::in,
 	decl_set::in, decl_set::out, io__state::di, io__state::uo) is det.
 
@@ -807,16 +817,18 @@
 	% computed by linkage/2 from the dataname, which we use for any
 	% prior declarations.
 	%
-	{ linkage(VarName, Linkage) },
-	{
-		( Linkage = extern, ExportedFromModule = yes
-		; Linkage = static, ExportedFromModule = no
-		)
-	->
-		true
-	;
-		error("linkage mismatch")
-	},
+	% XXX
+	%globals__io_get_globals(Globals),
+	%{ linkage(VarName, Globals, Linkage) },
+	%{
+	%	( Linkage = extern, ExportedFromModule = yes
+	%	; Linkage = static, ExportedFromModule = no
+	%	)
+	%->
+	%	true
+	%;
+	%	error("linkage mismatch")
+	%},
 	
 		% The code for data local to a Mercury module
 		% should normally be visible only within the C file
@@ -2134,6 +2146,10 @@
 		N0, N, DeclSet0, DeclSet) -->
 	output_mem_ref_decls(MemRef, FirstIndent, LaterIndent,
 		N0, N, DeclSet0, DeclSet).
+output_rval_decls(c_func(_RT, _, Args, _St), FirstIndent, LaterIndent,
+		N0, N, DeclSet0, DeclSet) -->
+	output_arg_decls(Args, FirstIndent, LaterIndent,
+		N0, N, DeclSet0, DeclSet).
 
 :- pred output_mem_ref_decls(mem_ref, string, string, int, int,
 	decl_set, decl_set, io__state, io__state).
@@ -2146,6 +2162,16 @@
 	output_rval_decls(Rval, FirstIndent, LaterIndent, N0, N,
 		DeclSet0, DeclSet).
 
+:- pred output_arg_decls(list(pair(llds_type, rval)), string, string, int, int,
+	decl_set, decl_set, io__state, io__state).
+:- mode output_arg_decls(in, in, in, in, out, in, out, di, uo) is det.
+
+output_arg_decls([], _, _, N, N, DeclSet, DeclSet) --> [].
+output_arg_decls([_Type - Rval|Args], First, Later,
+		N0, N, DeclSet0, DeclSet) -->
+	output_rval_decls(Rval, First, Later, N0, N1, DeclSet0, DeclSet1),
+	output_arg_decls(Args, First, Later, N1, N, DeclSet1, DeclSet).
+
 %-----------------------------------------------------------------------------%
 
 % The following predicates are used to compute the names used for
@@ -2344,6 +2370,7 @@
 data_name_would_include_code_address(base_typeclass_info(_, _), yes).
 data_name_would_include_code_address(module_layout, no).
 data_name_would_include_code_address(proc_layout(_), yes).
+data_name_would_include_code_address(scc_id(_), yes).
 data_name_would_include_code_address(internal_layout(_), no).
 data_name_would_include_code_address(tabling_pointer(_), no).
 
@@ -2642,6 +2669,7 @@
 output_lval_decls(sp, _, _, N, N, DeclSet, DeclSet) --> [].
 output_lval_decls(lvar(_), _, _, N, N, DeclSet, DeclSet) --> [].
 output_lval_decls(temp(_, _), _, _, N, N, DeclSet, DeclSet) --> [].
+output_lval_decls(global(_, _), _, _, N, N, DeclSet, DeclSet) --> [].
 output_lval_decls(mem_ref(Rval), FirstIndent, LaterIndent, N0, N,
 		DeclSet0, DeclSet) -->
 	output_rval_decls(Rval, FirstIndent, LaterIndent, N0, N,
@@ -2833,8 +2861,9 @@
 	% works, but on some systems such as RS/6000s running AIX
 	% it results in link errors.
 	%
-	{ linkage(VarName, Linkage) },
+	globals__io_lookup_bool_option(profile_deep, ProfileDeep),
 	globals__io_lookup_bool_option(split_c_files, SplitFiles),
+	{ linkage(VarName, ProfileDeep, Linkage) },
 	(
 		( { Linkage = extern }
 		; { SplitFiles = yes }
@@ -2883,20 +2912,25 @@
 % the definition) which says whether or not a data name is exported
 % is not useful.  Instead, we need to determine whether or not something
 % is exported from its `data_name'.
+% If deep profiling is enabled, then the proc_layout for a procedure
+% may be referenced by the scc data for another module.
 %
 
 :- type linkage ---> extern ; static.
 
-:- pred linkage(data_name::in, linkage::out) is det.
-linkage(common(_),                 static).
-linkage(type_ctor(info, _, _),     extern).
-linkage(type_ctor(layout, _, _),   static).
-linkage(type_ctor(functors, _, _), static).
-linkage(base_typeclass_info(_, _), extern).
-linkage(module_layout,             static).
-linkage(proc_layout(_),            static).
-linkage(internal_layout(_),        static).
-linkage(tabling_pointer(_),        static).
+:- pred linkage(data_name::in, bool::in, linkage::out) is det.
+linkage(common(_),                 _,	static).
+linkage(type_ctor(info, _, _),     _,	extern).
+linkage(type_ctor(layout, _, _),   _,	static).
+linkage(type_ctor(functors, _, _), _,	static).
+linkage(base_typeclass_info(_, _), _,	extern).
+linkage(module_layout,             _,	static).
+linkage(proc_layout(_),            _,	extern).
+% linkage(proc_layout(_),            no,	static).
+% linkage(proc_layout(_),            yes,	extern).
+linkage(internal_layout(_),        _,	static).
+linkage(tabling_pointer(_),        _,	static).
+linkage(scc_id(_),        	   _,	extern).
 
 %-----------------------------------------------------------------------------%
 
@@ -3156,6 +3190,13 @@
 		{ string__int_to_string(N, NStr) },
 		io__write_string(NStr)
 	;
+		{ VarName = scc_id(N) },
+		{ llds_out__sym_name_mangle(ModuleName, MangledModuleName) },
+		io__write_string(MangledModuleName),
+		io__write_string("__scc_id_"),
+		{ string__int_to_string(N, NStr) },
+		io__write_string(NStr)
+	;
 		{ VarName = type_ctor(BaseData, TypeName0, TypeArity) },
 		{ llds_out__sym_name_mangle(ModuleName, MangledModuleName) },
 		io__write_string("mercury_data_"),
@@ -3713,7 +3754,24 @@
 		io__write_int(FieldNum),
 		io__write_string(")")
 	).
+output_rval(c_func(_RT, FuncName, Arguments, _Static)) -->
+	io__write_string(FuncName),
+	io__write_string("("),
+	output_c_func_args(Arguments),
+	io__write_string(")").
 
+:- pred output_c_func_args(list(pair(llds_type, rval)), io__state, io__state).
+:- mode output_c_func_args(in, di, uo) is det.
+
+output_c_func_args([]) --> [].
+output_c_func_args([Type - Rval]) -->
+	output_rval_as_type(Rval, Type).
+output_c_func_args([Type - Rval|Args]) -->
+	{ Args = [_|_] },
+	output_rval_as_type(Rval, Type),
+	io__write_string(", "),
+	output_c_func_args(Args).
+
 :- pred output_unary_op(unary_op, io__state, io__state).
 :- mode output_unary_op(in, di, uo) is det.
 
@@ -3802,6 +3860,29 @@
 	{ error("Cannot output a var(_) in a static initializer") }.
 output_static_rval(mem_addr(_)) -->
 	{ error("Cannot output a mem_ref(_) in a static initializer") }.
+output_static_rval(c_func(_RT, Name, Args, Static)) -->
+	(
+		{ Static = static },
+		write_string(Name),
+		write_string("("),
+		output_static_rvals(Args),
+		write_string(")")
+	;
+		{ Static = dynamic },
+		{ error("Cannot output a c_func/4 in a static initializer") }
+	).
+
+:- pred output_static_rvals(list(pair(llds_type, rval)), io__state, io__state).
+:- mode output_static_rvals(in, di, uo) is det.
+
+output_static_rvals([]) --> [].
+output_static_rvals([_Type - Rval]) -->
+	output_static_rval(Rval).
+output_static_rvals([_Type - Rval|Rvals]) -->
+	{ Rvals = [_|_] },
+	output_static_rval(Rval),
+	write_string(", "),
+	output_static_rvals(Rvals).
 
 :- pred output_rval_static_const(rval_const, io__state, io__state).
 :- mode output_rval_static_const(in, di, uo) is det.
@@ -3905,6 +3986,12 @@
 output_lval(succip(Rval)) -->
 	io__write_string("MR_succip_slot("),
 	output_rval(Rval),
+	io__write_string(")").
+output_lval(global(Type, GlobalName)) -->
+	io__write_string("LVALUE_CAST("),
+	output_llds_type(Type),
+	io__write_string(", "),
+	io__write_string(GlobalName),
 	io__write_string(")").
 output_lval(field(MaybeTag, Rval, FieldNum)) -->
 	( { MaybeTag = yes(Tag) } ->
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list