updated diff for tracing

Zoltan Somogyi zs at cs.mu.oz.au
Thu Oct 2 12:31:06 AEST 1997


First implementation of the generation of traces for Opium-style trace
analysis.

In this initial implementation, there are only three ports: call, exit
and fail. Later versions will add ports that indicate entry to an arm
of a switch or disjunction and to the then or else part of an if-then-else.

compiler/options.m:
	Add a new option, --generate-trace.

compiler/handle_options.m:
	When --generate-trace is on, turn off HLDS->HLDS optimizations
	that would change the behavior of the trace.

compiler/code_info.m:
	Add a new field in code_into for storing information that is
	needed when generating trace code. (At the moment, this info is
	the identity of two stack slots storing the sequence number and
	depth of the current procedure call.) This info must be in the
	code_info structure, because it is used not only by code_gen.m
	but also by call_gen.m, and later by switch_gen.m, disj_gen.m and
	ite_gen.m.

compiler/code_gen.m:
	Add code to initialize the tracing info in code_info and to add
	trace statements to procedure prologs and epilogs if --generate-trace
	is on.

compiler/call_gen.m:
	Clean up the generation of code for calls, merging the three
	predicates for det, semi and non procedures into one, and factoring
	out some common code between the generation of code for normal calls
	and higher order calls. Add code to reset the call depth just before
	each (normal or higher-order) call if --generate-trace is on.

compiler/trace.m:
	New file responsible for the generation of trace statements in the
	C file output by the compiler. Code in code_gen.m and call_gen.m
	calls trace.m; so will code in switch_gen.m, disj_gen.m and ite_gen.m.

compiler/mercury_compile.m:
	When --generate-trace is on, include mercury_trace.h at the top
	of generated C files.

runtime/mercury_trace.[ch]:
	The new runtime tracing module. The proper version will be written
	in Rennes, this is just for initial testing.

runtime/Mmakefile:
	Include the new module in the runtime library.

doc/user_guide.texi:
	Document --generate-trace.

Zoltan.

cvs diff: Diffing .
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/call_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/call_gen.m,v
retrieving revision 1.113
diff -u -r1.113 call_gen.m
--- call_gen.m	1997/07/27 14:59:52	1.113
+++ call_gen.m	1997/10/02 00:57:26
@@ -27,17 +27,9 @@
 :- mode call_gen__generate_higher_order_call(in, in, in, in, in, in, in, out,
 				in, out) is det.
 
-:- pred call_gen__generate_det_call(pred_id, proc_id, list(var), 
+:- pred call_gen__generate_call(code_model, pred_id, proc_id, list(var),
 			hlds_goal_info, code_tree, code_info, code_info).
-:- mode call_gen__generate_det_call(in, in, in, in, out, in, out) is det.
-
-:- pred call_gen__generate_semidet_call(pred_id, proc_id, list(var),
-			hlds_goal_info, code_tree, code_info, code_info).
-:- mode call_gen__generate_semidet_call(in, in, in, in, out, in, out) is det.
-
-:- pred call_gen__generate_nondet_call(pred_id, proc_id, list(var),
-			hlds_goal_info, code_tree, code_info, code_info).
-:- mode call_gen__generate_nondet_call(in, in, in, in, out, in, out) is det.
+:- mode call_gen__generate_call(in, in, in, in, in, out, in, out) is det.
 
 :- pred call_gen__generate_det_builtin(pred_id, proc_id, list(var),
 			code_tree, code_info, code_info).
@@ -79,164 +71,244 @@
 
 :- implementation.
 
-:- import_module hlds_module, hlds_data, prog_data, code_util, globals.
+:- import_module hlds_module, hlds_goal, hlds_data, prog_data, code_util.
 :- import_module arg_info, type_util, mode_util, unify_proc, instmap.
-:- import_module hlds_goal.
+:- import_module trace, globals.
 :- import_module bool, int, list, assoc_list, tree, set, map.
 :- import_module std_util, require.
 
-	% To generate a call to a deterministic predicate, first
-	% we get the arginfo for the callee.
-	% We then save any live variables onto the stack, clear any
-	% "reserved" registers (which get allocated as temporaries
-	% during expression generation), and then setup the registers
-	% for the procedure call. We then branch to the procedure
-	% and rebuild the register information to reflect the state
-	% when the callee returns.
-call_gen__generate_det_call(PredId, ModeId, Arguments, GoalInfo, Code) -->
-	code_info__get_pred_proc_arginfo(PredId, ModeId, ArgInfo),
-	{ assoc_list__from_corresponding_lists(Arguments, ArgInfo, Args) },
-	{ call_gen__select_out_args(Args, OutArgs) },
-	call_gen__save_variables(OutArgs, CodeA),
-	code_info__setup_call(Args, caller, CodeB),
-	code_info__get_next_label(ReturnLabel),
-	code_info__get_module_info(ModuleInfo),
-
-	code_info__get_instmap(InstMap),
-	{ goal_info_get_instmap_delta(GoalInfo, InstMapDelta) },
-	{ instmap__apply_instmap_delta(InstMap, InstMapDelta,
-		AfterCallInstMap) },
+%---------------------------------------------------------------------------%
 
-	{ call_gen__input_args(ArgInfo, InputArguments) },
-	call_gen__generate_call_livevals(OutArgs, InputArguments, CodeC0),
-	{ call_gen__output_arg_locs(Args, OutputArguments) },
-	call_gen__generate_return_livevals(OutArgs, OutputArguments,
-		AfterCallInstMap, OutLiveVals),
-	code_info__make_entry_label(ModuleInfo, PredId, ModeId, yes, Address),
-	{ CodeC1 = node([
-		call(Address, label(ReturnLabel), OutLiveVals, det)
-			- "branch to det procedure",
-		label(ReturnLabel) - "Continuation label"
-	]) },
-	{ Code = tree(CodeA, tree(CodeB, tree(CodeC0, CodeC1))) },
-	call_gen__rebuild_registers(Args).
+call_gen__generate_call(CodeModel, PredId, ModeId, Arguments, GoalInfo, Code)
+		-->
 
-%---------------------------------------------------------------------------%
+		% find out which arguments are input and which are output
+	code_info__get_pred_proc_arginfo(PredId, ModeId, ArgInfo),
+	{ assoc_list__from_corresponding_lists(Arguments, ArgInfo, ArgsInfos) },
 
-	% Check whether the call was really deterministic or whether
-	% it's a nondet call for which we are pruning all solutions except the
-	% first.
+		% save the known variables on the stack, except those
+		% generated by this call
+	{ call_gen__select_out_args(ArgsInfos, OutArgs) },
+	call_gen__save_variables(OutArgs, SaveCode),
 
-call_gen__generate_semidet_call(PredId, ProcId, Arguments, GoalInfo, Code) -->
-	code_info__get_module_info(ModuleInfo),
-	{ module_info_preds(ModuleInfo, Preds) },
-	{ map__lookup(Preds, PredId, PredInfo) },
-	{ pred_info_procedures(PredInfo, Procs) },
-	{ map__lookup(Procs, ProcId, ProcInfo) },
-	{ proc_info_interface_code_model(ProcInfo, CodeModel) },
-	( { CodeModel = model_semi } ->
-		call_gen__generate_semidet_call_2(PredId, ProcId, Arguments,
-			GoalInfo, Code)
-	;
-		call_gen__generate_nondet_call(PredId, ProcId, Arguments, 
-			GoalInfo, Code)
-	).
+		% save possibly unknown variables on the stack as well
+		% if they may be needed on backtracking, and figure out the
+		% call model
+	call_gen__prepare_for_call(CodeModel, FlushCode, CallModel, _),
 
-:- pred call_gen__generate_semidet_call_2(pred_id, proc_id, list(var),
-			hlds_goal_info, code_tree, code_info, code_info).
-:- mode call_gen__generate_semidet_call_2(in, in, in, in, out, in, out) is det.
+		% move the input arguments to their registers
+	code_info__setup_call(ArgsInfos, caller, SetupCode),
 
-	% To generate a call to a semideterministic predicate, first
-	% we get the arginfo for the callee.
-	% We then save any live variables onto the stack, clear any
-	% "reserved" registers (which get allocated as temporaries
-	% during expression generation), and then setup the registers
-	% for the procedure call. We then branch to the procedure
-	% and rebuild the register information to reflect the state
-	% when the callee returns.
-	% On return we test the value in register r1 to see if the
-	% callee succeeded or failed. In the event of failure
-	% we branch to the appropriate continuation as generated by
-	% code_info__generate_failure.
+	code_info__get_maybe_trace_info(MaybeTraceInfo),
+	( { MaybeTraceInfo = yes(TraceInfo) } ->
+		{ trace__generate_depth_reset_code(TraceInfo, TraceCode) }
+	;
+		{ TraceCode = empty }
+	),
 
-call_gen__generate_semidet_call_2(PredId, ModeId, Arguments, GoalInfo, Code) -->
-	code_info__get_pred_proc_arginfo(PredId, ModeId, ArgInfo),
-	{ assoc_list__from_corresponding_lists(Arguments, ArgInfo, Args) },
-	{ call_gen__select_out_args(Args, OutArgs) },
-	call_gen__save_variables(OutArgs, CodeA),
-	code_info__setup_call(Args, caller, CodeB),
-	code_info__get_next_label(ReturnLabel),
-	code_info__get_module_info(ModuleInfo),
+		% figure out what locations are live at the call point,
+		% for use by the value numbering optimization
 	{ call_gen__input_args(ArgInfo, InputArguments) },
-	call_gen__generate_call_livevals(OutArgs, InputArguments, CodeC0),
-	{ call_gen__output_arg_locs(Args, OutputArguments) },
+	call_gen__generate_call_livevals(OutArgs, InputArguments, LiveCode),
 
+		% figure out what variables will be live at the return point,
+		% and where, for use in the accurate garbage collector
 	code_info__get_instmap(InstMap),
 	{ goal_info_get_instmap_delta(GoalInfo, InstMapDelta) },
 	{ instmap__apply_instmap_delta(InstMap, InstMapDelta,
 		AfterCallInstMap) },
-
-	call_gen__generate_return_livevals(OutArgs, OutputArguments, 
+	{ call_gen__output_arg_locs(ArgsInfos, OutputArguments) },
+	call_gen__generate_return_livevals(OutArgs, OutputArguments,
 		AfterCallInstMap, OutLiveVals),
+
+		% make the call
+	code_info__get_module_info(ModuleInfo),
 	code_info__make_entry_label(ModuleInfo, PredId, ModeId, yes, Address),
-	{ CodeC1 = node([
-		call(Address, label(ReturnLabel), OutLiveVals, semidet)
-			- "branch to semidet procedure",
+	code_info__get_next_label(ReturnLabel),
+	{ call_gen__call_comment(CodeModel, CallComment) },
+	{ CallCode = node([
+		call(Address, label(ReturnLabel), OutLiveVals, CallModel)
+			- CallComment,
 		label(ReturnLabel)
-			- "Continuation label"
+			- "continuation label"
 	]) },
-	call_gen__rebuild_registers(Args),
-	code_info__generate_failure(FailCode),
-	code_info__get_next_label(ContLab),
-	{ CodeD = tree(node([
-		if_val(lval(reg(r, 1)), label(ContLab)) -
-			"Test for success"
-		]), tree(FailCode, node([ label(ContLab) - "" ]))) },
 
-	{ Code = tree(CodeA, tree(CodeB, tree(tree(CodeC0, CodeC1), CodeD))) }.
+	call_gen__rebuild_registers(ArgsInfos),
+	call_gen__handle_failure(CodeModel, FailHandlingCode),
+
+	{ Code =
+		tree(SaveCode,
+		tree(FlushCode,
+		tree(SetupCode,
+		tree(TraceCode,
+		tree(LiveCode,
+		tree(CallCode,
+		     FailHandlingCode))))))
+	}.
 
 %---------------------------------------------------------------------------%
 
-call_gen__generate_nondet_call(PredId, ModeId, Arguments, GoalInfo, Code) -->
-	code_info__get_pred_proc_arginfo(PredId, ModeId, ArgInfo),
-	{ assoc_list__from_corresponding_lists(Arguments, ArgInfo, Args) },
-	{ call_gen__select_out_args(Args, OutArgs) },
-	call_gen__save_variables(OutArgs, SaveCode),
-	code_info__may_use_nondet_tailcall(TailCall),
-	code_info__unset_failure_cont(FlushCode),
-	code_info__setup_call(Args, caller, SetupCode),
-	code_info__get_next_label(ReturnLabel),
+	%
+	% for a higher-order call,
+	% we split the arguments into inputs and outputs, put the inputs
+	% in the locations expected by do_call_<detism>_closure in
+	% runtime/call.mod, generate the call to do_call_<detism>_closure,
+	% and pick up the outputs from the locations that we know
+	% runtime/call.mod leaves them in.
+	%
+	% lambda.m transforms the generated lambda predicates to
+	% make sure that all inputs come before all outputs, so that
+	% runtime/call.mod doesn't have trouble figuring out which registers
+	% the arguments go in.
+	%
+
+call_gen__generate_higher_order_call(_OuterCodeModel, PredVar, Args, Types,
+		Modes, Det, GoalInfo, Code) -->
+	{ determinism_to_code_model(Det, CodeModel) },
+	code_info__get_globals(Globals),
 	code_info__get_module_info(ModuleInfo),
-	{ call_gen__input_args(ArgInfo, InputArguments) },
-	call_gen__generate_call_livevals(OutArgs, InputArguments, LiveCode),
-	{ call_gen__output_arg_locs(Args, OutputArguments) },
+	{ globals__get_args_method(Globals, ArgsMethod) },
+	{ make_arg_infos(ArgsMethod, Types, Modes, CodeModel, ModuleInfo,
+		ArgInfos) },
+	{ assoc_list__from_corresponding_lists(Args, ArgInfos, ArgsInfos) },
+	{ call_gen__partition_args(ArgsInfos, InVars, OutVars) },
+	code_info__succip_is_used,
+	{ set__list_to_set(OutVars, OutArgs) },
+	call_gen__save_variables(OutArgs, SaveCode),
 
+	call_gen__prepare_for_call(CodeModel, FlushCode, CallModel,
+		RuntimeAddr),
+
+		% place the immediate input arguments in registers
+		% starting at r4.
+	call_gen__generate_immediate_args(InVars, 4, InLocs, ImmediateCode),
+	code_info__generate_stack_livevals(OutArgs, LiveVals0),
+	{ set__insert_list(LiveVals0,
+		[reg(r, 1), reg(r, 2), reg(r, 3) | InLocs], LiveVals) },
+	(
+		{ CodeModel = model_semi }
+	->
+		{ FirstArg = 2 }
+	;
+		{ FirstArg = 1 }
+	),
+
+	{ call_gen__outvars_to_outargs(OutVars, FirstArg, OutArguments) },
+	{ call_gen__output_arg_locs(OutArguments, OutLocs) },
 	code_info__get_instmap(InstMap),
 	{ goal_info_get_instmap_delta(GoalInfo, InstMapDelta) },
 	{ instmap__apply_instmap_delta(InstMap, InstMapDelta,
 		AfterCallInstMap) },
+	call_gen__generate_return_livevals(OutArgs, OutLocs, AfterCallInstMap, 
+		OutLiveVals),
 
-	call_gen__generate_return_livevals(OutArgs, OutputArguments,
-		AfterCallInstMap, OutLiveVals),
-	code_info__make_entry_label(ModuleInfo, PredId, ModeId, yes, Address),
-	{ CallModel = nondet(TailCall) },
+	code_info__produce_variable(PredVar, PredVarCode, PredRVal),
+	(
+		{ PredRVal = lval(reg(r, 1)) }
+	->
+		{ CopyCode = empty }
+	;
+		{ CopyCode = node([
+			assign(reg(r, 1), PredRVal) - "Copy pred-term"
+		]) }
+	),
+
+	{ list__length(InVars, NInVars) },
+	{ list__length(OutVars, NOutVars) },
+	{ ArgNumCode = node([
+		assign(reg(r, 2), const(int_const(NInVars))) -
+			"Assign number of immediate input arguments",
+		assign(reg(r, 3), const(int_const(NOutVars))) -
+			"Assign number of output arguments"
+	]) },
+
+	code_info__get_maybe_trace_info(MaybeTraceInfo),
+	( { MaybeTraceInfo = yes(TraceInfo) } ->
+		{ trace__generate_depth_reset_code(TraceInfo, TraceCode) }
+	;
+		{ TraceCode = empty }
+	),
+
+	code_info__get_next_label(ReturnLabel),
 	{ CallCode = node([
-		call(Address, label(ReturnLabel), OutLiveVals, CallModel)
-			- "branch to nondet procedure",
+		livevals(LiveVals)
+			- "",
+		call(RuntimeAddr, label(ReturnLabel), OutLiveVals, CallModel)
+			- "setup and call higher order pred",
 		label(ReturnLabel)
 			- "Continuation label"
 	]) },
-	call_gen__rebuild_registers(Args),
+
+	call_gen__rebuild_registers(OutArguments),
+	call_gen__handle_failure(CodeModel, FailHandlingCode),
+
 	{ Code =
 		tree(SaveCode,
 		tree(FlushCode,
-		tree(SetupCode,
-		tree(LiveCode,
-		     CallCode))))
+		tree(ImmediateCode,
+		tree(PredVarCode,
+		tree(CopyCode,
+		tree(ArgNumCode,
+		tree(TraceCode,
+		tree(CallCode,
+		     FailHandlingCode))))))))
 	}.
 
 %---------------------------------------------------------------------------%
 
+:- pred call_gen__prepare_for_call(code_model, code_tree, call_model,
+	code_addr, code_info, code_info).
+:- mode call_gen__prepare_for_call(in, out, out, out, in, out) is det.
+
+call_gen__prepare_for_call(CodeModel, FlushCode, CallModel, RuntimeAddr) -->
+	(
+		{ CodeModel = model_det },
+		{ CallModel = det },
+		{ RuntimeAddr = do_det_closure },
+		{ FlushCode = empty }
+	;
+		{ CodeModel = model_semi },
+		{ CallModel = semidet },
+		{ RuntimeAddr = do_semidet_closure },
+		{ FlushCode = empty }
+	;
+		{ CodeModel = model_non },
+		code_info__may_use_nondet_tailcall(TailCall),
+		{ CallModel = nondet(TailCall) },
+		{ RuntimeAddr = do_nondet_closure },
+		code_info__unset_failure_cont(FlushCode)
+	).
+
+:- pred call_gen__handle_failure(code_model, code_tree, code_info, code_info).
+:- mode call_gen__handle_failure(in, out, in, out ) is det.
+
+call_gen__handle_failure(CodeModel, FailHandlingCode) -->
+	( { CodeModel = model_semi } ->
+		code_info__generate_failure(FailCode),
+		code_info__get_next_label(ContLab),
+		{ FailTestCode = node([
+			if_val(lval(reg(r, 1)), label(ContLab))
+				- "test for success"
+		]) },
+		{ ContLabelCode = node([label(ContLab) - ""]) },
+		{ FailHandlingCode =
+			tree(FailTestCode,
+			tree(FailCode, 
+			     ContLabelCode))
+		}
+	;
+		{ FailHandlingCode = empty }
+	).
+
+:- pred call_gen__call_comment(code_model, string).
+:- mode call_gen__call_comment(in, out) is det.
+
+call_gen__call_comment(model_det,  "branch to det procedure").
+call_gen__call_comment(model_semi, "branch to semidet procedure").
+call_gen__call_comment(model_non,  "branch to nondet procedure").
+
+%---------------------------------------------------------------------------%
+
 call_gen__save_variables(Args, Code) -->
 	code_info__get_known_variables(Variables0),
 	{ set__list_to_set(Variables0, Vars0) },
@@ -580,138 +652,6 @@
 	{ code_util__arg_loc_to_register(L, R) },
 	call_gen__insert_arg_livelvals(As, GC_Method, AfterCallInstMap, 
 		[LiveVal | LiveVals0], LiveVals).
-
-%---------------------------------------------------------------------------%
-
-	%
-	% for a higher-order call,
-	% we split the arguments into inputs and outputs, put the inputs
-	% in the locations expected by do_call_<detism>_closure in
-	% runtime/call.mod, generate the call to do_call_<detism>_closure,
-	% and pick up the outputs from the locations that we know
-	% runtime/call.mod leaves them in.
-	%
-	% lambda.m transforms the generated lambda predicates to
-	% make sure that all inputs come before all outputs, so that
-	% runtime/call.mod doesn't have trouble figuring out which registers
-	% the arguments go in.
-	%
-
-call_gen__generate_higher_order_call(_OuterCodeModel, PredVar, Args, Types,
-		Modes, Det, GoalInfo, Code) -->
-	{ determinism_to_code_model(Det, InnerCodeModel) },
-	code_info__get_globals(Globals),
-	code_info__get_module_info(ModuleInfo),
-	{ globals__get_args_method(Globals, ArgsMethod) },
-	{ make_arg_infos(ArgsMethod, Types, Modes, InnerCodeModel, ModuleInfo,
-		ArgInfo) },
-	{ assoc_list__from_corresponding_lists(Args, ArgInfo, ArgsAndArgInfo) },
-	{ call_gen__partition_args(ArgsAndArgInfo, InVars, OutVars) },
-	call_gen__generate_higher_call(InnerCodeModel, PredVar, InVars, OutVars,
-		GoalInfo, Code).
-
-:- pred call_gen__generate_higher_call(code_model, var, list(var), list(var),
-			hlds_goal_info, code_tree, code_info, code_info).
-:- mode call_gen__generate_higher_call(in, in, in, in, in, out, in, out) is det.
-
-call_gen__generate_higher_call(CodeModel, PredVar, InVars, OutVars, GoalInfo,
-		Code) -->
-	code_info__succip_is_used,
-	{ set__list_to_set(OutVars, OutArgs) },
-	call_gen__save_variables(OutArgs, SaveCode),
-	(
-		{ CodeModel = model_det },
-		{ CallModel = det },
-		{ RuntimeAddr = do_det_closure },
-		{ FlushCode = empty }
-	;
-		{ CodeModel = model_semi },
-		{ CallModel = semidet },
-		{ RuntimeAddr = do_semidet_closure },
-		{ FlushCode = empty }
-	;
-		{ CodeModel = model_non },
-		code_info__may_use_nondet_tailcall(TailCall),
-		{ CallModel = nondet(TailCall) },
-		{ RuntimeAddr = do_nondet_closure },
-		code_info__unset_failure_cont(FlushCode)
-	),
-		% place the immediate input arguments in registers
-		% starting at r4.
-	call_gen__generate_immediate_args(InVars, 4, InLocs, ImmediateCode),
-	code_info__generate_stack_livevals(OutArgs, LiveVals0),
-	{ set__insert_list(LiveVals0,
-		[reg(r, 1), reg(r, 2), reg(r, 3) | InLocs], LiveVals) },
-	(
-		{ CodeModel = model_semi }
-	->
-		{ FirstArg = 2 }
-	;
-		{ FirstArg = 1 }
-	),
-	{ call_gen__outvars_to_outargs(OutVars, FirstArg, OutArguments) },
-	{ call_gen__output_arg_locs(OutArguments, OutLocs) },
-
-	code_info__get_instmap(InstMap),
-	{ goal_info_get_instmap_delta(GoalInfo, InstMapDelta) },
-	{ instmap__apply_instmap_delta(InstMap, InstMapDelta,
-		AfterCallInstMap) },
-
-	call_gen__generate_return_livevals(OutArgs, OutLocs, AfterCallInstMap, 
-		OutLiveVals),
-	code_info__produce_variable(PredVar, PredVarCode, PredRVal),
-	(
-		{ PredRVal = lval(reg(r, 1)) }
-	->
-		{ CopyCode = empty }
-	;
-		{ CopyCode = node([
-			assign(reg(r, 1), PredRVal) - "Copy pred-term"
-		])}
-	),
-	{ list__length(InVars, NInVars) },
-	{ list__length(OutVars, NOutVars) },
-	{ SetupCode = tree(CopyCode, node([
-			assign(reg(r, 2), const(int_const(NInVars))) -
-				"Assign number of immediate input arguments",
-			assign(reg(r, 3), const(int_const(NOutVars))) -
-				"Assign number of output arguments"
-		])
-	) },
-	code_info__get_next_label(ReturnLabel),
-	{ TryCallCode = node([
-		livevals(LiveVals) - "",
-		call(RuntimeAddr, label(ReturnLabel), OutLiveVals, CallModel)
-			- "setup and call higher order pred",
-		label(ReturnLabel) - "Continuation label"
-	]) },
-	call_gen__rebuild_registers(OutArguments),
-	(
-		{ CodeModel = model_semi }
-	->
-		code_info__generate_failure(FailCode),
-		code_info__get_next_label(ContLab),
-		{ TestSuccessCode = node([
-			if_val(lval(reg(r, 1)), label(ContLab)) -
-				"Test for success"
-		]) },
-		{ ContLabelCode = node([label(ContLab) - ""]) },
-		{ CallCode =
-			tree(TryCallCode,
-			tree(TestSuccessCode,
-			tree(FailCode,
-			     ContLabelCode))) }
-	;
-		{ CallCode = TryCallCode }
-	),
-	{ Code =
-		tree(SaveCode,
-		tree(FlushCode,
-		tree(ImmediateCode,
-		tree(PredVarCode,
-		tree(SetupCode,
-		     CallCode)))))
-	}.
 
 %---------------------------------------------------------------------------%
 
Index: compiler/code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_gen.m,v
retrieving revision 1.36
diff -u -r1.36 code_gen.m
--- code_gen.m	1997/09/25 03:34:48	1.36
+++ code_gen.m	1997/09/30 22:04:53
@@ -57,9 +57,9 @@
 
 :- implementation.
 
-:- import_module call_gen, unify_gen, ite_gen, switch_gen.
-:- import_module disj_gen, pragma_c_gen, globals, options, hlds_out.
-:- import_module code_aux, middle_rec, passes_aux.
+:- import_module call_gen, unify_gen, ite_gen, switch_gen, disj_gen.
+:- import_module pragma_c_gen, trace, globals, options, hlds_out.
+:- import_module code_aux, middle_rec, passes_aux, llds_out.
 :- import_module code_util, type_util, mode_util.
 :- import_module prog_data, instmap.
 :- import_module bool, char, int, string, list, term.
@@ -203,8 +203,14 @@
 		PredId, ProcId, ProcInfo, InitialInst, FollowVars,
 		ModuleInfo, CellCount0, ContInfo0, CodeInfo0),
 		% generate code for the procedure
+	globals__lookup_bool_option(Globals, generate_trace, Trace),
+	( Trace = yes ->
+		trace__setup(CodeInfo0, CodeInfo1)
+	;
+		CodeInfo1 = CodeInfo0
+	),
 	generate_category_code(CodeModel, Goal, CodeTree, FrameInfo,
-		CodeInfo0, CodeInfo),
+		CodeInfo1, CodeInfo),
 		% extract the new continuation_info and cell count
 	code_info__get_continuation_info(ContInfo1, CodeInfo, _CodeInfo1),
 	code_info__get_cell_count(CellCount, CodeInfo, _CodeInfo2),
@@ -258,9 +264,9 @@
 		{ Code = MiddleRecCode },
 		{ FrameInfo = frame(0, no) }
 	;
-		% Make a new failure cont (not model_non)
-		% This continuation is never actually used,
-		% but is a place holder.
+		% make a new failure cont (not model_non);
+		% this continuation is never actually used,
+		% but is a place holder
 		code_info__manufacture_failure_cont(no),
 
 		code_gen__generate_goal(model_det, Goal, BodyCode),
@@ -280,7 +286,7 @@
 	).
 
 generate_category_code(model_semi, Goal, Code, FrameInfo) -->
-		% Make a new failure cont (not model_non)
+		% make a new failure cont (not model_non)
 	code_info__manufacture_failure_cont(no),
 
 		% generate the code for the body of the clause
@@ -290,16 +296,40 @@
 	{ Code = tree(PrologCode, tree(BodyCode, EpilogCode)) }.
 
 generate_category_code(model_non, Goal, Code, FrameInfo) -->
-		% Make a failure continuation, we lie and
-		% say that it is nondet, and then unset it
-		% so that it points to do_fail
+		% make a new failure cont (yes, it is model_non)
 	code_info__manufacture_failure_cont(yes),
+		% we must arrange the tracing of failure out of this proc
+	code_info__get_maybe_trace_info(MaybeTraceInfo),
+	( { MaybeTraceInfo = yes(TraceInfo) } ->
+		{ set__init(ResumeVars) },
+		code_info__make_known_failure_cont(ResumeVars, stack_only, yes,
+			SetupCode),
+
+			% generate the code for the body of the clause
+		code_info__push_resume_point_vars(ResumeVars),
+		code_gen__generate_goal(model_non, Goal, BodyCode),
+		code_gen__generate_prolog(model_non, FrameInfo, PrologCode),
+		code_gen__generate_epilog(model_non, FrameInfo, EpilogCode),
+		code_info__pop_resume_point_vars,
+		{ MainCode = tree(PrologCode, tree(BodyCode, EpilogCode)) },
 
-		% generate the code for the body of the clause
-	code_gen__generate_goal(model_non, Goal, BodyCode),
-	code_gen__generate_prolog(model_non, FrameInfo, PrologCode),
-	code_gen__generate_epilog(model_non, FrameInfo, EpilogCode),
-	{ Code = tree(PrologCode, tree(BodyCode, EpilogCode)) }.
+		code_info__restore_failure_cont(RestoreCode),
+		trace__generate_event_code(fail, TraceInfo, TraceEventCode),
+		code_info__generate_failure(FailCode),
+		{ Code =
+			tree(MainCode,
+			tree(SetupCode,
+			tree(RestoreCode,
+			tree(TraceEventCode,
+			     FailCode))))
+		}
+	;
+			% generate the code for the body of the clause
+		code_gen__generate_goal(model_non, Goal, BodyCode),
+		code_gen__generate_prolog(model_non, FrameInfo, PrologCode),
+		code_gen__generate_epilog(model_non, FrameInfo, EpilogCode),
+		{ Code = tree(PrologCode, tree(BodyCode, EpilogCode)) }
+	).
 
 %---------------------------------------------------------------------------%
 
@@ -362,6 +392,14 @@
 		{ MaybeSuccipSlot = no }
 	),
 	{ FrameInfo = frame(TotalSlots, MaybeSuccipSlot) },
+	code_info__get_maybe_trace_info(MaybeTraceInfo),
+	( { MaybeTraceInfo = yes(TraceInfo) } ->
+		{ trace__generate_slot_fill_code(TraceInfo, TraceFillCode) },
+		trace__generate_event_code(call, TraceInfo, TraceEventCode),
+		{ TraceCode = tree(TraceFillCode, TraceEventCode) }
+	;
+		{ TraceCode = empty }
+	),
 	{ predicate_module(ModuleInfo, PredId, ModuleName) },
 	{ predicate_name(ModuleInfo, PredId, PredName) },
 	{ predicate_arity(ModuleInfo, PredId, Arity) },
@@ -393,7 +431,8 @@
 		tree(LabelCode,
 		tree(AllocCode,
 		tree(SaveSuccipCode,
-		     EndComment))))
+		tree(TraceCode,
+		     EndComment)))))
 	}.
 
 %---------------------------------------------------------------------------%
@@ -470,13 +509,30 @@
 	),
 	{ RestoreDeallocCode = tree(RestoreSuccipCode, DeallocCode ) },
 	{ code_gen__output_args(Args, LiveArgs) },
+	code_info__get_maybe_trace_info(MaybeTraceInfo),
+	( { MaybeTraceInfo = yes(TraceInfo) } ->
+		trace__generate_event_code(exit, TraceInfo, SuccessTraceCode),
+		( { CodeModel = model_semi } ->
+			trace__generate_event_code(fail, TraceInfo,
+				FailureTraceCode)
+		;
+			{ FailureTraceCode = empty }
+		)
+	;
+		{ SuccessTraceCode = empty },
+		{ FailureTraceCode = empty }
+	),
 	(
 		{ CodeModel = model_det },
 		{ SuccessCode = node([
 			livevals(LiveArgs) - "",
 			goto(succip) - "Return from procedure call"
 		]) },
-		{ AllSuccessCode = tree(RestoreDeallocCode, SuccessCode) },
+		{ AllSuccessCode =
+			tree(SuccessTraceCode,
+			tree(RestoreDeallocCode,
+			     SuccessCode))
+		},
 		{ AllFailureCode = empty }
 	;
 		{ CodeModel = model_semi },
@@ -487,21 +543,33 @@
 			livevals(SuccessLiveRegs) - "",
 			goto(succip) - "Return from procedure call"
 		]) },
-		{ AllSuccessCode = tree(RestoreDeallocCode, SuccessCode) },
+		{ AllSuccessCode =
+			tree(SuccessTraceCode,
+			tree(RestoreDeallocCode,
+			     SuccessCode))
+		},
 		{ set__singleton_set(FailureLiveRegs, reg(r, 1)) },
 		{ FailureCode = node([
 			assign(reg(r, 1), const(false)) - "Fail",
 			livevals(FailureLiveRegs) - "",
 			goto(succip) - "Return from procedure call"
 		]) },
-		{ AllFailureCode = tree(ResumeCode,
-			tree(RestoreDeallocCode, FailureCode)) }
+		{ AllFailureCode =
+			tree(ResumeCode,
+			tree(FailureTraceCode,
+			tree(RestoreDeallocCode,
+			     FailureCode)))
+		}
 	;
 		{ CodeModel = model_non },
-		{ AllSuccessCode = node([
+		{ SuccessCode = node([
 			livevals(LiveArgs) - "",
 			goto(do_succeed(no)) - "Return from procedure call"
 		]) },
+		{ AllSuccessCode =
+			tree(SuccessTraceCode,
+			     SuccessCode)
+		},
 		{ AllFailureCode = empty }
 	),
 	{ EndComment = node([
@@ -635,8 +703,8 @@
 		{ BuiltinState = not_builtin }
 	->
 		code_info__succip_is_used,
-		call_gen__generate_det_call(PredId, ProcId, Args, GoalInfo,
-			Instr)
+		call_gen__generate_call(model_det, PredId, ProcId, Args,
+			GoalInfo, Instr)
 	;
 		call_gen__generate_det_builtin(PredId, ProcId, Args, Instr)
 	).
@@ -722,8 +790,8 @@
 		{ BuiltinState = not_builtin }
 	->
 		code_info__succip_is_used,
-		call_gen__generate_semidet_call(PredId, ProcId, Args, GoalInfo,
-			Code)
+		call_gen__generate_call(model_semi, PredId, ProcId, Args,
+			GoalInfo, Code)
 	;
 		call_gen__generate_semidet_builtin(PredId, ProcId, Args, Code)
 	).
@@ -926,8 +994,8 @@
 		{ BuiltinState = not_builtin }
 	->
 		code_info__succip_is_used,
-		call_gen__generate_nondet_call(PredId, ProcId, Args, GoalInfo,
-			Code)
+		call_gen__generate_call(model_non, PredId, ProcId, Args,
+			GoalInfo, Code)
 	;
 		call_gen__generate_nondet_builtin(PredId, ProcId, Args, Code)
 	).
Index: compiler/code_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_info.m,v
retrieving revision 1.212
diff -u -r1.212 code_info.m
--- code_info.m	1997/09/14 03:54:36	1.212
+++ code_info.m	1997/09/30 22:29:58
@@ -33,7 +33,7 @@
 
 :- interface.
 
-:- import_module hlds_pred, hlds_goal, llds, instmap.
+:- import_module hlds_pred, hlds_goal, llds, instmap, trace.
 :- import_module globals.
 :- import_module bool, set, std_util, assoc_list.
 
@@ -67,8 +67,8 @@
 :- pred code_info__init(varset, set(var), stack_slots, bool, globals,
 	pred_id, proc_id, proc_info, instmap, follow_vars, module_info,
 	int /* cell number */, continuation_info, code_info).
-:- mode code_info__init(in, in, in, in, in, in, in, in, in, in, in, in, in, out)
-	is det.
+:- mode code_info__init(in, in, in, in, in, in, in, in, in, in, in, in, in,
+	out) is det.
 
 		% Get the variables for the current procedure.
 :- pred code_info__get_varset(varset, code_info, code_info).
@@ -124,6 +124,14 @@
 		code_info, code_info).
 :- mode code_info__set_continuation_info(in, in, out) is det.
 
+:- pred code_info__get_maybe_trace_info(maybe(trace_info),
+		code_info, code_info).
+:- mode code_info__get_maybe_trace_info(out, in, out) is det.
+
+:- pred code_info__set_maybe_trace_info(maybe(trace_info), 
+		code_info, code_info).
+:- mode code_info__set_maybe_trace_info(in, in, out) is det.
+
 %---------------------------------------------------------------------------%
 
 :- implementation.
@@ -167,11 +175,11 @@
 :- pred code_info__set_max_temp_slot_count(int, code_info, code_info).
 :- mode code_info__set_max_temp_slot_count(in, in, out) is det.
 
-:- pred code_info__get_temps_in_use(map(lval, lval_or_ticket),
+:- pred code_info__get_temps_in_use(map(lval, slot_contents),
 	code_info, code_info).
 :- mode code_info__get_temps_in_use(out, in, out) is det.
 
-:- pred code_info__set_temps_in_use(map(lval, lval_or_ticket),
+:- pred code_info__set_temps_in_use(map(lval, slot_contents),
 	code_info, code_info).
 :- mode code_info__set_temps_in_use(in, in, out) is det.
 
@@ -227,7 +235,7 @@
 					% temporary stackslots that have been
 					% used during the procedure
 			globals,	% code generation options
-			map(lval, lval_or_ticket),
+			map(lval, slot_contents),
 					% The temp locations in use on the stack
 					% and what they contain (for gc).
 			continuation_info,	
@@ -249,7 +257,7 @@
 					% When a variable included in the top
 					% set becomes no longer forward live,
 					% we must save its value to the stack.
-			int
+			int,
 					% A count of how many triples of
 					% curfr, maxfr and redoip are live on
 					% the det stack. These triples are
@@ -260,11 +268,17 @@
 					% garbage collector need to know about
 					% these slots.  (Triple is a misnomer:
 					% in grades with trailing, it is four.)
+			maybe(trace_info)
+					% Information about which stack slots
+					% the call sequence number and depth
+					% are stored, provided tracing is
+					% switched on.
 	).
 
-:- type lval_or_ticket 
+:- type slot_contents 
 	--->	ticket			% a ticket (trail pointer)
 	;	ticket_counter		% a copy of the ticket counter
+	;	trace_data
 	;	lval(lval).
 
 %---------------------------------------------------------------------------%
@@ -314,7 +328,8 @@
 		Shapes,
 		Zombies0,
 		ResumeSetStack0,
-		0
+		0,
+		no
 	).
 
 	% XXX This should be in arg_info.m.
@@ -339,87 +354,91 @@
 
 code_info__get_var_slot_count(A, CI, CI) :-
 	CI = code_info(A, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_label_count(B, CI, CI) :-
 	CI = code_info(_, B, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_varset(C, CI, CI) :-
 	CI = code_info(_, _, C, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_pred_id(D, CI, CI) :-
 	CI = code_info(_, _, _, D, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_proc_id(E, CI, CI) :-
 	CI = code_info(_, _, _, _, E, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_cell_count(F, CI, CI) :-
 	CI = code_info(_, _, _, _, _, F, _, _, _, _, _, _, _, _, _, _, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_exprn_info(G, CI, CI) :-
 	CI = code_info(_, _, _, _, _, _, G, _, _, _, _, _, _, _, _, _, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_proc_info(H, CI, CI) :-
 	CI = code_info(_, _, _, _, _, _, _, H, _, _, _, _, _, _, _, _, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_succip_used(I, CI, CI) :-
 	CI = code_info(_, _, _, _, _, _, _, _, I, _, _, _, _, _, _, _, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_fail_stack(J, CI, CI) :-
 	CI = code_info(_, _, _, _, _, _, _, _, _, J, _, _, _, _, _, _, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_module_info(K, CI, CI) :-
 	CI = code_info(_, _, _, _, _, _, _, _, _, _, K, _, _, _, _, _, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_forward_live_vars(L, CI, CI) :-
 	CI = code_info(_, _, _, _, _, _, _, _, _, _, _, L, _, _, _, _, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_instmap(M, CI, CI) :-
 	CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, M, _, _, _, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_avail_temp_slots(N, CI, CI) :-
 	CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, N, _, _, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_max_temp_slot_count(O, CI, CI) :-
 	CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, O, _, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_globals(P, CI, CI) :-
 	CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, P, _, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_temps_in_use(Q, CI, CI) :-
 	CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, Q, _, _,
-		_, _).
+		_, _, _).
 
 code_info__get_continuation_info(R, CI, CI) :-
 	CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, R, _,
-		_, _).
+		_, _, _).
 
 code_info__get_zombies(S, CI, CI) :-
 	CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, S,
-		_, _).
+		_, _, _).
 
 code_info__get_resume_point_stack(T, CI, CI) :-
 	CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-		T, _).
+		T, _, _).
 
 code_info__get_commit_triple_count(U, CI, CI) :-
 	CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
-		_, U).
+		_, U, _).
+
+code_info__get_maybe_trace_info(V, CI, CI) :-
+	CI = code_info(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+		_, _, V).
 
 % :- type code_info	--->
 %		code_info(
@@ -451,7 +470,7 @@
 %					% temporary stackslots that have been
 %					% used during the procedure
 %	P		globals,	% code generation options
-%	Q		map(lval, lval_or_ticket),
+%	Q		map(lval, slot_contents),
 %					% The temp locations in use on the stack
 %					% and what they contain (for gc).
 %	R		continuation_info,	
@@ -484,6 +503,11 @@
 %					% garbage collector need to know about
 %					% these slots.  (Triple is a misnomer:
 %					% in grades with trailing, it is four.)
+%	V		maybe(trace_info)
+%					% Information about which stack slots
+%					% the call sequence number and depth
+%					% are stored, provided tracing is
+%					% switched on.
 %	).
 %
 % we don't need
@@ -493,90 +517,97 @@
 % code_info__set_proc_id
 % code_info__set_module_info
 % code_info__set_globals
+% code_info__set_code_model
 
 code_info__set_label_count(B, CI0, CI) :-
 	CI0 = code_info(A, _, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U),
+		R, S, T, U, V),
 	CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U).
+		R, S, T, U, V).
 
 code_info__set_cell_count(F, CI0, CI) :-
 	CI0 = code_info(A, B, C, D, E, _, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U),
+		R, S, T, U, V),
 	CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U).
+		R, S, T, U, V).
 
 code_info__set_exprn_info(G, CI0, CI) :-
 	CI0 = code_info(A, B, C, D, E, F, _, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U),
+		R, S, T, U, V),
 	CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U).
+		R, S, T, U, V).
 
 code_info__set_succip_used(I, CI0, CI) :-
 	CI0 = code_info(A, B, C, D, E, F, G, H, _, J, K, L, M, N, O, P, Q,
-		R, S, T, U),
+		R, S, T, U, V),
 	CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U).
+		R, S, T, U, V).
 
 code_info__set_fail_stack(J, CI0, CI) :-
 	CI0 = code_info(A, B, C, D, E, F, G, H, I, _, K, L, M, N, O, P, Q,
-		R, S, T, U),
+		R, S, T, U, V),
 	CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U).
+		R, S, T, U, V).
 
 code_info__set_forward_live_vars(L, CI0, CI) :-
 	CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, _, M, N, O, P, Q,
-		R, S, T, U),
+		R, S, T, U, V),
 	CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U).
+		R, S, T, U, V).
 
 code_info__set_instmap(M, CI0, CI) :-
 	CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, _, N, O, P, Q,
-		R, S, T, U),
+		R, S, T, U, V),
 	CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U).
+		R, S, T, U, V).
 
 code_info__set_avail_temp_slots(N, CI0, CI) :-
 	CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, _, O, P, Q,
-		R, S, T, U),
+		R, S, T, U, V),
 	CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U).
+		R, S, T, U, V).
 
 code_info__set_max_temp_slot_count(O, CI0, CI) :-
 	CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, _, P, Q,
-		R, S, T, U),
+		R, S, T, U, V),
 	CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U).
+		R, S, T, U, V).
 
 code_info__set_temps_in_use(Q, CI0, CI) :-
 	CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, _,
-		R, S, T, U),
+		R, S, T, U, V),
 	CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U).
+		R, S, T, U, V).
 
 code_info__set_continuation_info(R, CI0, CI) :-
 	CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		_, S, T, U),
+		_, S, T, U, V),
 	CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U).
+		R, S, T, U, V).
 
 code_info__set_zombies(S, CI0, CI) :-
 	CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, _, T, U),
+		R, _, T, U, V),
 	CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U).
+		R, S, T, U, V).
 
 code_info__set_resume_point_stack(T, CI0, CI) :-
 	CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, _, U),
+		R, S, _, U, V),
 	CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U).
+		R, S, T, U, V).
 
 code_info__set_commit_triple_count(U, CI0, CI) :-
 	CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, _),
+		R, S, T, _, V),
 	CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
-		R, S, T, U).
+		R, S, T, U, V).
+
+code_info__set_maybe_trace_info(V, CI0, CI) :-
+	CI0 = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
+		R, S, T, U, _),
+	CI = code_info(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
+		R, S, T, U, V).
 
 %---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
@@ -631,6 +662,10 @@
 :- pred code_info__cons_id_to_tag(var, cons_id, cons_tag, code_info, code_info).
 :- mode code_info__cons_id_to_tag(in, in, out, in, out) is det.
 
+	% Get the code model of the current procedure.
+:- pred code_info__get_proc_model(code_model, code_info, code_info).
+:- mode code_info__get_proc_model(out, in, out) is det.
+
 :- pred code_info__get_headvars(list(var), code_info, code_info).
 :- mode code_info__get_headvars(out, in, out) is det.
 
@@ -698,9 +733,6 @@
 
 :- implementation.
 
-:- pred code_info__get_proc_model(code_model, code_info, code_info).
-:- mode code_info__get_proc_model(out, in, out) is det.
-
 :- pred code_info__push_failure_cont(failure_cont, code_info, code_info).
 :- mode code_info__push_failure_cont(in, in, out) is det.
 
@@ -2794,7 +2826,7 @@
 	{ set__insert(Vals0, Slot, Vals1) },
 	code_info__generate_var_livevals(Vs, Vals1, Vals).
 
-:- pred code_info__generate_temp_livevals(assoc_list(lval, lval_or_ticket),
+:- pred code_info__generate_temp_livevals(assoc_list(lval, slot_contents),
 	set(lval), set(lval)).
 :- mode code_info__generate_temp_livevals(in, in, out) is det.
 
@@ -2853,7 +2885,7 @@
 	{ set__insert(Vals0, Slot - V, Vals1) },
 	code_info__generate_var_livelvals(Vs, Vals1, Vals).
 
-:- pred code_info__generate_temp_livelvals(assoc_list(lval, lval_or_ticket),
+:- pred code_info__generate_temp_livelvals(assoc_list(lval, slot_contents),
 	list(liveinfo), list(liveinfo)).
 :- mode code_info__generate_temp_livelvals(in, in, out) is det.
 
@@ -2914,7 +2946,7 @@
 	code_info__livevals_to_livelvals(Ls, GC_Method, AfterCallInstMap, 
 		Lives).
 
-:- pred code_info__get_live_value_type(lval_or_ticket, live_value_type).
+:- pred code_info__get_live_value_type(slot_contents, live_value_type).
 :- mode code_info__get_live_value_type(in, out) is det.
 
 code_info__get_live_value_type(lval(succip), succip).
@@ -2937,6 +2969,7 @@
 					% modify this, if the GC is going
 					% to garbage-collect the trail.
 code_info__get_live_value_type(ticket_counter, unwanted).
+code_info__get_live_value_type(trace_data, unwanted).
 
 %---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
@@ -2978,12 +3011,15 @@
 :- pred code_info__get_total_stackslot_count(int, code_info, code_info).
 :- mode code_info__get_total_stackslot_count(out, in, out) is det.
 
+:- pred code_info__get_trace_slot(lval, code_info, code_info).
+:- mode code_info__get_trace_slot(out, in, out) is det.
+
 %---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
 
 :- implementation.
 
-:- pred code_info__acquire_temp_slot(lval_or_ticket, lval,
+:- pred code_info__acquire_temp_slot(slot_contents, lval,
 	code_info, code_info).
 :- mode code_info__acquire_temp_slot(in, out, in, out) is det.
 
@@ -2998,6 +3034,9 @@
 
 :- pred code_info__stack_variable(int, lval, code_info, code_info).
 :- mode code_info__stack_variable(in, out, in, out) is det.
+
+code_info__get_trace_slot(StackVar) -->
+	code_info__acquire_temp_slot(trace_data, StackVar).
 
 code_info__acquire_temp_slot(Item, StackVar) -->
 	code_info__get_avail_temp_slots(AvailSlots0),
Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.29
diff -u -r1.29 handle_options.m
--- handle_options.m	1997/09/02 07:03:39	1.29
+++ handle_options.m	1997/09/29 05:31:11
@@ -253,6 +253,22 @@
 		[]
 	),
 
+	% --generate-trace requires disabling optimizations
+	% that would change the trace being generated
+	globals__io_lookup_bool_option(generate_trace, Trace),
+	( { Trace = yes } ->
+		globals__io_set_option(inline_simple, bool(no)),
+		globals__io_set_option(inline_single_use, bool(no)),
+		globals__io_set_option(inline_compound_threshold, int(0)),
+		globals__io_set_option(optimize_unused_args, bool(no)),
+		globals__io_set_option(optimize_higher_order, bool(no)),
+		globals__io_set_option(optimize_duplicate_calls, bool(no)),
+		globals__io_set_option(optimize_constructor_last_call,
+			bool(no))
+	;
+		[]
+	),
+
 	% --dump-hlds and --statistics require compilation by phases
 	globals__io_lookup_accumulating_option(dump_hlds, DumpStages),
 	globals__io_lookup_bool_option(statistics, Statistics),
@@ -261,6 +277,7 @@
 	;
 		[]
 	),
+
 	% --intermod-unused-args implies --intermodule-optimization and
 	% --optimize-unused-args.
 	globals__io_lookup_bool_option(intermod_unused_args, Intermod),
@@ -270,6 +287,7 @@
 	;
 		[]
 	),
+
 	% Don't do the unused_args optimization when making the
 	% optimization interface.
 	globals__io_lookup_bool_option(make_optimization_interface, MakeOpt),
@@ -278,6 +296,7 @@
 	;
 		[]
 	),
+
 	% If --use-search-directories-for-intermod is true, append the
 	% search directories to the list of directories to search for
 	% .opt files.
@@ -294,7 +313,7 @@
 	;
 		[]
 	),
-	
+
 	% --optimize-frames requires --optimize-labels and --optimize-jumps
 	globals__io_lookup_bool_option(optimize_frames, OptFrames),
 	( { OptFrames = yes } ->
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.54
diff -u -r1.54 mercury_compile.m
--- mercury_compile.m	1997/09/25 03:34:51	1.54
+++ mercury_compile.m	1997/09/26 06:42:29
@@ -1449,7 +1449,15 @@
 	),
 	{ export__get_pragma_exported_procs(HLDS, PragmaExports) },
 	maybe_add_header_file_include(PragmaExports, Name, C_HeaderCode0,
-		C_HeaderCode),
+		C_HeaderCode1),
+	globals__io_lookup_bool_option(generate_trace, Trace),
+	( { Trace = yes } ->
+		{ term__context_init(Context) },
+		{ TraceInclude = "#include ""mercury_trace.h""\n" - Context },
+		{ list__append(C_HeaderCode1, [TraceInclude], C_HeaderCode) }
+	;
+		{ C_HeaderCode = C_HeaderCode1 }
+	),
 	{ list__condense([C_BodyCode, BaseTypeData, CommonDataModules,
 		ProcModules, [c_export(PragmaExports)]], ModuleList) },
 	{ list__length(ModuleList, NumChunks) }.
Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.203
diff -u -r1.203 options.m
--- options.m	1997/08/25 02:24:46	1.203
+++ options.m	1997/09/24 22:13:58
@@ -69,6 +69,7 @@
 		;	compile_only
 	% Auxiliary output options
 		;	assume_gmake
+		;	generate_trace
 		;	generate_bytecode
 		;	generate_prolog
 		;	prolog_dialect
@@ -290,6 +291,7 @@
 option_defaults_2(aux_output_option, [
 		% Auxiliary Output Options
 	assume_gmake		-	bool(yes),
+	generate_trace		-	bool(no),
 	generate_bytecode	-	bool(no),
 	generate_prolog		-	bool(no),
 	prolog_dialect		-	string("default"),
@@ -565,6 +567,7 @@
 
 % aux output options
 long_option("assume-gmake",		assume_gmake).
+long_option("generate-trace",		generate_trace).
 long_option("generate-bytecode",	generate_bytecode).
 long_option("generate-prolog",		generate_prolog).
 long_option("generate-Prolog",		generate_prolog).
@@ -1108,6 +1111,9 @@
 	io__write_string("\t\tWhen generating `.dep' files, generate Makefile\n"),
 	io__write_string("\t\tfragments that use only the features of standard make;\n"),
 	io__write_string("\t\tdo not assume the availability of GNU Make extensions.\n"),
+	io__write_string("\t--generate-trace\n"),
+	io__write_string("\t\tInclude code to generate an execution trace in the\n"),
+	io__write_string("\t\tC code output by the compiler.\n"),
 	io__write_string("\t--generate-bytecode\n"),
 	io__write_string("\t\tOutput a bytecode form of the module for use\n"),
 	io__write_string("\t\tby an experimental debugger.\n"),
cvs diff: compiler/trace.m is a new entry, no comparison available
cvs diff: Diffing compiler/notes
cvs diff: Diffing doc
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.97
diff -u -r1.97 user_guide.texi
--- user_guide.texi	1997/09/23 14:00:16	1.97
+++ user_guide.texi	1997/09/24 22:13:48
@@ -1355,6 +1355,10 @@
 do not assume the availability of GNU Make extensions.
 This makes these files significantly larger.
 
+ at item --generate-trace
+Include code to generate an execution trace in the
+C code output by the compiler.
+
 @item --generate-bytecode
 @c Output a bytecode version of the module
 @c into the @file{@var{module}.bytecode} file,
cvs diff: Diffing extras
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/Togl-1.2
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing library
cvs diff: Diffing lp_solve
cvs diff: Diffing lp_solve/lp_examples
cvs diff: Diffing profiler
cvs diff: Diffing runtime
Index: runtime/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/Mmakefile,v
retrieving revision 1.13
diff -u -r1.13 Mmakefile
--- Mmakefile	1997/09/29 18:13:36	1.13
+++ Mmakefile	1997/10/01 04:58:33
@@ -25,8 +25,8 @@
 HDRS		= calls.h conf.h context.h \
 		  deep_copy.h dlist.h debug.h dummy.h \
 		  engine.h getopt.h goto.h heap.h imp.h init.h label.h \
-		  memory.h mercury_float.h mercury_string.h mercury_trail.h \
-		  mercury_types.h misc.h \
+		  memory.h mercury_float.h mercury_string.h mercury_trace.h \
+		  mercury_trail.h mercury_types.h misc.h \
 		  overflow.h prof.h prof_mem.h regorder.h regs.h \
 		  spinlock.h std.h stacks.h \
 		  table.h tags.h timing.h type_info.h wrapper.h \
@@ -45,7 +45,7 @@
 MOD_OS		= $(MOD_CS:.c=.o)
 ORIG_CS		= deep_copy.c dlist.c dummy.c label.c \
 		  memory.c misc.c regs.c table.c timing.c prof.c prof_mem.c \
-		  spinlock.c mercury_float.c mercury_trail.c
+		  spinlock.c mercury_float.c mercury_trace.c mercury_trail.c
 ORIG_OS		= $(ORIG_CS:.c=.o)
 OBJS		= $(MOD_OS) $(ORIG_OS)
 # OBJS		= engine.o wrapper.o call.o \
cvs diff: runtime/mercury_trace.c is a new entry, no comparison available
cvs diff: runtime/mercury_trace.h is a new entry, no comparison available
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/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/general
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trial
cvs diff: Diffing util
%-----------------------------------------------------------------------------%
% Copyright (C) 1997 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%

% This module handles the generation of traces for the trace analysis system.
%
% We reserve two slots in the stack frame of the traced procedure.
% One contains the call sequence number, which is set in the procedure prolog
% by incrementing a global counter. The other contains the call depth, which
% is also set by incrementing a global variable containing the depth of the
% caller. The caller sets this global variable from its own saved depth
% just before the call.

% Author: zs.

%-----------------------------------------------------------------------------%

:- module trace.

:- interface.

:- import_module llds, code_info.

:- type trace_port	--->	call
			;	exit
			;	fail.

:- type trace_info.

:- pred trace__setup(code_info::in, code_info::out) is det.

:- pred trace__generate_slot_fill_code(trace_info::in, code_tree::out) is det.

:- pred trace__generate_depth_reset_code(trace_info::in, code_tree::out) is det.

:- pred trace__generate_event_code(trace_port::in, trace_info::in,
	code_tree::out, code_info::in, code_info::out) is det.

%-----------------------------------------------------------------------------%

:- implementation.

:- import_module hlds_module, hlds_pred, tree.
:- import_module int, list, std_util, string, require.

:- type trace_info
	--->	trace_info(
			lval,	% stack slot of call sequence number
			lval	% stack slot of call depth
		).

trace__setup -->
	code_info__get_trace_slot(CallNumSlot),
	code_info__get_trace_slot(CallDepthSlot),
	{ TraceInfo = trace_info(CallNumSlot, CallDepthSlot) },
	code_info__set_maybe_trace_info(yes(TraceInfo)).

trace__generate_slot_fill_code(TraceInfo, TraceCode) :-
	TraceInfo = trace_info(CallNumLval, CallDepthLval),
	trace__stackref_to_string(CallNumLval, CallNumStr),
	trace__stackref_to_string(CallDepthLval, CallDepthStr),
	string__append(CallNumStr, " = MR_trace_incr_seq();\n",
		CallNumStmt),
	string__append(CallDepthStr, " = MR_trace_incr_depth();\n",
		CallDepthStmt),
	TraceCode = node([
		c_code(CallNumStmt) - "",
		c_code(CallDepthStmt) - ""
	]).

trace__generate_depth_reset_code(TraceInfo, TraceCode) :-
	TraceInfo = trace_info(_CallNumLval, CallDepthLval),
	trace__stackref_to_string(CallDepthLval, CallDepthStr),
	string__append_list(["MR_trace_reset_depth(", CallDepthStr, ");\n"],
		Stmt),
	TraceCode = node([
		c_code(Stmt) - ""
	]).

trace__generate_event_code(Port, TraceInfo, TraceCode) -->
	code_info__get_pred_id(PredId),
	code_info__get_proc_id(ProcId),
	code_info__get_module_info(ModuleInfo),
	code_info__get_proc_model(CodeModel),
	{
	TraceInfo = trace_info(CallNumLval, CallDepthLval),
	trace__stackref_to_string(CallNumLval, CallNumStr),
	trace__stackref_to_string(CallDepthLval, CallDepthStr),
	predicate_module(ModuleInfo, PredId, ModuleName),
	predicate_name(ModuleInfo, PredId, PredName),
	predicate_arity(ModuleInfo, PredId, Arity),
	string__int_to_string(Arity, ArityStr),
	Quote = """",
	trace__port_to_string(Port, PortStr),
	trace__code_model_to_string(CodeModel, CodeModelStr),
	proc_id_to_int(ProcId, ProcInt),
	ModeNum is ProcInt mod 10000,
	string__int_to_string(ModeNum, ModeNumStr),
	string__append_list([
		"MR_trace(",
		PortStr, ", ",
		CodeModelStr, ", ",
		CallNumStr, ", ",
		CallDepthStr, ", ",
		Quote, ModuleName, Quote, ", ",
		Quote, PredName, Quote, ", ",
		ArityStr, ", ",
		ModeNumStr, ");\n"],
		TraceStmt),
	TraceCode = node([c_code(TraceStmt) - ""])
	}.

:- pred trace__port_to_string(trace_port::in, string::out) is det.

trace__port_to_string(call, "MR_PORT_CALL").
trace__port_to_string(exit, "MR_PORT_EXIT").
trace__port_to_string(fail, "MR_PORT_FAIL").

:- pred trace__code_model_to_string(code_model, string).
:- mode trace__code_model_to_string(in, out) is det.

trace__code_model_to_string(model_det,  "MR_MODEL_DET").
trace__code_model_to_string(model_semi, "MR_MODEL_SEMI").
trace__code_model_to_string(model_non,  "MR_MODEL_NON").

:- pred trace__stackref_to_string(lval, string).
:- mode trace__stackref_to_string(in, out) is det.

trace__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")
	).
/*
** Copyright (C) 1997 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/

/*
** mercury_trace.c - implements the tracing subsystem.
*/

#include "imp.h"
#include "mercury_trace.h"
#include <stdio.h>

int	MR_trace_call_seqno = 0;
int	MR_trace_call_depth = 0;

void	MR_trace(MR_trace_port port, MR_trace_code_model model,
	int seqno, int depth, const char *modulename, const char *predname,
	int arity,
	int modenum)
{
	int	i;

	fprintf(stderr, "%4d %2d ", seqno, depth);

	for (i = 0; i < depth; i++)
		putc(' ', stderr);

	switch (port)
	{
case MR_PORT_CALL:	fprintf(stderr, "CALL ");
			break;

case MR_PORT_EXIT:	fprintf(stderr, "EXIT ");
			break;

case MR_PORT_FAIL:	fprintf(stderr, "FAIL ");
			break;
	}

	switch (model)
	{
case MR_MODEL_DET:	fprintf(stderr, "DET  ");
			break;

case MR_MODEL_SEMI:	fprintf(stderr, "SEMI ");
			break;

case MR_MODEL_NON:	fprintf(stderr, "NON  ");
			break;
	}

	fprintf(stderr, "%s:%s/%d-%d\n", modulename, predname, arity, modenum);
}
/*
** Copyright (C) 1997 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/

/*
** mercury_trace.h - defines the interface between
** the tracing subsystem and compiled code.
**
** The macros and the function defined in this module are intended to be
** called only from code generated by the Mercury compiler, and from
** hand-compiled code in the Mercury runtime or the Mercury standard library.
*/

#ifndef MERCURY_TRACE_H
#define MERCURY_TRACE_H

#define	MR_trace_incr_seq()	++MR_trace_call_seqno
#define	MR_trace_incr_depth()	++MR_trace_call_depth
#define	MR_trace_reset_depth(d)	MR_trace_call_depth = d

extern	int	MR_trace_call_seqno;
extern	int	MR_trace_call_depth;

typedef	enum {
	MR_PORT_CALL, MR_PORT_EXIT, MR_PORT_FAIL
} MR_trace_port;

typedef	enum {
	MR_MODEL_DET, MR_MODEL_SEMI, MR_MODEL_NON
} MR_trace_code_model;

extern	void	MR_trace(
	MR_trace_port,
	MR_trace_code_model,
	int,			/* call sequence number */
	int,			/* call depth */
	const char *,		/* module name */
	const char *,		/* predicate name */
	int,			/* predicate arity */
	int);			/* mode number within predicate */

#endif



More information about the developers mailing list