[m-rev.] For review: Annotate the HLDS with regions

Julien Fischer juliensf at csse.unimelb.edu.au
Wed Jun 27 15:30:56 AEST 2007


On Mon, 18 Jun 2007, Quan Phan wrote:

> Estimated hours taken: 25.
> Branch: main.
>
> Annotate the HLDS with information about regions. This includes calls to
> region builtins, extra region arguments for procedures and calls, regions
> for construction unifications.
>
> compiler/hlds_goal.m:
>        Add another type constructor for how_to_construct to allow
> 	constructing terms in regions.
>
> compiler/goal_util.m
> compiler/hlds_out.m
> compiler/ml_unify_gen.m
> compiler/interval.m
> compiler/quantification.m
> compiler/structure_reuse.indirect.m
> 	Change to suit with the above additional type constructor.
>
> compiler/rbmm.condition_renaming.m:
> 	Change the algorithm so that the transformation needed to solve the
> 	problem with if-then-else is derived after the region annotated
> 	program has been transformed for solving the region resurrection
> 	problem. This is needed because the solution to region resurrection
> 	problem may introduce bindings of non-local region variables inside
> 	condition goal of an if-then-else.
>
> compiler/rbmm.execution_path.m:
> 	Correct a typo.
>
> compiler/rbmm.m: Add a new submodule region_transformation.
>
> compiler/rbmm.region_resurrection_renaming.m:
> 	Provide better comments. Reordering some predicates to suit with
> 	the flow of computation.
>
> compiler/rbmm.region_transformation.m:
> 	New file.
> 	Annotate the HLDS with region information to prepare for code
> 	generation.

...

> Index: interval.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/compiler/interval.m,v
> retrieving revision 1.29
> diff -u -u -r1.29 interval.m
> --- interval.m	12 Jun 2007 07:21:25 -0000	1.29
> +++ interval.m	18 Jun 2007 12:35:51 -0000
> @@ -353,6 +353,11 @@
>                 HowToConstruct = reuse_cell(_),
>                 unexpected(this_file, "build_interval_info_in_goal: reuse")
>             ;
> +                % XXX Temporary for the time being.
> +                HowToConstruct = construct_in_region(_),
> +                unexpected(this_file,
> +                    "build_interval_info_in_goal: contruct in region")

s/contruct/construct/

> +            ;
>                 ( HowToConstruct = construct_statically(_)
>                 ; HowToConstruct = construct_dynamically
>                 )


...

> Index: quantification.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/compiler/quantification.m,v
> retrieving revision 1.116
> diff -u -u -r1.116 quantification.m
> --- quantification.m	12 Jun 2007 07:21:25 -0000	1.116
> +++ quantification.m	18 Jun 2007 12:37:41 -0000
> @@ -517,6 +517,8 @@
>         ;
>             ( How = construct_statically(_)
>             ; How = construct_dynamically
> +            % XXX Temporary for the time being.
> +            ; How = construct_in_region(_)
>             ),
>             MaybeSetArgs = no,
>             MaybeReuseVar = no
> @@ -1129,6 +1131,8 @@
>         ;
>             ( How = construct_statically(_)
>             ; How = construct_dynamically
> +            % XXX Temporary for the time being.
> +            ; How = construct_in_region(_)
>             ),
>             MaybeSetArgs = no
>         ),
> Index: rbmm.condition_renaming.m
> ===================================================================
> RCS file:
> /home/mercury/mercury1/repository/mercury/compiler/rbmm.condition_renaming.m,v
> retrieving revision 1.2
> diff -u -u -r1.2 rbmm.condition_renaming.m
> --- rbmm.condition_renaming.m	15 Jun 2007 11:46:11 -0000	1.2
> +++ rbmm.condition_renaming.m	18 Jun 2007 07:46:31 -0000
> @@ -16,6 +16,17 @@
> % program point so that the binding of non-local regions in the condition
> % goal of an if-then-else is resolved.
> %
> +% When reasoning about the renaming and reverse renaming needed for

 	... for an if-then-else we take into account ...

> +% if-then-else here we take into account the changes to regions caused by the
> +% renaming and renaming annotations needed for region resurrection.
> +% This can be viewed as if the program is transformed by the renaming
> +% and reverse renaming for region surrection first. This is to solve the

s/surrection/ressurrection/

> +% problem with region resurrection. Then that transformed program is
> +% transformed again to solve the problem with if-then-else. Note that the
> +% first transformation may add to the problem with if-then-else, e.g.,
> +% when it introduces reverse renaming to a non-local variable inside the
> +% condition goal of an if-then-else.
> +%

...

> Index: rbmm.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.m,v
> retrieving revision 1.4
> diff -u -u -r1.4 rbmm.m
> --- rbmm.m	15 Jun 2007 11:46:11 -0000	1.4
> +++ rbmm.m	18 Jun 2007 07:32:48 -0000
> @@ -28,6 +28,7 @@
> :- include_module region_instruction.
> :- include_module region_liveness_info.
> :- include_module region_resurrection_renaming.
> +:- include_module region_transformation.
>
> :- import_module hlds.
> :- import_module hlds.hlds_module.
> @@ -52,6 +53,10 @@
> :- import_module transform_hlds.rbmm.points_to_analysis.
> :- import_module transform_hlds.rbmm.region_instruction.
> :- import_module transform_hlds.rbmm.region_resurrection_renaming.
> +:- import_module transform_hlds.rbmm.region_transformation.
> +
> +:- import_module map.
> +:- import_module hlds.hlds_out.

Please check the coding standard regarding module imports.  In particular
compiler imports should be in one block, followed by library imports in
another.

...

> Index: rbmm.region_resurrection_renaming.m
> ===================================================================
> RCS file:
> /home/mercury/mercury1/repository/mercury/compiler/rbmm.region_resurrection_renaming.m,v
> retrieving revision 1.2
> diff -u -u -r1.2 rbmm.region_resurrection_renaming.m
> --- rbmm.region_resurrection_renaming.m	15 Jun 2007 11:46:12 -0000	1.2
> +++ rbmm.region_resurrection_renaming.m	18 Jun 2007 07:49:45 -0000
> @@ -56,19 +56,49 @@
> :- type join_point_region_name_table ==
>     map(pred_proc_id, map(program_point, string)).
>
> +    % This predicate traveses execution paths and computes 2 pieces of

s/2/two/

> +    % information:
> +    % 1. The set of regions that become live before a program point
> +    % (for each program point in a procedure).
> +    % 2. For each procedure, compute the execution paths in which
> +    % resurrections of regions happen. For such an execution path
> +    % it also calculates the regions which resurrect. Only procedures
> +    % which contain resurrection are kept in the results. And for such
> +    % procedures only execution paths that contain resurrection are
> +    % kept.
> +    %
> :- pred compute_resurrection_paths(execution_path_table::in,
>     proc_pp_region_set_table::in, proc_pp_region_set_table::in,
>     proc_region_set_table::in, proc_region_set_table::in,
>     proc_pp_region_set_table::out, proc_resurrection_path_table::out) is det.

...

> +:- pred collect_join_points_path(list(list(program_point))::in,
> +    list(program_point)::in, int::in, int::out, set(program_point)::in,
> +    set(program_point)::out, map(program_point, string)::in,
> +    map(program_point, string)::out) is det.
> +
> +collect_join_points_path(Paths, Path, !Counter, !JoinPoints,
> +        !JoinPointProc) :-
> +    list.delete_all(Paths, Path, TheOtherPaths),
> +    % We ignore the first program point in each path because
> +    % it cannot be a join point.
> +    ( if    Path = [PrevPoint, ProgPoint | ProgPoints]
> +      then
> +            ( if    is_join_point(ProgPoint, PrevPoint, TheOtherPaths)
> +              then
> +                    svmap.set(ProgPoint,
> +                        "_jp_" ++ string.int_to_string(!.Counter),
> +                        !JoinPointProc),
> +                    svset.insert(ProgPoint, !JoinPoints),
> +                    !:Counter = !.Counter + 1
> +              else
> +                    true
> +            ),
> +            collect_join_points_path(Paths,
> +                [ProgPoint | ProgPoints], !Counter, !JoinPoints,
> +                !JoinPointProc)
> +      else
> +            true
> +    ).

Rather than using an `int' as the counter here you should use the `counter'
type from the standard library (defined in thecounter module).

...

> Index: rbmm.region_transformation.m
> ===================================================================
> RCS file: rbmm.region_transformation.m
> diff -N rbmm.region_transformation.m
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ rbmm.region_transformation.m	18 Jun 2007 06:46:46 -0000
> @@ -0,0 +1,944 @@
> +%-----------------------------------------------------------------------------%
> +% vim: ft=mercury ts=4 sw=4
> +%-----------------------------------------------------------------------------%
> +% Copyright (C) 2007 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.
> +%-----------------------------------------------------------------------------%
> +%
> +% File: rbmm.region_transformation.m
> +% Main author: quan.
> +%
> +% This module annotates the HLDS with region information.
> +% The region information includes:
> +% - Add extra region arguments (to pass regions around) to procedures and
> +% calls.
> +% - Update how_to_construct of construction unifications so that we can
> +% construct terms in a region.
> +% - Add region builtin calls (defined in region_builtin.m).

...

> +:- pred generate_list_of_region_type(int::in, mer_type::in,
> +	list(mer_type)::out) is det.
> +
> +generate_list_of_region_type(N, RegType, RegTypes) :-
> +	( if	N = 0
> +	  then
> +	  	    RegTypes = []
> +	  else
> +			generate_list_of_region_type(N - 1, RegType, RegTypes0),
> +			RegTypes = [RegType | RegTypes0]
> +	).


You can use the library function list.duplicate/2 to do that.

...

> +:- pred region_transform_proc(rpta_info_table::in, proc_region_set_table::in,
> +	proc_region_set_table::in, proc_region_set_table::in,
> +	proc_pp_region_list_table::in,
> +	renaming_table::in, renaming_table::in, annotation_table::in,
> +	renaming_annotation_table::in, renaming_annotation_table::in,
> +	pred_id::in, proc_id::in, name_to_prog_var_table::in,
> +	name_to_prog_var_table::out, module_info::in, module_info::out) is det.
> +
> +region_transform_proc(RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
> +		ActualRegionArgTable, ResurRenamingTable, IteRenamingTable,
> +		AnnotationTable, ResurRenamingAnnoTable, IteRenamingAnnoTable,
> +		PredId, ProcId, !NameToVarTable, !ModuleInfo) :-
> +    PPId = proc(PredId, ProcId),
> +	module_info_pred_proc_info(!.ModuleInfo, PPId, PredInfo, ProcInfo0),
> +	fill_goal_path_slots(!.ModuleInfo, ProcInfo0, ProcInfo1),
> +	proc_info_get_varset(ProcInfo1, VarSet0),
> +	proc_info_get_vartypes(ProcInfo1, VarTypes0),
> +	proc_info_get_headvars(ProcInfo1, HeadVars0),
> +	proc_info_get_argmodes(ProcInfo1, ActualArgModes0),
> +	proc_info_get_goal(ProcInfo1, Goal0),
> +	map.lookup(RptaInfoTable, PPId, rpta_info(Graph, _)),
> +	map.lookup(ConstantRTable, PPId, ConstantR),
> +	map.lookup(DeadRTable, PPId, DeadR),
> +	map.lookup(BornRTable, PPId, BornR),
> +	map.lookup(ActualRegionArgTable, PPId, ActualRegionArgProc),
> +	( if	map.search(ResurRenamingTable, PPId, ResurRenamingProc0)
> +	  then
> +			ResurRenamingProc = ResurRenamingProc0,
> +			map.lookup(ResurRenamingAnnoTable, PPId,
> +				ResurRenamingAnnoProc)
> +	  else
> +			ResurRenamingProc = map.init,
> +			ResurRenamingAnnoProc = map.init
> +	),
> +	( if	map.search(IteRenamingTable, PPId, IteRenamingProc0)
> +	  then
> +			IteRenamingProc = IteRenamingProc0,
> +			map.lookup(IteRenamingAnnoTable, PPId,
> +				IteRenamingAnnoProc)
> +	  else
> +			IteRenamingProc = map.init,
> +			IteRenamingAnnoProc = map.init
> +	),
> +	map.lookup(AnnotationTable, PPId, AnnotationProc),
> +
> +	NameToVar0 = map.init,
> +	annotate_proc(!.ModuleInfo, PredInfo, Graph, ConstantR, DeadR, BornR,
> +		ActualRegionArgProc, ResurRenamingProc, IteRenamingProc,
> +		AnnotationProc, ResurRenamingAnnoProc, IteRenamingAnnoProc,
> +		VarSet0, _, VarTypes0, _, HeadVars0, _, ActualArgModes0, _,
> +		Goal0, _, NameToVar0, NameToVar, ProcInfo1, ProcInfo),


You will need to recompute the instmap deltas for the procedure at this point,
e.g. something like

 	RecomputeAtomic = yes,
 	recompute_instmap_delta_proc(RecomputeAtomic, ProcInfo2, ProcInfo, !ModuleInfo),

(where ProcInfo2 is the output of annotate_proc/26)

You may also need to recompute the purity at this point as well, i.e. call
repurity_check_proc/4.


> +
> +	module_info_set_pred_proc_info(PPId, PredInfo, ProcInfo, !ModuleInfo),
> +	svmap.det_insert(PPId, NameToVar, !NameToVarTable).
> +
> +	% Currently for a procedure we annotate the following information:
> +	% 1. VarSet with region variables
> +	% 2. VarTypes with region variables and their types
> +	% 3. HeadVars with formal region arguments
> +	% 4. ActualHeadModes with the modes for region variables
> +	% 5. Body:
> +	% 	+ new region arguments at calls
> +	%	+ new calls to region instructions
> +	%
> +	% XXX What about head_var_caller_liveness and
> +	% prog_sub_info -> arg_pass_info
> +	%
> +	%
> +:- pred annotate_proc(module_info::in, pred_info::in, rpt_graph::in,
> +	region_set::in, region_set::in, region_set::in,
> +	pp_region_list_table::in, renaming_proc::in, renaming_proc::in,
> +	annotation_proc::in, renaming_annotation_proc::in,
> +	renaming_annotation_proc::in, prog_varset::in, prog_varset::out,
> +	vartypes::in, vartypes::out, list(prog_var)::in, list(prog_var)::out,
> +	list(mer_mode)::in, list(mer_mode)::out, hlds_goal::in, hlds_goal::out,
> +	name_to_prog_var::in, name_to_prog_var::out, proc_info::in,
> +	proc_info::out) is det.
> +
> +annotate_proc(ModuleInfo, PredInfo, Graph, ConstantR, DeadR, BornR,
> +		ActualRegionArgProc, ResurRenamingProc, IteRenamingProc,
> +		AnnotationProc, ResurRenamingAnnoProc, IteRenamingAnnoProc,
> +		!VarSet, !VarTypes, !HeadVars, !ActualArgModes, !Goal,
> +		!NameToVar, !ProcInfo) :-
> +	region_transform_goal(ModuleInfo, Graph, ResurRenamingProc,
> +		IteRenamingProc, ActualRegionArgProc,
> +		AnnotationProc, ResurRenamingAnnoProc, IteRenamingAnnoProc,
> +		!Goal, !NameToVar, !VarSet, !VarTypes),
> +
> +	% Computing head_vars.
> +	% Note that formal region arguments are not subjected to renaming.
> +	set.to_sorted_list(ConstantR, LConstantR),
> +	set.to_sorted_list(DeadR, LDeadR),
> +	set.to_sorted_list(BornR, LBornR),
> +	FormalInputNodes = LConstantR ++ LDeadR,
> +	FormalNodes = FormalInputNodes ++ LBornR,
> +	list.map_foldl3(node_to_reg_var(Graph), FormalNodes, FormalRegionArgs,
> +		!NameToVar, !VarSet, !VarTypes),
> +
> +	% Computing actual_head_modes.
> +	InMode = in_mode,
> +	OutMode = out_mode,
> +	list.foldl(generate_mode_list(InMode), FormalInputNodes, [], InModes),
> +	list.foldl(generate_mode_list(OutMode), LBornR, [], OutModes),
> +
> +	% One thing to notice here is that the output of a function needs
> +	% to be the last argument.
> +	PredOrFunc = pred_info_is_pred_or_func(PredInfo),
> +	(
> +		PredOrFunc = pf_predicate,
> +		!:HeadVars = !.HeadVars ++ FormalRegionArgs,
> +		!:ActualArgModes = !.ActualArgModes ++ InModes ++ OutModes
> +	;
> +		PredOrFunc = pf_function,
> +		list.split_last_det(!.HeadVars, BeforeLastHeadVar, LastHeadVar),
> +		!:HeadVars = BeforeLastHeadVar ++ FormalRegionArgs
> +			++ [LastHeadVar],
> +		list.split_last_det(!.ActualArgModes, BeforeLastHeadMode,
> +			LastHeadMode),
> +		!:ActualArgModes = BeforeLastHeadMode ++ InModes
> +			++ OutModes ++ [LastHeadMode]
> +	),
> +
> +	proc_info_set_varset(!.VarSet, !ProcInfo),
> +	proc_info_set_goal(!.Goal, !ProcInfo),
> +	proc_info_set_vartypes(!.VarTypes, !ProcInfo),
> +	proc_info_set_headvars(!.HeadVars, !ProcInfo),
> +	proc_info_set_argmodes(!.ActualArgModes, !ProcInfo).
> +
> +:- pred generate_mode_list(mer_mode::in, rptg_node::in, list(mer_mode)::in,
> +	list(mer_mode)::out) is det.
> +
> +generate_mode_list(Mode, _Node, Modes0, [Mode | Modes0]).
> +
> +	% Basically, we will turn this atomic goal and all the region
> +	% annotations attached to (before and after) it into a
> +	% conjunction (even when there is no annotation). If the

Why don't you just leave them alone if there is no annotation?

...

> +	%
> +	% Note: When both renamings (for resurrection and if-then-else) of a
> +	% region exist at a program point, we will apply the resurrection one.
> +	% This is due to the fact that when reasonning about what renaming is

s/reasonning/reasoning/

> +	% needed for if-then-else we have taken into account the changes
> +	% caused by renaming and annotations needed for resurrection problem.
> +	%

 	... for the ressurrection problem.

> +:- pred region_transform_goal(module_info::in, rpt_graph::in,
> +	renaming_proc::in, renaming_proc::in, pp_region_list_table::in,
> +	annotation_proc::in, renaming_annotation_proc::in,
> +	renaming_annotation_proc::in, hlds_goal::in, hlds_goal::out,
> +	name_to_prog_var::in, name_to_prog_var::out,
> +	prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
> +
> +region_transform_goal(ModuleInfo, Graph, ResurRenamingProc, IteRenamingProc,
> +		ActualRegionArgProc, AnnotationProc, ResurRenamingAnnoProc,
> +		IteRenamingAnnoProc, !Goal, !NameToVar, !VarSet, !VarTypes) :-
> +    !.Goal = hlds_goal(GoalExpr0, Info),
> +	(	goal_is_atomic(GoalExpr0)
> +	->
> +		ProgPoint = program_point_init(Info),
> +		ProgPoint = pp(Context, _),
> +		find_renamings_at_prog_point(ResurRenamingProc, IteRenamingProc,
> +			ProgPoint, ResurRenaming, IteRenaming),
> +
> +		% Depending on the expression, this call will annotate
> +		% - a call with actual region arguments,
> +		% - a construction unification with a region to construct in.
> +		region_transform_goal_expr(Graph, ResurRenaming,
> +			IteRenaming, ActualRegionArgProc, ProgPoint,
> +			GoalExpr0, GoalExpr, !NameToVar, !VarSet, !VarTypes),
> +
> +		% Assignment unifications due to ite renaming.
> +		assignments_from_ite_renaming_anno(IteRenamingAnnoProc,
> +			ProgPoint, !NameToVar, !VarSet, !VarTypes,
> +			[], IteRenamingAssignments),
> +
> +		% Region instructions before and after this program point.
> +		(	map.search(AnnotationProc, ProgPoint,
> +				before_after(Before, After))
> +		->
> +			% Region instructions before this program point.
> +			list.foldl4(region_instruction_to_conj(ModuleInfo,
> +				Context, ResurRenaming, IteRenaming), Before,
> +				!NameToVar, !VarSet, !VarTypes,
> +				IteRenamingAssignments, Conjs1),
> +
> +			% The goal at this program point itself.
> +			Conjs2 = Conjs1 ++ [hlds_goal(GoalExpr, Info)],
> +
> +			% Region instructions after this program point.
> +			list.foldl4(region_instruction_to_conj(ModuleInfo,
> +				Context, ResurRenaming, IteRenaming), After,
> +				!NameToVar, !VarSet, !VarTypes,
> +				Conjs2, Conjs3)
> +		;
> +			% The goal at this program point itself.
> +			Conjs3 = IteRenamingAssignments ++
> +				[hlds_goal(GoalExpr, Info)]
> +		),
> +
> +		% Assignment unifications due to region resurrection renaming.
> +		assignments_from_resur_renaming_anno(ResurRenamingAnnoProc,
> +			ProgPoint, IteRenaming, !NameToVar, !VarSet, !VarTypes,
> +			Conjs3, Conjs),
> +
> +		!:Goal = hlds_goal(conj(plain_conj, Conjs), Info)
> +	;
> +		region_transform_compound_goal(ModuleInfo, Graph,
> +			ResurRenamingProc, IteRenamingProc, ActualRegionArgProc,
> +			AnnotationProc, ResurRenamingAnnoProc,
> +			IteRenamingAnnoProc, !Goal, !NameToVar, !VarSet,
> +			!VarTypes)
> +	).
> +
> +:- pred region_transform_goal_expr(rpt_graph::in, renaming::in,
> +	renaming::in, pp_region_list_table::in, program_point::in,
> +	hlds_goal_expr::in, hlds_goal_expr::out, name_to_prog_var::in,
> +	name_to_prog_var::out, prog_varset::in, prog_varset::out,
> +	vartypes::in, vartypes::out) is det.
> +
> +	% Annotate procedure calls with actual region arguments.
> +	%
> +region_transform_goal_expr(Graph, ResurRenaming, IteRenaming,
> +		ActualRegionArgProc, ProgPoint, !GoalExpr, !NameToVar, !VarSet,
> +		!VarTypes) :-
> +	!.GoalExpr = plain_call(CalleePredId, CalleeProcId, Args0, Builtin,
> +		Context, Name),
> +	% XXX Callee may be a builtin or an imported procedure that we have
> +	% not analysed, we just ignore such a call for now.
> +	( if	map.search(ActualRegionArgProc, ProgPoint, ActualNodes0)
> +	  then	ActualNodes = ActualNodes0
> +	  else	ActualNodes = []
> +	),
> +	list.map_foldl3(node_to_reg_var_with_both_renamings(Graph,
> +		ResurRenaming, IteRenaming),
> +		ActualNodes, ActualRegionArgs, !NameToVar, !VarSet, !VarTypes),
> +	Args = Args0 ++ ActualRegionArgs,
> +	!:GoalExpr = plain_call(CalleePredId, CalleeProcId, Args, Builtin,
> +		Context, Name).
> +
> +	% Annotate construction unifications with regions to construct in.
> +	%
> +region_transform_goal_expr(Graph, ResurRenaming, IteRenaming,
> +		_, _, !GoalExpr, !NameToVar, !VarSet, !VarTypes) :-
> +	!.GoalExpr = unify(LHS, RHS, Mode, Unification0, Context),
> +    annotate_constructions_unification(Graph, ResurRenaming, IteRenaming,
> +		Unification0, Unification, !NameToVar, !VarSet, !VarTypes),
> +	!:GoalExpr = unify(LHS, RHS, Mode, Unification, Context).
> +
> +region_transform_goal_expr(_, _, _, _, _, !GoalExpr, !NameToVar,
> +		!VarSet, !VarTypes) :-
> +	!.GoalExpr = generic_call(_, _, _, _),
> +	sorry(this_file,
> +		"region_transform_goal_expr: generic call is not handled.").
> +
> +region_transform_goal_expr(_, _, _, _, _, !GoalExpr, !NameToVar,
> +		!VarSet, !VarTypes) :-
> +	!.GoalExpr = call_foreign_proc(_, _, _, _, _, _, _),
> +	sorry(this_file, "region_transform_goal_expr: " ++
> +		"call to foreign procedure is not handled").
> +
> +region_transform_goal_expr(_, _, _, _, _, !GoalExpr, !NameToVar,
> +		!VarSet, !VarTypes) :-
> +	( !.GoalExpr = conj(_, [])
> +	; !.GoalExpr = disj([])
> +	).
> +
> +region_transform_goal_expr(_, _, _, _, _, !GoalExpr, !NameToVar,
> +		!VarSet, !VarTypes) :-
> +	( !.GoalExpr = conj(_, [_ | _])
> +	; !.GoalExpr = disj([_ | _])
> +	; !.GoalExpr = if_then_else(_, _, _, _)
> +	; !.GoalExpr = negation(_)
> +	; !.GoalExpr = switch(_, _, _)
> +	; !.GoalExpr = scope(_, _)
> +	; !.GoalExpr = shorthand(_)
> +	),
> +	unexpected(this_file,
> +		"region_transform_goal_expr: encounter compound goal").
> +

...

> +:- pred annotate_constructions_unification(rpt_graph::in, renaming::in,
> +	renaming::in, unification::in, unification::out,
> +	name_to_prog_var::in, name_to_prog_var::out,
> +	prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
> +
> +annotate_constructions_unification(Graph, ResurRenaming, IteRenaming,
> +		!Unification, !NameToVar, !VarSet, !VarTypes) :-
> +	!.Unification = construct(Var, ConsId, Args, ArgModes, _HowToConstruct0,
> +		IsUnique, SubInfo),
> +	get_node_by_variable(Graph, Var, Node),
> +	Name = rptg_lookup_region_name(Graph, Node),
> +	name_to_reg_var_with_both_renamings(Name, ResurRenaming, IteRenaming,
> +		RegVar, !NameToVar, !VarSet, !VarTypes),
> +	HowToConstruct = construct_in_region(RegVar),
> +	!:Unification = construct(Var, ConsId, Args, ArgModes, HowToConstruct,
> +		IsUnique, SubInfo).
> +
> +annotate_constructions_unification(_, _, _, !Unification, !VarSet,
> +		!VarTypes, !NameToVar) :-
> +	(
> +		( !.Unification = deconstruct(_, _, _, _, _, _)
> +		; !.Unification = assign(_, _)
> +		; !.Unification = simple_test(_, _)
> +		),
> +		true

Delete 'true'.

> +	;
> +		!.Unification = complicated_unify(_, _, _),
> +		unexpected(this_file, "annotate_construction_unification: "
> +			++ "encounter complicated unify")
> +	).
> +
> +	% The process here is related to the way we treat the unifications
> +	% between the switch vars and a constant or a functor of arity zero.
> +	% For more information about the treatment, see rbmm.execution_path.m.
> +	% These unifications are not explicitly present in the goal but we
> +	% still need to insert annotations derived for them into the goal.
> +	% Therefore we will make a conjunction of the annotations attached to an
> +	% implicit unification. We transform the goal separately. Then we make
> +	% another conjunction of the conjunction and the transformed goal.
> +	% Finally, we try to flatten this new conjunction.
> +	%
> +:- pred region_transform_case(module_info::in, rpt_graph::in,
> +	renaming_proc::in, renaming_proc::in, pp_region_list_table::in,
> +	annotation_proc::in, renaming_annotation_proc::in,
> +	renaming_annotation_proc::in, hlds_goal::in, case::in, case::out,
> +	name_to_prog_var::in, name_to_prog_var::out,
> +	prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
> +
> +region_transform_case(ModuleInfo, Graph, ResurRenamingProc,
> +		IteRenamingProc, ActualRegionArgProc, AnnotationProc,
> +		ResurRenamingAnnoProc, IteRenamingAnnoProc, Switch,
> +		case(ConsId, !.Goal), case(ConsId, !:Goal),
> +		!NameToVar, !VarSet, !VarTypes) :-
> +	( 	( ConsId = cons(_, 0)
> +		; ConsId = int_const(_)
> +		; ConsId = string_const(_)
> +		; ConsId = float_const(_)
> +		),
> +		Switch = hlds_goal(switch(_, _, _), Info)
> +	->
> +		ProgPoint = program_point_init(Info),
> +		ProgPoint = pp(Context, _),
> +		find_renamings_at_prog_point(ResurRenamingProc, IteRenamingProc,
> +			ProgPoint, ResurRenaming, IteRenaming),
> +
> +		% Assignment unifications due to ite renaming.
> +		assignments_from_ite_renaming_anno(IteRenamingAnnoProc,
> +			ProgPoint, !NameToVar, !VarSet, !VarTypes,
> +			[], IteRenamingAssignments),
> +
> +		% Region instructions before and after this program
> +		% point.
> +		(	map.search(AnnotationProc, ProgPoint,
> +				before_after(Before, After))
> +		->
> +			% Region instructions before this program point.
> +			list.foldl4(region_instruction_to_conj(
> +				ModuleInfo, Context, ResurRenaming,
> +				IteRenaming), Before, !NameToVar,
> +				!VarSet, !VarTypes,
> +				IteRenamingAssignments, Conjs1),
> +
> +			% Region instructions after this program point.
> +			list.foldl4(region_instruction_to_conj(
> +				ModuleInfo, Context, ResurRenaming,
> +				IteRenaming), After, !NameToVar,
> +				!VarSet, !VarTypes, Conjs1, Conjs2)
> +		;
> +			Conjs2 = IteRenamingAssignments
> +		),
> +
> +		% Assignment unifications due to region resurrection
> +		% renaming.
> +		assignments_from_resur_renaming_anno(ResurRenamingAnnoProc,
> +			ProgPoint, IteRenaming, !NameToVar, !VarSet, !VarTypes,
> +			Conjs2, Conjs),
> +
> +		RemovedGoal = hlds_goal(conj(plain_conj, Conjs), Info)
> +	;
> +		Switch = hlds_goal(_, Info),
> +		RemovedGoal = hlds_goal(conj(plain_conj, []), Info)
> +	),
> +	region_transform_goal(ModuleInfo, Graph, ResurRenamingProc,
> +		IteRenamingProc, ActualRegionArgProc, AnnotationProc,
> +		ResurRenamingAnnoProc, IteRenamingAnnoProc, !Goal, !NameToVar,
> +		!VarSet, !VarTypes),
> +	flatten_conjunction([RemovedGoal, !.Goal], FlatConjs),
> +	Switch = hlds_goal(_, ConjsInfo),
> +	!:Goal = hlds_goal(conj(plain_conj, FlatConjs), ConjsInfo).
> +
> +:- pred find_renamings_at_prog_point(renaming_proc::in, renaming_proc::in,
> +	program_point::in, renaming::out, renaming::out) is det.
> +
> +find_renamings_at_prog_point(ResurRenamingProc, IteRenamingProc, ProgPoint,
> +		ResurRenaming, IteRenaming) :-
> +	( if	map.search(ResurRenamingProc, ProgPoint, ResurRenaming0)
> +	  then
> +	  		ResurRenaming = ResurRenaming0
> +	  else
> +	  		ResurRenaming = map.init
> +	),
> +	( if	map.search(IteRenamingProc, ProgPoint, IteRenaming0)
> +	  then
> +	  		IteRenaming = IteRenaming0
> +	  else
> +	  		IteRenaming = map.init
> +	).
> +
> +:- pred assignments_from_ite_renaming_anno(renaming_annotation_proc::in,
> +	program_point::in, name_to_prog_var::in, name_to_prog_var::out,
> +	prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
> +	hlds_goals::in, hlds_goals::out) is det.
> +
> +assignments_from_ite_renaming_anno(IteRenamingAnnoProc, ProgPoint,
> +		!NameToVar, !VarSet, !VarTypes, !IteRenamingAssignments) :-
> +	% Assignment unifications due to ite renaming.
> +	(	map.search(IteRenamingAnnoProc, ProgPoint, IteRenamingAnnos)
> +	->
> +		list.foldl4( ite_renaming_annotation_to_assignment,
> +			IteRenamingAnnos, !NameToVar, !VarSet, !VarTypes,
> +			!IteRenamingAssignments)
> +	;
> +		true
> +	).
> +
> +:- pred assignments_from_resur_renaming_anno(renaming_annotation_proc::in,
> +	program_point::in, renaming::in, name_to_prog_var::in,
> +	name_to_prog_var::out, prog_varset::in, prog_varset::out,
> +	vartypes::in, vartypes::out, hlds_goals::in, hlds_goals::out) is det.
> +
> +assignments_from_resur_renaming_anno(ResurRenamingAnnoProc, ProgPoint,
> +		IteRenaming, !NameToVar, !VarSet, !VarTypes, !Conjs) :-
> +	(	map.search(ResurRenamingAnnoProc, ProgPoint,
> +			ResurRenamingAnnos)
> +	->
> +		list.foldl4(resur_renaming_annotation_to_assignment(
> +			IteRenaming), ResurRenamingAnnos, !NameToVar, !VarSet,
> +			!VarTypes, !Conjs)
> +	;
> +		true
> +	).
> +
> +	% XXX This flatten predicate is copied and pasted from
> +	% prop_mode_constraints.m.
> +	%
> +    % flatten_conjunction(!Goals) flattens the conjunction Goals - that
> +    % is, moves the conjuncts from nested conjunctions into Goals.
> +    %
> +:- pred flatten_conjunction(hlds_goals::in, hlds_goals::out) is det.
> +
> +flatten_conjunction(!Goals) :-
> +    list.foldr(add_to_conjunction, !.Goals, [], !:Goals).
> +
> +    % add_to_conjunction(Goal, !Goals) adds Goal to the front of
> +    % the conjunction Goals. It keeps the conjunction flat, so
> +    % nested conjunctions are scrapped and their conjuncts prepended
> +    % to Goals.
> +    %
> +:- pred add_to_conjunction(hlds_goal::in, hlds_goals::in, hlds_goals::out)
> +    is det.
> +
> +add_to_conjunction(Goal, !Goals) :-
> +    ( Goal = hlds_goal(conj(plain_conj, SubGoals), _) ->
> +        list.append(SubGoals, !Goals)
> +    ;
> +        list.cons(Goal, !Goals)
> +    ).
> +
> +:- pred node_to_reg_var(rpt_graph::in, rptg_node::in,
> +	prog_var::out, name_to_prog_var::in, name_to_prog_var::out,
> +	prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.

Add a comment describing what this predicate does.

> +
> +node_to_reg_var(Graph, Node, RegVar, !NameToVar, !VarSet,
> +		!VarTypes) :-
> +	RegName = rptg_lookup_region_name(Graph, Node),
> +	name_to_reg_var(RegName, RegVar, !NameToVar, !VarSet, !VarTypes).
> +
> +:- pred name_to_reg_var(string::in, prog_var::out,
> +	name_to_prog_var::in, name_to_prog_var::out,
> +	prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
> +
> +name_to_reg_var(Name, RegVar, !NameToVar, !VarSet, !VarTypes) :-
> +	( if	map.search(!.NameToVar, Name, RegVar0)
> +	  then
> +			RegVar = RegVar0
> +	  else
> +			varset.new_named_var(!.VarSet, Name, RegVar, !:VarSet),
> +			svmap.det_insert(RegVar, make_region_type, !VarTypes),
> +			svmap.det_insert(Name, RegVar, !NameToVar)
> +	).
> +
> +:- pred node_to_reg_var_with_both_renamings(rpt_graph::in, renaming::in,
> +	renaming::in, rptg_node::in, prog_var::out,
> +	name_to_prog_var::in, name_to_prog_var::out,
> +	prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
> +
> +node_to_reg_var_with_both_renamings(Graph, ResurRenaming, IteRenaming,
> +		Node, RegVar, !NameToVar, !VarSet, !VarTypes) :-
> +	RegName = rptg_lookup_region_name(Graph, Node),
> +	name_to_reg_var_with_both_renamings(RegName, ResurRenaming, IteRenaming,
> +		RegVar, !NameToVar, !VarSet, !VarTypes).
> +
> +:- pred name_to_reg_var_with_renaming(string::in, renaming::in,
> +	prog_var::out, name_to_prog_var::in, name_to_prog_var::out,
> +	prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
> +
> +name_to_reg_var_with_renaming(Name0, ResurRenaming, RegVar,
> +		!NameToVar, !VarSet, !VarTypes) :-
> +	( if	map.search(ResurRenaming, Name0, Name1)
> +	  then
> +	  		Name = Name1
> +	  else
> +			Name = Name0
> +	),
> +	name_to_reg_var(Name, RegVar, !NameToVar, !VarSet, !VarTypes).
> +
> +	% Resurrection renaming will be applied first. If a renaming exists
> +	% for the name (therefore the name is changed to another name) then
> +	% ite renaming need not to be applied because actually it is not
> +	% applicable anymore.
> +:- pred name_to_reg_var_with_both_renamings(string::in, renaming::in,
> +	renaming::in, prog_var::out,
> +	name_to_prog_var::in, name_to_prog_var::out,
> +	prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
> +
> +name_to_reg_var_with_both_renamings(Name0, ResurRenaming, IteRenaming,
> +		RegVar, !NameToVar, !VarSet, !VarTypes) :-
> +	( if	map.search(ResurRenaming, Name0, Name1)
> +	  then	Name = Name1
> +	  else
> +	  		( if	map.search(IteRenaming, Name0, Name2)
> +			  then	Name = Name2
> +			  else  Name = Name0
> +			)
> +	),
> +	name_to_reg_var(Name, RegVar, !NameToVar, !VarSet, !VarTypes).
> +

...

> +:- pred region_instruction_to_conj(module_info::in, term.context::in,
> +	renaming::in, renaming::in, string::in,
> +	name_to_prog_var::in, name_to_prog_var::out,
> +	prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
> +	hlds_goals::in, hlds_goals::out) is det.
> +
> +	% Instruction is of the form: "Tx: xxxxxx R..."
> +	% The first x is the number of the rule, which is not important here.
> +	% The next 6 x is either "remove" or "create", the last part is the
> +	% region name. This region name will be subjected to renaming due to
> +	% if-then-else and region resurrection.
> +	% This predicate turns such an instruction into a call to a suitable
> +	% region builtin.
> +	%

Move this comment above the predicate declaration.

> +region_instruction_to_conj(ModuleInfo, Context, ResurRenaming, IteRenaming,
> +		Instruction, !NameToVar, !VarSet, !VarTypes, Conjs0, Conjs) :-
> +	string.substring(Instruction, 4, 6, Kind),
> +	string.substring(Instruction, 11, string.length(Instruction) - 11,
> +		RegionName),
> +	name_to_reg_var_with_both_renamings(RegionName, ResurRenaming,
> +		IteRenaming, RegVar, !NameToVar, !VarSet, !VarTypes),
> +	(
> +		Kind = "create"
> +	->
> +		generate_simple_call(mercury_region_builtin_module,
> +			"create_region", pf_predicate, only_mode, detism_det,
> +			purity_impure, [RegVar], [], [RegVar - free_inst],
> +			ModuleInfo, Context, CallGoal)
> +	;
> +		Kind = "remove"
> +	->
> +		generate_simple_call(mercury_region_builtin_module,
> +			"remove_region", pf_predicate, only_mode, detism_det,
> +			purity_impure, [RegVar], [], [RegVar - ground_inst],
> +			ModuleInfo, Context, CallGoal)
> +	;
> +		unexpected(this_file, "region_instruction_to_conj: " ++
> +			"encounter unknown region instruction")
> +	),
> +	Conjs = Conjs0 ++ [CallGoal].
> +
> +	% A resurrection renaming annotation is in the form Rx = Rx_resur_y,
> +	% where Rx is the original name of the region, the other is the one
> +	% the region is renamed to.
> +	% This predicate converts the anotation into an assigment unification.
> +	% The original name of the region is subjected to the renaming due to
> +	% if-then-else, if such a renaming exists at the current program point.
> +	%
> +:- pred resur_renaming_annotation_to_assignment(renaming::in, string::in,
> +	name_to_prog_var::in, name_to_prog_var::out,
> +	prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
> +	hlds_goals::in, hlds_goals::out) is det.
> +
> +resur_renaming_annotation_to_assignment(IteRenaming, Annotation,
> +		!NameToVar, !VarSet, !VarTypes, Conjs0, Conjs) :-
> +	( if	string.sub_string_search(Annotation, "=", Index)
> +	  then
> +	  		Left = string.substring(Annotation, 0, Index - 1),
> +			Right = string.substring(Annotation, Index + 2,
> +				string.length(Annotation) - (Index + 2)),
> +			% Only the left region needs to be renamed. Ite renaming
> +			% does not involve one on the right side.
> +			name_to_reg_var_with_renaming(Left, IteRenaming,
> +				LeftRegVar, !NameToVar, !VarSet, !VarTypes),
> +			name_to_reg_var(Right, RightRegVar, !NameToVar,
> +				!VarSet, !VarTypes),
> +			make_assignment_goal(LeftRegVar, RightRegVar,
> +				"resurrection renaming annotation",
> +				AssignmentGoal),
> +			Conjs = Conjs0 ++ [AssignmentGoal]
> +	  else
> +	  		unexpected(this_file, "resur_renaming_annotation_to_assignment: "
> +				++ "annotation is not assigment")
> +	).
> +
> +	% This predicate turns a renaming annotation due to if-then-else into
> +	% an assignment. No renaming needs to be applied to the
> +	% if-then-else renaming annotations.
> +	%
> +:- pred ite_renaming_annotation_to_assignment(string::in,
> +	name_to_prog_var::in, name_to_prog_var::out,
> +	prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
> +	hlds_goals::in, hlds_goals::out) is det.
> +
> +ite_renaming_annotation_to_assignment(Annotation, !NameToVar,
> +		!VarSet, !VarTypes, Conjs0, Conjs) :-
> +	( if	string.sub_string_search(Annotation, "=", Index)
> +	  then
> +	  		Left = string.substring(Annotation, 0, Index - 1),
> +			Right = string.substring(Annotation, Index + 2,
> +				string.length(Annotation) - (Index + 2)),
> +			name_to_reg_var(Left, LeftRegVar, !NameToVar,
> +				!VarSet, !VarTypes),
> +			name_to_reg_var(Right, RightRegVar, !NameToVar,
> +				!VarSet, !VarTypes),
> +			make_assignment_goal(LeftRegVar, RightRegVar,
> +				"ite renaming annotation", AssignmentGoal),
> +			Conjs = Conjs0 ++ [AssignmentGoal]
> +	  else
> +	  		unexpected(this_file, "ite_renaming_annotation_to_assignment: "
> +				++ "annotation is not assignment")
> +	).
> +
> +:- pred make_assignment_goal(prog_var::in, prog_var::in, string::in,
> +	hlds_goal::out) is det.
> +
> +make_assignment_goal(LeftRegVar, RightRegVar, Context, AssignmentGoal) :-
> +	AssignmentExpr = unify(LeftRegVar, rhs_var(RightRegVar),
> +		out_mode - in_mode,
> +		assign(LeftRegVar, RightRegVar),
> +		unify_context(
> +			umc_implicit(Context),
> +			[]
> +		)
> +	),
> +	NonLocals = set.from_list([LeftRegVar, RightRegVar]),
> +	instmap_delta_from_assoc_list([LeftRegVar - free_inst,
> +		RightRegVar - ground_inst], InstmapDelta),
> +	goal_info_init(NonLocals, InstmapDelta, detism_det,
> +		purity_pure, AssignmentInfo),
> +	AssignmentGoal = hlds_goal(AssignmentExpr, AssignmentInfo).
> +

...

> Index: structure_reuse.indirect.m
> ===================================================================
> RCS file:
> /home/mercury/mercury1/repository/mercury/compiler/structure_reuse.indirect.m,v
> retrieving revision 1.10
> diff -u -u -r1.10 structure_reuse.indirect.m
> --- structure_reuse.indirect.m	12 Jun 2007 07:21:26 -0000	1.10
> +++ structure_reuse.indirect.m	18 Jun 2007 12:50:00 -0000
> @@ -302,6 +302,8 @@
>             ;
>                 ( HowToConstruct = construct_dynamically
>                 ; HowToConstruct = reuse_cell(_)
> +                % XXX Temporary for the time being.
> +                ; HowToConstruct = construct_in_region(_)
>                 )

The above code is used to record variables that contain statically
allocated data; the above XXX is unnecessary since all other sorts
of construction unification should be handled the same way at that
point.

Julien.
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list