[m-dev.] for review: reorganize hlds_goal.m

Fergus Henderson fjh at cs.mu.OZ.AU
Wed Nov 1 20:51:25 AEDT 2000


Zoltan, could you please review this one?

Estimated hours taken: 1

compiler/hlds_goal.m:
	Reorganize things to improve readability.  In particular,
	reorder the declarations so that they are grouped in coherent
	sections, with the stuff specific to particular back-ends
	(Aditi or LLDS) at the end, and add some comments documenting this.
	Use a single interface section rather than interleaving
	multiple interface and implementation sections.

Workspace: /home/pgrad/fjh/ws/hg
Index: compiler/hlds_goal.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_goal.m,v
retrieving revision 1.79
diff -u -d -r1.79 hlds_goal.m
--- compiler/hlds_goal.m	2000/10/30 07:08:58	1.79
+++ compiler/hlds_goal.m	2000/11/01 09:50:29
@@ -12,11 +12,16 @@
 
 :- interface.
 
-:- import_module hlds_data, hlds_pred, llds, prog_data, (inst), instmap.
+:- import_module hlds_data, hlds_pred, prog_data, (inst), instmap.
+:- import_module llds.	% XXX needed for `lval'
 :- import_module bool, char, list, set, map, std_util.
 
+%-----------------------------------------------------------------------------%
+
 	% Here is how goals are represented
 
+:- type hlds_goals	== list(hlds_goal).
+
 :- type hlds_goal	== pair(hlds_goal_expr, hlds_goal_info).
 
 :- type hlds_goal_expr
@@ -204,6 +209,11 @@
 
 	.
 
+%-----------------------------------------------------------------------------%
+%
+% Information for generic_calls
+%
+
 :- type generic_call
 	--->	higher_order(
 			prog_var,
@@ -225,113 +235,28 @@
 		)
 	.
 
-:- func generic_call_pred_or_func(generic_call) = pred_or_func.
-
-	% Builtin Aditi operations. 
-:- type aditi_builtin
-	--->
-		% Call an Aditi predicate from Mercury compiled to C.
-		% This is introduced by magic.m.
-		% Arguments: 
-		%   type-infos for the input arguments
-		%   the input arguments
-		%   type-infos for the output arguments
-		%   the output arguments
-		aditi_call(
-			pred_proc_id,	% procedure to call
-			int,		% number of inputs
-			list(type),	% types of input arguments
-			int		% number of outputs
-		)
-
-		% Insert or delete a single tuple into/from a base relation.
-		% Arguments:
-		%   type-infos for the arguments of the tuple to insert
-		%   the arguments of tuple to insert
-		% aditi__state::di, aditi__state::uo
-	;	aditi_tuple_insert_delete(
-			aditi_insert_delete,
-			pred_id		% base relation to insert into
-		)
-
-		% Insert/delete/modify operations which take
-		% an input closure.
-		% These operations all have two variants. 
-		%
-		% A pretty syntax:
-		%
-		% aditi_bulk_insert(p(DB, X, Y) :- q(DB, X, Y)).
-		% aditi_bulk_delete(p(DB, X, Y) :- q(DB, X, Y)).
-		% aditi_bulk_modify(
-		%	(p(DB, X0, Y0) ==> p(_, X, Y) :-
-		%		X = X0 + 1,
-		%		Y = Y0 + 3
-		%	)).
-		%
-		% An ugly syntax:
-		%
-		% InsertPred = (aditi_bottom_up
-		%	pred(DB::aditi_mui, X::out, Y::out) :- 
-		%		q(DB, X, Y)
-		% ),
-		% aditi_bulk_insert(pred p/3, InsertPred).
-		%
-		% DeletePred = (aditi_bottom_up
-		%	pred(DB::aditi_mui, X::out, Y::out) :- 
-		%		p(DB, X, Y),
-		%		q(DB, X, Y)
-		% ),
-		% aditi_bulk_delete(pred p/3, DeletePred).
-	;	aditi_insert_delete_modify(
-			aditi_insert_delete_modify,
-			pred_id,
-			aditi_builtin_syntax
-		)
-	.
-
-:- type aditi_insert_delete
-	--->	delete			% `aditi_delete'
-	;	insert			% `aditi_insert'
-	.
-
-:- type aditi_insert_delete_modify
-	--->	delete(bulk_or_filter)	% `aditi_bulk_delete' or `aditi_filter'
-	;	bulk_insert		% `aditi_bulk_insert'
-	;	modify(bulk_or_filter)	% `aditi_bulk_modify' or `aditi_modify'
-	.
+	% Get a description of a generic_call goal.
+:- pred hlds_goal__generic_call_id(generic_call, call_id).
+:- mode hlds_goal__generic_call_id(in, out) is det.
 
-	% Deletions and modifications can either be done by computing
-	% all tuples for which the update applies, then applying the
-	% update for all tuples in one go (`bulk'), or by applying
-	% the update to each tuple during a pass over the relation
-	% being modified (`filter').
-	%
-	% The `filter' updates are not yet implemented in Aditi, and
-	% it may be difficult to ever implement them.
-:- type bulk_or_filter
-	--->	bulk
-	;	filter
-	.
+	% Determine whether a generic_call is calling
+	% a predicate or a function
+:- func generic_call_pred_or_func(generic_call) = pred_or_func.
 
-	% Which syntax was used for an `aditi_delete' or `aditi_modify'
-	% call. The first syntax is prettier, the second is used
-	% where the closure to be passed in is not known at the call site.
-	% (See the "Aditi update syntax" section of the Mercury Language
-	% Reference Manual).
-:- type aditi_builtin_syntax
-	--->	pred_term		% e.g.
-					% aditi_bulk_insert(p(_, X) :- X = 1).
-	;	sym_name_and_closure	% e.g.
-					% aditi_insert(p/2,
-					%    (pred(_::in, X::out) is nondet:-
-					%	X = 1)
-					%    )
-	.
+%-----------------------------------------------------------------------------%
+%
+% Information for quantifications
+%
 
 :- type can_remove
 	--->	can_remove
 	;	cannot_remove.
 
+%-----------------------------------------------------------------------------%
+%
+% Information for calls
+%
+
 	% There may be two sorts of "builtin" predicates - those that we
 	% open-code using inline instructions (e.g. arithmetic predicates),
 	% and those which are still "internal", but for which we generate
@@ -343,40 +268,19 @@
 			;	out_of_line_builtin
 			;	not_builtin.
 
+%-----------------------------------------------------------------------------%
+%
+% Information for switches
+%
+
 :- type case		--->	case(cons_id, hlds_goal).
 			%	functor to match with,
 			%	goal to execute if match succeeds.
-
-:- type stack_slots	==	map(prog_var, lval).
-				% Maps variables to their stack slots.
-				% The only legal lvals in the range are
-				% stackvars and framevars.
 
-:- type follow_vars_map	==	map(prog_var, lval).
-
-:- type follow_vars	--->	follow_vars(follow_vars_map, int).
-				% Advisory information about where variables
-				% ought to be put next. Variables may or may
-				% not appear in the map. If they do, then the
-				% associated lval says where the value of that
-				% variable ought to be put when it is computed,
-				% or, if the lval refers to the nonexistent
-				% register r(-1), it says that it should be
-				% put into an available register. The integer
-				% in the second half of the pair gives the
-				% number of the first register that is
-				% not reserved for other purposes, and is
-				% free to hold such variables.
-
-:- type store_map	==	map(prog_var, lval).
-				% Authoritative information about where
-				% variables must be put at the ends of
-				% branches of branched control structures.
-				% However, between the follow_vars and
-				% and store_alloc passes, these fields
-				% temporarily hold follow_vars information.
-				% Apart from this, the legal range is
-				% the set of legal lvals.
+%-----------------------------------------------------------------------------%
+%
+% Information for unifications
+%
 
 	% Initially all unifications are represented as
 	% unify(prog_var, unify_rhs, _, _, _), but mode analysis replaces
@@ -403,22 +307,6 @@
 			hlds_goal
 		).
 
-	% For lambda expressions built automatically for Aditi updates
-	% the modes of `aditi__state' arguments may need to be fixed
-	% by purity.m because make_hlds.m does not know which relation
-	% is being updated, so it doesn't know which are the `aditi__state'
-	% arguments.
-:- type fix_aditi_state_modes
-	--->	modes_need_fixing
-	;	modes_are_ok
-	.
-
-	% `yes' iff the cell is available for compile time garbage collection.
-	% Compile time garbage collection is when the compiler
-	% recognises that a memory cell is no longer needed and can be
-	% safely deallocated (ie by inserting an explicit call to free).
-:- type can_cgc == bool.
-
 :- type unification
 		% A construction unification is a unification with a functor
 		% or lambda expression which binds the LHS variable,
@@ -540,6 +428,12 @@
 					% being a complicated unify.
 		).
 
+	% `yes' iff the cell is available for compile time garbage collection.
+	% Compile time garbage collection is when the compiler
+	% recognises that a memory cell is no longer needed and can be
+	% safely deallocated (ie by inserting an explicit call to free).
+:- type can_cgc == bool.
+
 	% A unify_context describes the location in the original source
 	% code of a unification, for use in error messages.
 
@@ -646,201 +540,6 @@
 	;	cell_is_shared
 	.
 
-:- type hlds_goals == list(hlds_goal).
-
-:- type hlds_goal_info.
-
-:- type goal_feature
-	--->	constraint	% This is included if the goal is
-				% a constraint.  See constraint.m
-				% for the definition of this.
-	;	(impure)	% This goal is impure.  See hlds_pred.m.
-	;	(semipure)	% This goal is semipure.  See hlds_pred.m.
-	;	call_table_gen.	% This goal generates the variable that
-				% represents the call table tip. If debugging
-				% is enabled, the code generator needs to save
-				% the value of this variable in its stack slot
-				% as soon as it is generated; this marker
-				% tells the code generator when this happens.
-
-	% see compiler/notes/allocation.html for what these alternatives mean
-:- type resume_point	--->	resume_point(set(prog_var), resume_locs)
-			;	no_resume_point.
-
-:- type resume_locs	--->	orig_only
-			;	stack_only
-			;	orig_and_stack
-			;	stack_and_orig.
-
-	% We can think of the goal that defines a procedure to be a tree,
-	% whose leaves are primitive goals and whose interior nodes are
-	% compound goals. These two types describe the position of a goal
-	% in this tree. A goal_path_step type says which branch to take at an
-	% interior node; the integer counts start at one. (For switches,
-	% the second int gives the total number of function symbols in the type
-	% of the switched-on var; for builtin types such as integer and string,
-	% for which this number is effectively infinite, we store a negative
-	% number.) The goal_path type gives the sequence of steps from the root
-	% to the given goal *in reverse order*, so that the step closest to
-	% the root is last. (Keeping the list in reverse order makes the
-	% common operations constant-time instead of linear in the length
-	% of the list.)
-
-:- type goal_path_step	--->	conj(int)
-			;	disj(int)
-			;	switch(int, int)
-			;	ite_cond
-			;	ite_then
-			;	ite_else
-			;	neg
-			;	exist(maybe_cut)
-			;	first
-			;	later.
-
-:- type maybe_cut	--->	cut ; no_cut.
-
-:- type goal_path == list(goal_path_step).
-
-	% Given the variable info field from a pragma foreign_code, get all the
-	% variable names.
-:- pred get_pragma_foreign_var_names(list(maybe(pair(string, mode))),
-		list(string)).
-:- mode get_pragma_foreign_var_names(in, out) is det.
-
-	% Get a description of a generic_call goal.
-:- pred hlds_goal__generic_call_id(generic_call, call_id).
-:- mode hlds_goal__generic_call_id(in, out) is det.
-
-%-----------------------------------------------------------------------------%
-
-:- implementation.
-
-	% NB. Don't forget to check goal_util__name_apart_goalinfo
-	% if this structure is modified.
-:- type hlds_goal_info
-	---> goal_info(
-		pre_births :: set(prog_var),	% the pre-birth set
-		post_births :: set(prog_var),	% the post-birth set
-		pre_deaths :: set(prog_var),	% the pre-death set
-		post_deaths :: set(prog_var),	% the post-death set
-				% (all four are computed by liveness.m)
-				% NB for atomic goals, the post-deadness
-				% should be applied _before_ the goal
-
-		determinism :: determinism, 
-				% the overall determinism of the goal
-				% (computed during determinism analysis)
-				% [because true determinism is undecidable,
-				% this may be a conservative approximation]
-
-		instmap_delta :: instmap_delta,
-				% the change in insts over this goal
-				% (computed during mode analysis)
-				% [because true unreachability is undecidable,
-				% the instmap_delta may be reachable even
-				% when the goal really never succeeds]
-				%
-				% The following invariant is required
-				% by the code generator and is enforced
-				% by the final simplification pass:
-				% the determinism specifies at_most_zero solns
-				% iff the instmap_delta is unreachable.
-				%
-				% Before the final simplification pass,
-				% the determinism and instmap_delta
-				% might not be consistent with regard to
-				% unreachability, but both will be
-				% conservative approximations, so if either
-				% says a goal is unreachable then it is.
-				%
-				% Normally the instmap_delta will list only
-				% the nonlocal variables of the goal.
-
-		context :: prog_context,
-
-		nonlocals :: set(prog_var),
-				% the non-local vars in the goal,
-				% i.e. the variables that occur both inside
-				% and outside of the goal.
-				% (computed by quantification.m)
-				% [in some circumstances, this may be a
-				% conservative approximation: it may be
-				% a superset of the real non-locals]
-
-		/*
-		code_gen_nonlocals :: maybe(set(prog_var)),
-				% the non-local vars in the goal,
-				% modified slightly for code generation.
-				% The difference between the code-gen nonlocals
-				% and the ordinary nonlocals is that arguments
-				% of a reconstruction which are taken from the
-				% reused cell are not considered to be
-				% `code_gen_nonlocals' of the goal.
-				% This avoids allocating stack slots and
-				% generating unnecessary field extraction
-				% instructions for those arguments.
-				% Mode information is still computed using
-				% the ordinary non-locals.
-				% 
-				% If the field has value `no', the ordinary
-				% nonlocals are used instead. This will
-				% be the case if the procedure body does not
-				% contain any reconstructions.
-		*/
-
-		follow_vars :: maybe(follow_vars),
-				% advisory information about where variables
-				% ought to be put next. The legal range
-				% includes the nonexistent register r(-1),
-				% which indicates any available register.
-
-		features :: set(goal_feature),
-				% The set of used-defined "features" of
-				% this goal, which optimisers may wish
-				% to know about.
-
-		resume_point :: resume_point,
-				% If this goal establishes a resumption point,
-				% state what variables need to be saved for
-				% that resumption point, and which entry
-				% labels of the resumption point will be
-				% needed. (See compiler/notes/allocation.html)
-
-		goal_path :: goal_path
-				% The path to this goal from the root in
-				% reverse order.
-	).
-
-get_pragma_foreign_var_names(MaybeVarNames, VarNames) :-
-	get_pragma_foreign_var_names_2(MaybeVarNames, [], VarNames0),
-	list__reverse(VarNames0, VarNames).
-
-:- pred get_pragma_foreign_var_names_2(list(maybe(pair(string, mode)))::in,
-	list(string)::in, list(string)::out) is det.
-
-get_pragma_foreign_var_names_2([], Names, Names).
-get_pragma_foreign_var_names_2([MaybeName | MaybeNames], Names0, Names) :-
-	(
-		MaybeName = yes(Name - _),
-		Names1 = [Name | Names0]
-	;
-		MaybeName = no,
-		Names1 = Names0
-	),
-	get_pragma_foreign_var_names_2(MaybeNames, Names1, Names).
-
-hlds_goal__generic_call_id(higher_order(_, PorF, Arity),
-		generic_call(higher_order(PorF, Arity))).
-hlds_goal__generic_call_id(
-		class_method(_, _, ClassId, MethodId),
-		generic_call(class_method(ClassId, MethodId))).
-hlds_goal__generic_call_id(aditi_builtin(Builtin, Name),
-		generic_call(aditi_builtin(Builtin, Name))).
-
-%-----------------------------------------------------------------------------%
-
-:- interface.
-
 :- type unify_mode	==	pair(mode, mode).
 
 :- type uni_mode	--->	pair(inst) -> pair(inst).
@@ -850,10 +549,17 @@
 					% of the LHS and the RHS respectively
 
 %-----------------------------------------------------------------------------%
+%
+% Information for all kinds of goals
+%
 
-	% Access predicates for the hlds_goal_info data structure.
+%
+% Access predicates for the hlds_goal_info data structure.
+% For documentation on the meaning of the fields that these
+% procedures access, see the definition of the hlds_goal_info type.
+%
 
-:- interface.
+:- type hlds_goal_info.
 
 :- pred goal_info_init(hlds_goal_info).
 :- mode goal_info_init(out) is det.
@@ -861,7 +567,6 @@
 :- pred goal_info_init(prog_context, hlds_goal_info).
 :- mode goal_info_init(in, out) is det.
 
-
 :- pred goal_info_init(set(prog_var), instmap_delta, determinism,
 		hlds_goal_info).
 :- mode goal_info_init(in, in, in, out) is det.
@@ -983,6 +688,55 @@
 :- pred goal_info_resume_vars_and_loc(resume_point, set(prog_var), resume_locs).
 :- mode goal_info_resume_vars_and_loc(in, out, out) is det.
 
+
+:- type goal_feature
+	--->	constraint	% This is included if the goal is
+				% a constraint.  See constraint.m
+				% for the definition of this.
+	;	(impure)	% This goal is impure.  See hlds_pred.m.
+	;	(semipure)	% This goal is semipure.  See hlds_pred.m.
+	;	call_table_gen.	% This goal generates the variable that
+				% represents the call table tip. If debugging
+				% is enabled, the code generator needs to save
+				% the value of this variable in its stack slot
+				% as soon as it is generated; this marker
+				% tells the code generator when this happens.
+
+
+	% We can think of the goal that defines a procedure to be a tree,
+	% whose leaves are primitive goals and whose interior nodes are
+	% compound goals. These two types describe the position of a goal
+	% in this tree. A goal_path_step type says which branch to take at an
+	% interior node; the integer counts start at one. (For switches,
+	% the second int gives the total number of function symbols in the type
+	% of the switched-on var; for builtin types such as integer and string,
+	% for which this number is effectively infinite, we store a negative
+	% number.) The goal_path type gives the sequence of steps from the root
+	% to the given goal *in reverse order*, so that the step closest to
+	% the root is last. (Keeping the list in reverse order makes the
+	% common operations constant-time instead of linear in the length
+	% of the list.)
+
+:- type goal_path == list(goal_path_step).
+
+:- type goal_path_step	--->	conj(int)
+			;	disj(int)
+			;	switch(int, int)
+			;	ite_cond
+			;	ite_then
+			;	ite_else
+			;	neg
+			;	exist(maybe_cut)
+			;	first
+			;	later.
+
+:- type maybe_cut	--->	cut ; no_cut.
+
+%-----------------------------------------------------------------------------%
+%
+% Miscellaneous utility procedures for dealing with HLDS goals
+%
+
 	% Convert a goal to a list of conjuncts.
 	% If the goal is a conjunction, then return its conjuncts,
 	% otherwise return the goal as a singleton list.
@@ -1087,6 +841,7 @@
 :- pred set_goal_contexts(prog_context, hlds_goal, hlds_goal).
 :- mode set_goal_contexts(in, in, out) is det.
 
+
 	% Create the hlds_goal for a unification, filling in all the as yet
 	% unknown slots with dummy values.
 :- pred create_atomic_unification(prog_var, unify_rhs, prog_context,
@@ -1161,13 +916,312 @@
 		proc_info, proc_info).
 :- mode make_const_construction(in, in, out, out, in, out) is det.
 
+
+	% Given the variable info field from a pragma foreign_code, get all the
+	% variable names.
+:- pred get_pragma_foreign_var_names(list(maybe(pair(string, mode))),
+		list(string)).
+:- mode get_pragma_foreign_var_names(in, out) is det.
+
+%-----------------------------------------------------------------------------%
+%
+% Stuff specific to Aditi.
+%
+
+	% Builtin Aditi operations. 
+:- type aditi_builtin
+	--->
+		% Call an Aditi predicate from Mercury compiled to C.
+		% This is introduced by magic.m.
+		% Arguments: 
+		%   type-infos for the input arguments
+		%   the input arguments
+		%   type-infos for the output arguments
+		%   the output arguments
+		aditi_call(
+			pred_proc_id,	% procedure to call
+			int,		% number of inputs
+			list(type),	% types of input arguments
+			int		% number of outputs
+		)
+
+		% Insert or delete a single tuple into/from a base relation.
+		% Arguments:
+		%   type-infos for the arguments of the tuple to insert
+		%   the arguments of tuple to insert
+		% aditi__state::di, aditi__state::uo
+	;	aditi_tuple_insert_delete(
+			aditi_insert_delete,
+			pred_id		% base relation to insert into
+		)
+
+		% Insert/delete/modify operations which take
+		% an input closure.
+		% These operations all have two variants. 
+		%
+		% A pretty syntax:
+		%
+		% aditi_bulk_insert(p(DB, X, Y) :- q(DB, X, Y)).
+		% aditi_bulk_delete(p(DB, X, Y) :- q(DB, X, Y)).
+		% aditi_bulk_modify(
+		%	(p(DB, X0, Y0) ==> p(_, X, Y) :-
+		%		X = X0 + 1,
+		%		Y = Y0 + 3
+		%	)).
+		%
+		% An ugly syntax:
+		%
+		% InsertPred = (aditi_bottom_up
+		%	pred(DB::aditi_mui, X::out, Y::out) :- 
+		%		q(DB, X, Y)
+		% ),
+		% aditi_bulk_insert(pred p/3, InsertPred).
+		%
+		% DeletePred = (aditi_bottom_up
+		%	pred(DB::aditi_mui, X::out, Y::out) :- 
+		%		p(DB, X, Y),
+		%		q(DB, X, Y)
+		% ),
+		% aditi_bulk_delete(pred p/3, DeletePred).
+	;	aditi_insert_delete_modify(
+			aditi_insert_delete_modify,
+			pred_id,
+			aditi_builtin_syntax
+		)
+	.
+
+:- type aditi_insert_delete
+	--->	delete			% `aditi_delete'
+	;	insert			% `aditi_insert'
+	.
+
+:- type aditi_insert_delete_modify
+	--->	delete(bulk_or_filter)	% `aditi_bulk_delete' or `aditi_filter'
+	;	bulk_insert		% `aditi_bulk_insert'
+	;	modify(bulk_or_filter)	% `aditi_bulk_modify' or `aditi_modify'
+	.
+
+	% Deletions and modifications can either be done by computing
+	% all tuples for which the update applies, then applying the
+	% update for all tuples in one go (`bulk'), or by applying
+	% the update to each tuple during a pass over the relation
+	% being modified (`filter').
+	%
+	% The `filter' updates are not yet implemented in Aditi, and
+	% it may be difficult to ever implement them.
+:- type bulk_or_filter
+	--->	bulk
+	;	filter
+	.
+
+	% Which syntax was used for an `aditi_delete' or `aditi_modify'
+	% call. The first syntax is prettier, the second is used
+	% where the closure to be passed in is not known at the call site.
+	% (See the "Aditi update syntax" section of the Mercury Language
+	% Reference Manual).
+:- type aditi_builtin_syntax
+	--->	pred_term		% e.g.
+					% aditi_bulk_insert(p(_, X) :- X = 1).
+	;	sym_name_and_closure	% e.g.
+					% aditi_insert(p/2,
+					%    (pred(_::in, X::out) is nondet:-
+					%	X = 1)
+					%    )
+	.
+
+
+	% For lambda expressions built automatically for Aditi updates
+	% the modes of `aditi__state' arguments may need to be fixed
+	% by purity.m because make_hlds.m does not know which relation
+	% is being updated, so it doesn't know which are the `aditi__state'
+	% arguments.
+:- type fix_aditi_state_modes
+	--->	modes_need_fixing
+	;	modes_are_ok
+	.
+
 %-----------------------------------------------------------------------------%
+%
+% Stuff specific to the LLDS back-end.
+%
+
+%
+% The following types are annotations on the HLDS
+% that are used only by the LLDS back-end.
+%
 
+:- type stack_slots	==	map(prog_var, lval).
+				% Maps variables to their stack slots.
+				% The only legal lvals in the range are
+				% stackvars and framevars.
+
+:- type follow_vars_map	==	map(prog_var, lval).
+
+:- type follow_vars	--->	follow_vars(follow_vars_map, int).
+				% Advisory information about where variables
+				% ought to be put next. Variables may or may
+				% not appear in the map. If they do, then the
+				% associated lval says where the value of that
+				% variable ought to be put when it is computed,
+				% or, if the lval refers to the nonexistent
+				% register r(-1), it says that it should be
+				% put into an available register. The integer
+				% in the second half of the pair gives the
+				% number of the first register that is
+				% not reserved for other purposes, and is
+				% free to hold such variables.
+
+:- type store_map	==	map(prog_var, lval).
+				% Authoritative information about where
+				% variables must be put at the ends of
+				% branches of branched control structures.
+				% However, between the follow_vars and
+				% and store_alloc passes, these fields
+				% temporarily hold follow_vars information.
+				% Apart from this, the legal range is
+				% the set of legal lvals.
+
+	% see compiler/notes/allocation.html for what these alternatives mean
+:- type resume_point	--->	resume_point(set(prog_var), resume_locs)
+			;	no_resume_point.
+
+:- type resume_locs	--->	orig_only
+			;	stack_only
+			;	orig_and_stack
+			;	stack_and_orig.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
 :- implementation.
 
 :- import_module det_analysis, prog_util, type_util.
 :- import_module require, string, term, varset.
 
+%-----------------------------------------------------------------------------%
+%
+% Predicates dealing with generic_calls
+%
+
+hlds_goal__generic_call_id(higher_order(_, PorF, Arity),
+		generic_call(higher_order(PorF, Arity))).
+hlds_goal__generic_call_id(
+		class_method(_, _, ClassId, MethodId),
+		generic_call(class_method(ClassId, MethodId))).
+hlds_goal__generic_call_id(aditi_builtin(Builtin, Name),
+		generic_call(aditi_builtin(Builtin, Name))).
+
+generic_call_pred_or_func(higher_order(_, PredOrFunc, _)) = PredOrFunc.
+generic_call_pred_or_func(class_method(_, _, _, CallId)) =
+	simple_call_id_pred_or_func(CallId).
+generic_call_pred_or_func(aditi_builtin(_, CallId)) =
+	simple_call_id_pred_or_func(CallId).
+
+:- func simple_call_id_pred_or_func(simple_call_id) = pred_or_func.
+simple_call_id_pred_or_func(PredOrFunc - _) = PredOrFunc.
+
+%-----------------------------------------------------------------------------%
+%
+% Information stored with all kinds of goals
+%
+
+	% NB. Don't forget to check goal_util__name_apart_goalinfo
+	% if this structure is modified.
+:- type hlds_goal_info
+	---> goal_info(
+		pre_births :: set(prog_var),	% the pre-birth set
+		post_births :: set(prog_var),	% the post-birth set
+		pre_deaths :: set(prog_var),	% the pre-death set
+		post_deaths :: set(prog_var),	% the post-death set
+				% (all four are computed by liveness.m)
+				% NB for atomic goals, the post-deadness
+				% should be applied _before_ the goal
+
+		determinism :: determinism, 
+				% the overall determinism of the goal
+				% (computed during determinism analysis)
+				% [because true determinism is undecidable,
+				% this may be a conservative approximation]
+
+		instmap_delta :: instmap_delta,
+				% the change in insts over this goal
+				% (computed during mode analysis)
+				% [because true unreachability is undecidable,
+				% the instmap_delta may be reachable even
+				% when the goal really never succeeds]
+				%
+				% The following invariant is required
+				% by the code generator and is enforced
+				% by the final simplification pass:
+				% the determinism specifies at_most_zero solns
+				% iff the instmap_delta is unreachable.
+				%
+				% Before the final simplification pass,
+				% the determinism and instmap_delta
+				% might not be consistent with regard to
+				% unreachability, but both will be
+				% conservative approximations, so if either
+				% says a goal is unreachable then it is.
+				%
+				% Normally the instmap_delta will list only
+				% the nonlocal variables of the goal.
+
+		context :: prog_context,
+
+		nonlocals :: set(prog_var),
+				% the non-local vars in the goal,
+				% i.e. the variables that occur both inside
+				% and outside of the goal.
+				% (computed by quantification.m)
+				% [in some circumstances, this may be a
+				% conservative approximation: it may be
+				% a superset of the real non-locals]
+
+		/*
+		code_gen_nonlocals :: maybe(set(prog_var)),
+				% the non-local vars in the goal,
+				% modified slightly for code generation.
+				% The difference between the code-gen nonlocals
+				% and the ordinary nonlocals is that arguments
+				% of a reconstruction which are taken from the
+				% reused cell are not considered to be
+				% `code_gen_nonlocals' of the goal.
+				% This avoids allocating stack slots and
+				% generating unnecessary field extraction
+				% instructions for those arguments.
+				% Mode information is still computed using
+				% the ordinary non-locals.
+				% 
+				% If the field has value `no', the ordinary
+				% nonlocals are used instead. This will
+				% be the case if the procedure body does not
+				% contain any reconstructions.
+		*/
+
+		follow_vars :: maybe(follow_vars),
+				% advisory information about where variables
+				% ought to be put next. The legal range
+				% includes the nonexistent register r(-1),
+				% which indicates any available register.
+
+		features :: set(goal_feature),
+				% The set of used-defined "features" of
+				% this goal, which optimisers may wish
+				% to know about.
+
+		resume_point :: resume_point,
+				% If this goal establishes a resumption point,
+				% state what variables need to be saved for
+				% that resumption point, and which entry
+				% labels of the resumption point will be
+				% needed. (See compiler/notes/allocation.html)
+
+		goal_path :: goal_path
+				% The path to this goal from the root in
+				% reverse order.
+	).
+
+
 goal_info_init(GoalInfo) :-
 	Detism = erroneous,
 	set__init(PreBirths),
@@ -1287,8 +1341,6 @@
 goal_set_resume_point(Goal - GoalInfo0, ResumePoint, Goal - GoalInfo) :-
 	goal_info_set_resume_point(GoalInfo0, ResumePoint, GoalInfo).
 
-%-----------------------------------------------------------------------------%
-
 goal_info_resume_vars_and_loc(Resume, Vars, Locs) :-
 	(
 		Resume = resume_point(Vars, Locs)
@@ -1298,6 +1350,9 @@
 	).
 
 %-----------------------------------------------------------------------------%
+%
+% Miscellaneous utility procedures for dealing with HLDS goals
+%
 
 	% Convert a goal to a list of conjuncts.
 	% If the goal is a conjunction, then return its conjuncts,
@@ -1617,14 +1672,25 @@
 	instmap_delta_insert(InstMapDelta0, Var, Inst, InstMapDelta),
 	goal_info_init(NonLocals, InstMapDelta, det, GoalInfo).
 
-generic_call_pred_or_func(higher_order(_, PredOrFunc, _)) = PredOrFunc.
-generic_call_pred_or_func(class_method(_, _, _, CallId)) =
-	simple_call_id_pred_or_func(CallId).
-generic_call_pred_or_func(aditi_builtin(_, CallId)) =
-	simple_call_id_pred_or_func(CallId).
+%-----------------------------------------------------------------------------%
 
-:- func simple_call_id_pred_or_func(simple_call_id) = pred_or_func.
-simple_call_id_pred_or_func(PredOrFunc - _) = PredOrFunc.
+get_pragma_foreign_var_names(MaybeVarNames, VarNames) :-
+	get_pragma_foreign_var_names_2(MaybeVarNames, [], VarNames0),
+	list__reverse(VarNames0, VarNames).
+
+:- pred get_pragma_foreign_var_names_2(list(maybe(pair(string, mode)))::in,
+	list(string)::in, list(string)::out) is det.
+
+get_pragma_foreign_var_names_2([], Names, Names).
+get_pragma_foreign_var_names_2([MaybeName | MaybeNames], Names0, Names) :-
+	(
+		MaybeName = yes(Name - _),
+		Names1 = [Name | Names0]
+	;
+		MaybeName = no,
+		Names1 = Names0
+	),
+	get_pragma_foreign_var_names_2(MaybeNames, Names1, Names).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%


-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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