[m-rev.] For review: Make region variables regular Mercury variables
Quan Phan
Quan.Phan at cs.kuleuven.be
Wed Jun 6 16:12:14 AEST 2007
Hi,
Sorry, I missed one new file in the previous post.
Estimated hours taken: 60.
Branch: main.
Region variables have been considered imperative, making them different
from regular Mercury variables. We introduce renaming of region
variables so that region variables now normal Mercury logic variables.
This is necessary to integrate RBMM into Mercury.
Add one pass to collect actual region parameters at call sites.
Changes some files to follow coding standard or to have better
documentation.
compiler/mercury_compile.m:
Add !IO to the call to do_region_analysis.
compiler/rbmm.actual_region_arguments.m
New file.
Collect the actual region arguments at call sites in a seperate pass.
This should faciliate the process of annotating the HLDS later on.
compiler/rbmm.condition_renaming.m
New file.
Introduce renaming to solve the problem when non-local region
variables to an if-then-else get bound in the condition goal.
compiler/rbmm.execution_path.m
Minor changes to have better variable names.
compiler/rbmm.m
Include three new sub-modules.
Change do_region_analysis predicate so that it can print out.
Add calls to the predicate to collect actual region arguments and
to renaming predicates.
compiler/rbmm.region_instruction.m
Small changes to have better variable names.
compiler/rbmm.region_resurrection_renaming.m
New file.
Introduce renaming to solve the problem when region variables
change their bindings.
Regards,
Quan
Index: mercury_compile.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.439
diff -u -u -r1.439 mercury_compile.m
--- mercury_compile.m 1 Jun 2007 02:41:20 -0000 1.439
+++ mercury_compile.m 6 Jun 2007 02:17:44 -0000
@@ -4247,7 +4247,7 @@
Analysis = yes,
maybe_write_string(Verbose, "% Analysing regions ...\n", !IO),
maybe_flush_output(Verbose, !IO),
- do_region_analysis(!HLDS),
+ do_region_analysis(!HLDS, !IO),
maybe_write_string(Verbose, "% done.\n", !IO),
maybe_report_stats(Stats, !IO)
;
Index: rbmm.actual_region_arguments.m
===================================================================
RCS file: rbmm.actual_region_arguments.m
diff -N rbmm.actual_region_arguments.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ rbmm.actual_region_arguments.m 6 Jun 2007 05:48:33 -0000
@@ -0,0 +1,255 @@
+% -----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% 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.actual_region_arguments.m.
+% Main author: Quan Phan.
+%
+% This module derives the actual region arguments at each call site in a
+% procedure.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- module transform_hlds.rbmm.actual_region_arguments.
+:- interface.
+
+:- import_module hlds.
+:- import_module hlds.hlds_module.
+:- import_module hlds.hlds_pred.
+:- import_module transform_hlds.rbmm.points_to_graph.
+:- import_module transform_hlds.rbmm.points_to_info.
+:- import_module transform_hlds.rbmm.region_liveness_info.
+:- import_module transform_hlds.smm_common.
+
+:- import_module list.
+:- import_module map.
+
+:- type proc_pp_region_list_table == map(pred_proc_id, pp_region_list_table).
+
+:- type pp_region_list_table == map(program_point, list(rptg_node)).
+
+:- pred record_actual_region_arguments(module_info::in, rpta_info_table::in,
+ proc_region_set_table::in, proc_region_set_table::in,
+ proc_region_set_table::in, proc_pp_region_list_table::out) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module check_hlds.
+:- import_module check_hlds.goal_path.
+:- import_module hlds.hlds_goal.
+:- import_module libs.
+:- import_module libs.compiler_util.
+
+:- import_module set.
+:- import_module string.
+:- import_module svmap.
+
+record_actual_region_arguments(ModuleInfo, RptaInfoTable, ConstantRTable,
+ DeadRTable, BornRTable, ActualRegionArgTable) :-
+ module_info_predids(PredIds, ModuleInfo, _),
+ list.foldl(record_actual_region_arguments_pred(ModuleInfo,
+ RptaInfoTable, ConstantRTable, DeadRTable, BornRTable),
+ PredIds, map.init, ActualRegionArgTable).
+
+:- pred record_actual_region_arguments_pred(module_info::in,
+ rpta_info_table::in, proc_region_set_table::in,
+ proc_region_set_table::in, proc_region_set_table::in, pred_id::in,
+ proc_pp_region_list_table::in, proc_pp_region_list_table::out) is det.
+
+record_actual_region_arguments_pred(ModuleInfo, RptaInfoTable,
+ ConstantRTable, DeadRTable, BornRTable, PredId,
+ !ActualRegionArgTable) :-
+ module_info_pred_info(ModuleInfo, PredId, PredInfo),
+ ProcIds = pred_info_non_imported_procids(PredInfo),
+ list.foldl(record_actual_region_arguments_proc(ModuleInfo, PredId,
+ RptaInfoTable, ConstantRTable, DeadRTable, BornRTable), ProcIds,
+ !ActualRegionArgTable).
+
+:- pred record_actual_region_arguments_proc(module_info::in, pred_id::in,
+ rpta_info_table::in, proc_region_set_table::in,
+ proc_region_set_table::in, proc_region_set_table::in, proc_id::in,
+ proc_pp_region_list_table::in, proc_pp_region_list_table::out) is det.
+
+record_actual_region_arguments_proc(ModuleInfo, PredId, RptaInfoTable,
+ ConstantRTable, DeadRTable, BornRTable, ProcId,
+ !ActualRegionArgTable) :-
+
+ PPId = proc(PredId, ProcId),
+ ( if some_are_special_preds([PPId], ModuleInfo)
+ then true
+ else
+ module_info_proc_info(ModuleInfo, PPId, ProcInfo0),
+ fill_goal_path_slots(ModuleInfo, ProcInfo0, ProcInfo),
+ proc_info_get_goal(ProcInfo, Body),
+ record_actual_region_arguments_goal(ModuleInfo, PPId, RptaInfoTable,
+ ConstantRTable, DeadRTable, BornRTable, Body,
+ map.init, ActualRegionArgProc),
+ svmap.set(PPId, ActualRegionArgProc, !ActualRegionArgTable)
+ ).
+
+:- pred record_actual_region_arguments_goal(module_info::in,
+ pred_proc_id::in, rpta_info_table::in, proc_region_set_table::in,
+ proc_region_set_table::in, proc_region_set_table::in, hlds_goal::in,
+ pp_region_list_table::in, pp_region_list_table::out) is det.
+
+record_actual_region_arguments_goal(ModuleInfo, PPId, RptaInfoTable,
+ ConstantRTable, DeadRTable, BornRTable, Goal,
+ !ActualRegionArgProc) :-
+ Goal = hlds_goal(Expr, Info),
+ record_actual_region_arguments_expr(Expr, Info, ModuleInfo, PPId,
+ RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
+ !ActualRegionArgProc).
+
+:- pred record_actual_region_arguments_expr(hlds_goal_expr::in,
+ hlds_goal_info::in, module_info::in, pred_proc_id::in,
+ rpta_info_table::in, proc_region_set_table::in,
+ proc_region_set_table::in, proc_region_set_table::in,
+ pp_region_list_table::in, pp_region_list_table::out) is det.
+
+record_actual_region_arguments_expr(conj(_, Conjs), _, ModuleInfo, PPId,
+ RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
+ !ActualRegionArgProc) :-
+ list.foldl(record_actual_region_arguments_goal(ModuleInfo, PPId,
+ RptaInfoTable, ConstantRTable, DeadRTable, BornRTable), Conjs,
+ !ActualRegionArgProc).
+
+record_actual_region_arguments_expr(disj(Disjs), _, ModuleInfo, PPId,
+ RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
+ !ActualRegionArgProc) :-
+ list.foldl(record_actual_region_arguments_goal(ModuleInfo, PPId,
+ RptaInfoTable, ConstantRTable, DeadRTable, BornRTable),
+ Disjs, !ActualRegionArgProc).
+
+record_actual_region_arguments_expr(if_then_else(_, If, Then, Else), _,
+ ModuleInfo, PPId, RptaInfoTable, ConstantRTable, DeadRTable,
+ BornRTable, !ActualRegionArgProc) :-
+ record_actual_region_arguments_goal(ModuleInfo, PPId, RptaInfoTable,
+ ConstantRTable, DeadRTable, BornRTable, If, !ActualRegionArgProc),
+ record_actual_region_arguments_goal(ModuleInfo, PPId, RptaInfoTable,
+ ConstantRTable, DeadRTable, BornRTable, Then, !ActualRegionArgProc),
+ record_actual_region_arguments_goal(ModuleInfo, PPId, RptaInfoTable,
+ ConstantRTable, DeadRTable, BornRTable, Else, !ActualRegionArgProc).
+
+record_actual_region_arguments_expr(switch(_, _, Cases), _, ModuleInfo,
+ PPId, RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
+ !ActualRegionArgProc) :-
+ list.foldl(record_actual_region_arguments_case(ModuleInfo, PPId,
+ RptaInfoTable, ConstantRTable, DeadRTable, BornRTable),
+ Cases, !ActualRegionArgProc).
+
+record_actual_region_arguments_expr(generic_call(_, _, _, _), _, _, _, _, _,
+ _, _, !ActualRegionArgProc) :-
+ sorry(this_file,
+ "record_actual_region_arguments_expr: generic_call not handled").
+
+record_actual_region_arguments_expr(call_foreign_proc(_, _, _, _, _, _, _),
+ _, _, _, _, _, _, _, !ActualRegionArgProc) :-
+ sorry(this_file,
+ "record_actual_region_arguments_expr: call_foreign_proc not handled").
+
+record_actual_region_arguments_expr(negation(Goal), _, ModuleInfo, PPId,
+ RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
+ !ActualRegionArgProc) :-
+ record_actual_region_arguments_goal(ModuleInfo, PPId, RptaInfoTable,
+ ConstantRTable, DeadRTable, BornRTable, Goal, !ActualRegionArgProc).
+
+record_actual_region_arguments_expr(unify(_, _, _, _, _), _, _, _, _, _, _,
+ _, !ActualRegionArgProc).
+
+record_actual_region_arguments_expr(scope(_, Goal), _, ModuleInfo, PPId,
+ RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
+ !ActualRegionArgProc) :-
+ record_actual_region_arguments_goal(ModuleInfo, PPId, RptaInfoTable,
+ ConstantRTable, DeadRTable, BornRTable, Goal, !ActualRegionArgProc).
+
+record_actual_region_arguments_expr(shorthand(_), _, _, _, _, _, _, _,
+ !ActualRegionArgProc) :-
+ unexpected(this_file,
+ "record_actual_region_arguments_expr: shorthand not handled").
+
+:- pred record_actual_region_arguments_case(module_info::in,
+ pred_proc_id::in, rpta_info_table::in, proc_region_set_table::in,
+ proc_region_set_table::in, proc_region_set_table::in, case::in,
+ pp_region_list_table::in, pp_region_list_table::out) is det.
+
+record_actual_region_arguments_case(ModuleInfo, PPId, RptaInfoTable,
+ ConstantRTable, DeadRTable, BornRTable, Case, !ActualRegionArgProc) :-
+ Case = case(_, Goal),
+ record_actual_region_arguments_goal(ModuleInfo, PPId, RptaInfoTable,
+ ConstantRTable, DeadRTable, BornRTable, Goal, !ActualRegionArgProc).
+
+record_actual_region_arguments_expr(Expr, Info, ModuleInfo, CallerPPId,
+ RptaInfoTable, ConstantRTable, DeadRTable, BornRTable,
+ !ActualRegionArgProc) :-
+ Expr = plain_call(PredId, ProcId, _, _, _, _),
+ CalleePPId = proc(PredId, ProcId),
+ ( if some_are_special_preds([CalleePPId], ModuleInfo)
+ then true
+ else
+ CallSite = program_point_init(Info),
+ record_actual_region_arguments_call_site(CallerPPId, CallSite,
+ CalleePPId, RptaInfoTable, ConstantRTable, DeadRTable,
+ BornRTable, !ActualRegionArgProc)
+ ).
+
+:- pred record_actual_region_arguments_call_site(pred_proc_id::in,
+ program_point::in, pred_proc_id::in,
+ rpta_info_table::in, proc_region_set_table::in,
+ proc_region_set_table::in, proc_region_set_table::in,
+ pp_region_list_table::in, pp_region_list_table::out) is det.
+
+record_actual_region_arguments_call_site(CallerPPId, CallSite,
+ CalleePPId, RptaInfoTable, ConstantRTable, DeadRTable,
+ BornRTable, !ActualRegionArgProc) :-
+ map.lookup(ConstantRTable, CalleePPId, CalleeConstantR),
+ map.lookup(DeadRTable, CalleePPId, CalleeDeadR),
+ map.lookup(BornRTable, CalleePPId, CalleeBornR),
+
+ map.lookup(RptaInfoTable, CallerPPId, CallerRptaInfo),
+ CallerRptaInfo = rpta_info(_, CallerAlpha),
+ map.lookup(CallerAlpha, CallSite, AlphaAtCallSite),
+
+ % Actual constant region arguments.
+ set.to_sorted_list(CalleeConstantR, LCalleeConstantR),
+ list.foldl(find_actual_param(AlphaAtCallSite), LCalleeConstantR, [],
+ LActualConstantR0),
+ list.reverse(LActualConstantR0, LActualConstantR),
+
+ % Actual dead region arguments.
+ set.to_sorted_list(CalleeDeadR, LCalleeDeadR),
+ list.foldl(find_actual_param(AlphaAtCallSite), LCalleeDeadR, [],
+ LActualDeadR0),
+ list.reverse(LActualDeadR0, LActualDeadR),
+
+ % Actual dead region arguments.
+ set.to_sorted_list(CalleeBornR, LCalleeBornR),
+ list.foldl(find_actual_param(AlphaAtCallSite), LCalleeBornR, [],
+ LActualBornR0),
+ list.reverse(LActualBornR0, LActualBornR),
+
+ % Record in the order: constants, deads, and borns.
+ L = LActualConstantR ++ LActualDeadR ++ LActualBornR,
+ svmap.det_insert(CallSite, L, !ActualRegionArgProc).
+
+:- pred find_actual_param(map(rptg_node, rptg_node)::in, rptg_node::in,
+ list(rptg_node)::in, list(rptg_node)::out) is det.
+
+find_actual_param(Alpha_PP, Formal, Actuals0, Actuals) :-
+ map.lookup(Alpha_PP, Formal, Actual),
+ Actuals = [Actual | Actuals0].
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "rbmm.actual_region_arguments.m".
+
+%-----------------------------------------------------------------------------%
Index: rbmm.condition_renaming.m
===================================================================
RCS file: rbmm.condition_renaming.m
diff -N rbmm.condition_renaming.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ rbmm.condition_renaming.m 6 Jun 2007 01:44:32 -0000
@@ -0,0 +1,958 @@
+%-----------------------------------------------------------------------------%
+% 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.condition_renaming.m.
+% Main author: Quan Phan.
+%
+% If region variables are regular Mercury variables then a region (variable)
+% which is non-local to an if-then-else is not allowed to be created in
+% the condition goal of the if-then-else.
+% This module finds which renaming and reversed renaming are needed at each
+% program point so that the binding of non-local regions in the condition
+% goal of an if-then-else is resolved.
+
+:- module transform_hlds.rbmm.condition_renaming.
+:- interface.
+
+:- import_module hlds.
+:- import_module hlds.hlds_module.
+:- import_module hlds.hlds_pred.
+:- import_module mdbcomp.
+:- import_module mdbcomp.program_representation.
+:- import_module transform_hlds.rbmm.points_to_info.
+:- import_module transform_hlds.rbmm.region_liveness_info.
+:- import_module transform_hlds.rbmm.region_resurrection_renaming.
+
+:- import_module map.
+
+:- type proc_goal_path_regions_table ==
+ map(pred_proc_id, goal_path_regions_table).
+:- type goal_path_regions_table == map(goal_path, region_set).
+
+:- pred collect_non_local_and_in_cond_regions(module_info::in,
+ proc_pp_region_set_table::in, proc_pp_region_set_table::in,
+ proc_goal_path_regions_table::out, proc_goal_path_regions_table::out)
+ is det.
+
+:- pred collect_ite_renamed_regions(proc_goal_path_regions_table::in,
+ proc_goal_path_regions_table::in, proc_goal_path_regions_table::out)
+ is det.
+
+:- pred collect_ite_renaming(module_info::in, rpta_info_table::in,
+ proc_goal_path_regions_table::in, renaming_table::out) is det.
+
+:- pred collect_ite_annotation(proc_goal_path_regions_table::in,
+ execution_path_table::in, rpta_info_table::in, renaming_table::in,
+ renaming_annotation_table::out) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module check_hlds.
+:- import_module check_hlds.goal_path.
+:- import_module hlds.hlds_goal.
+:- import_module libs.
+:- import_module libs.compiler_util.
+:- import_module transform_hlds.rbmm.points_to_graph.
+:- import_module transform_hlds.smm_common.
+
+:- import_module int.
+:- import_module list.
+:- import_module pair.
+:- import_module set.
+:- import_module string.
+:- import_module svmap.
+
+ % This predicate collects two pieces of information.
+ % 1. The non-local regions of if-then-elses.
+ % A region is non-local to an if-then-else if the region
+ % is created in the if-then-else and outlives the scope
+ % of the if-then-else.
+ % 2. The regions which are created (get bound) in the condition
+ % goals of if-then-else.
+ % We will only store information about a procedure if the information
+ % exists. That means, for example, there is no entry from PPId to
+ % empty.
+ %
+ % This information is used to compute the regions which need to be
+ % renamed, i.e., both non-local and created in the condition of an
+ % if-then-else.
+ %
+collect_non_local_and_in_cond_regions(ModuleInfo, LRBeforeTable,
+ LRAfterTable, NonLocalRegionsTable, InCondRegionsTable) :-
+ module_info_predids(PredIds, ModuleInfo, _),
+ list.foldl2(collect_non_local_and_in_cond_regions_pred(ModuleInfo,
+ LRBeforeTable, LRAfterTable), PredIds,
+ map.init, NonLocalRegionsTable, map.init, InCondRegionsTable).
+
+:- pred collect_non_local_and_in_cond_regions_pred(module_info::in,
+ proc_pp_region_set_table::in, proc_pp_region_set_table::in, pred_id::in,
+ proc_goal_path_regions_table::in, proc_goal_path_regions_table::out,
+ proc_goal_path_regions_table::in, proc_goal_path_regions_table::out)
+ is det.
+
+collect_non_local_and_in_cond_regions_pred(ModuleInfo, LRBeforeTable,
+ LRAfterTable, PredId, !NonLocalRegionsTable, !InCondRegionsTable) :-
+ module_info_pred_info(ModuleInfo, PredId, PredInfo),
+ ProcIds = pred_info_non_imported_procids(PredInfo),
+ list.foldl2(collect_non_local_and_in_cond_regions_proc(ModuleInfo,
+ PredId, LRBeforeTable, LRAfterTable), ProcIds,
+ !NonLocalRegionsTable, !InCondRegionsTable).
+
+:- pred collect_non_local_and_in_cond_regions_proc(module_info::in,
+ pred_id::in, proc_pp_region_set_table::in,
+ proc_pp_region_set_table::in, proc_id::in,
+ proc_goal_path_regions_table::in, proc_goal_path_regions_table::out,
+ proc_goal_path_regions_table::in, proc_goal_path_regions_table::out)
+ is det.
+
+collect_non_local_and_in_cond_regions_proc(ModuleInfo, PredId,
+ LRBeforeTable, LRAfterTable, ProcId,
+ !NonLocalRegionsTable, !InCondRegionsTable) :-
+ PPId = proc(PredId, ProcId),
+ ( if some_are_special_preds([PPId], ModuleInfo)
+ then true
+ else
+ module_info_proc_info(ModuleInfo, PPId, ProcInfo0),
+ fill_goal_path_slots(ModuleInfo, ProcInfo0, ProcInfo),
+ proc_info_get_goal(ProcInfo, Goal),
+ map.lookup(LRBeforeTable, PPId, LRBeforeProc),
+ map.lookup(LRAfterTable, PPId, LRAfterProc),
+ collect_non_local_and_in_cond_regions_goal(LRBeforeProc,
+ LRAfterProc, Goal,
+ map.init, NonLocalRegionsProc,
+ map.init, InCondRegionsProc),
+ ( if map.count(NonLocalRegionsProc) = 0
+ then
+ true
+ else
+ svmap.set(PPId, NonLocalRegionsProc,
+ !NonLocalRegionsTable)
+ ),
+ ( if map.count(InCondRegionsProc) = 0
+ then
+ true
+ else
+ svmap.set(PPId, InCondRegionsProc,
+ !InCondRegionsTable)
+ )
+ ).
+
+:- pred collect_non_local_and_in_cond_regions_goal(pp_region_set_table::in,
+ pp_region_set_table::in, hlds_goal::in,
+ goal_path_regions_table::in, goal_path_regions_table::out,
+ goal_path_regions_table::in, goal_path_regions_table::out) is det.
+
+collect_non_local_and_in_cond_regions_goal(LRBeforeProc, LRAfterProc, Goal,
+ !NonLocalRegionsProc, !InCondRegionsProc) :-
+ Goal = hlds_goal(Expr, _),
+ collect_non_local_and_in_cond_regions_expr(LRBeforeProc, LRAfterProc,
+ Expr, !NonLocalRegionsProc, !InCondRegionsProc).
+
+:- pred collect_non_local_and_in_cond_regions_expr(pp_region_set_table::in,
+ pp_region_set_table::in, hlds_goal_expr::in,
+ goal_path_regions_table::in, goal_path_regions_table::out,
+ goal_path_regions_table::in, goal_path_regions_table::out) is det.
+
+collect_non_local_and_in_cond_regions_expr(LRBeforeProc, LRAfterProc,
+ conj(_, Conjs), !NonLocalRegionsProc, !InCondRegionsProc) :-
+ list.foldl2(collect_non_local_and_in_cond_regions_goal(LRBeforeProc,
+ LRAfterProc),
+ Conjs, !NonLocalRegionsProc, !InCondRegionsProc).
+
+collect_non_local_and_in_cond_regions_expr(_, _,
+ plain_call(_, _, _, _, _, _),
+ !NonLocalRegionsProc, !InCondRegionsProc).
+collect_non_local_and_in_cond_regions_expr(_, _, generic_call(_, _, _, _),
+ !NonLocalRegionsProc, !InCondRegionsProc).
+collect_non_local_and_in_cond_regions_expr(_, _,
+ call_foreign_proc(_, _, _, _, _, _, _),
+ !NonLocalRegionsProc, !InCondRegionsProc).
+
+collect_non_local_and_in_cond_regions_expr(LRBeforeProc, LRAfterProc,
+ switch(_, _, Cases), !NonLocalRegionsProc, !InCondRegionsProc) :-
+ list.foldl2(collect_non_local_and_in_cond_regions_case(LRBeforeProc,
+ LRAfterProc),
+ Cases, !NonLocalRegionsProc, !InCondRegionsProc).
+collect_non_local_and_in_cond_regions_expr(LRBeforeProc, LRAfterProc,
+ disj(Disjs), !NonLocalRegionsProc, !InCondRegionsProc) :-
+ list.foldl2(collect_non_local_and_in_cond_regions_goal(LRBeforeProc,
+ LRAfterProc),
+ Disjs, !NonLocalRegionsProc, !InCondRegionsProc).
+collect_non_local_and_in_cond_regions_expr(LRBeforeProc, LRAfterProc,
+ negation(Goal), !NonLocalRegionsProc, !InCondRegionsProc) :-
+ collect_non_local_and_in_cond_regions_goal(LRBeforeProc, LRAfterProc,
+ Goal, !NonLocalRegionsProc, !InCondRegionsProc).
+collect_non_local_and_in_cond_regions_expr(_, _, unify(_, _, _, _, _),
+ !NonLocalRegionsProc, !InCondRegionsProc).
+
+collect_non_local_and_in_cond_regions_expr(LRBeforeProc, LRAfterProc,
+ scope(_, Goal), !NonLocalRegionsProc, !InCondRegionsProc) :-
+ collect_non_local_and_in_cond_regions_goal(LRBeforeProc, LRAfterProc,
+ Goal, !NonLocalRegionsProc, !InCondRegionsProc).
+
+collect_non_local_and_in_cond_regions_expr(LRBeforeProc, LRAfterProc, Expr,
+ !NonLocalRegionProc, !InCondRegionsProc) :-
+ Expr = if_then_else(_, Cond, Then, Else),
+
+ % We only care about regions created inside condition goals.
+ collect_regions_created_in_condition(LRBeforeProc, LRAfterProc, Cond,
+ !InCondRegionsProc),
+
+ % The sets of non_local regions in the (Cond, Then) and in the (Else)
+ % branch are the same, therefore we will only calculate in one of them.
+ % As it is here, we calculate for (Else) with the hope that it is
+ % usually more efficient (only Else compared to both Cond and Then).
+ collect_non_local_and_in_cond_regions_goal(LRBeforeProc, LRAfterProc,
+ Cond, !NonLocalRegionProc, !InCondRegionsProc),
+ collect_non_local_and_in_cond_regions_goal(LRBeforeProc, LRAfterProc,
+ Then, !NonLocalRegionProc, !InCondRegionsProc),
+ collect_non_local_regions_in_ite(LRBeforeProc, LRAfterProc, Else,
+ !NonLocalRegionProc).
+
+collect_non_local_and_in_cond_regions_expr(_, _, shorthand(_),
+ !NonLocalRegionProc, !InCondRegionsProc) :-
+ unexpected(this_file, "collect_non_local_and_in_cond_regions_expr: "
+ ++ "shorthand not handled").
+
+:- pred collect_non_local_and_in_cond_regions_case(pp_region_set_table::in,
+ pp_region_set_table::in, case::in,
+ goal_path_regions_table::in, goal_path_regions_table::out,
+ goal_path_regions_table::in, goal_path_regions_table::out) is det.
+
+collect_non_local_and_in_cond_regions_case(LRBeforeProc, LRAfterProc, Case,
+ !NonLocalRegionProc, !InCondRegionsProc) :-
+ Case = case(_, Goal),
+ collect_non_local_and_in_cond_regions_goal(LRBeforeProc, LRAfterProc,
+ Goal, !NonLocalRegionProc, !InCondRegionsProc).
+
+:- pred collect_non_local_regions_in_ite(pp_region_set_table::in,
+ pp_region_set_table::in, hlds_goal::in, goal_path_regions_table::in,
+ goal_path_regions_table::out) is det.
+
+collect_non_local_regions_in_ite(LRBeforeProc, LRAfterProc, GoalInIte,
+ !NonLocalRegionProc) :-
+ GoalInIte = hlds_goal(Expr, Info),
+ ( if goal_is_atomic(Expr)
+ then
+ ProgPoint = program_point_init(Info),
+ ProgPoint = pp(_, GoalPath),
+ map.lookup(LRBeforeProc, ProgPoint, LRBefore),
+ map.lookup(LRAfterProc, ProgPoint, LRAfter),
+
+ % XXX We may also need VoidVarRegionTable to be included
+ % in RemovedAfter.
+ set.difference(LRBefore, LRAfter, RemovedAfter),
+ set.difference(LRAfter, LRBefore, CreatedBefore),
+
+ record_non_local_regions(GoalPath, CreatedBefore,
+ RemovedAfter, !NonLocalRegionProc)
+ else
+ collect_non_local_regions_in_ite_compound_goal(
+ LRBeforeProc, LRAfterProc, GoalInIte,
+ !NonLocalRegionProc)
+ ).
+
+ % The non-local regions of an if-then-else will be attached to
+ % the goal path to the condition.
+ % Non-local regions of an if-then-else are ones that are created
+ % somewhere inside the if-then-else and not be removed inside it
+ % (i.e., outlive the if-then-else's scope).
+ % If a region is created in an if-then-else, it is created
+ % in both (Cond, Then) and (Else) branches. (Of cource one of them
+ % is in effect at runtime). If it is removed in the if-then-else
+ % then it is also removed in both. Therefore it is enough to
+ % consider either (Cond, Then) or (Else). As said above,
+ % we here choose to calculate for (Else).
+ %
+ % The algorithm is that: at each program point (inside the else),
+ % the non-local set of regions is updated by including the regions
+ % created before or at that program point and excluding those removed
+ % at or after the program point.
+ % Because if-then-else can be nestted, we need to update the
+ % non-local sets of all the surrounding if-then-elses of this
+ % program point.
+ %
+:- pred record_non_local_regions(goal_path::in, region_set::in,
+ region_set::in, goal_path_regions_table::in,
+ goal_path_regions_table::out) is det.
+
+record_non_local_regions([], _, _, !NonLocalRegionProc).
+record_non_local_regions(Path, Created, Removed, !NonLocalRegionProc) :-
+ Path = [Step | Steps],
+ (
+ Step = step_ite_else
+ ->
+ % The current NonLocalRegions are attached to the goal path to
+ % the corresponding condition.
+ PathToCond = [step_ite_cond | Steps],
+ ( if map.search(!.NonLocalRegionProc, PathToCond,
+ NonLocalRegions0)
+ then
+ set.union(NonLocalRegions0, Created,
+ NonLocalRegions1),
+ set.difference(NonLocalRegions1, Removed,
+ NonLocalRegions)
+ else
+ set.difference(Created, Removed,
+ NonLocalRegions)
+ ),
+ % Only record if some non-local region(s) exist.
+ ( if set.empty(NonLocalRegions)
+ then
+ true
+ else
+ svmap.set(PathToCond, NonLocalRegions,
+ !NonLocalRegionProc)
+ )
+ ;
+ true
+ ),
+
+ % Need to update the non-local sets of outer if-then-elses of this
+ % one, if any.
+ record_non_local_regions(Steps, Created, Removed, !NonLocalRegionProc).
+
+:- pred collect_non_local_regions_in_ite_compound_goal(
+ pp_region_set_table::in, pp_region_set_table::in, hlds_goal::in,
+ goal_path_regions_table::in, goal_path_regions_table::out) is det.
+
+collect_non_local_regions_in_ite_compound_goal(LRBeforeProc, LRAfterProc,
+ GoalInIte, !NonLocalRegionProc) :-
+ GoalInIte = hlds_goal(Expr, _),
+ (
+ Expr = conj(_, [Conj | Conjs]),
+ list.foldl(collect_non_local_regions_in_ite(LRBeforeProc,
+ LRAfterProc),
+ [Conj | Conjs], !NonLocalRegionProc)
+ ;
+ Expr = disj([Disj | Disjs]),
+ list.foldl(collect_non_local_regions_in_ite(LRBeforeProc,
+ LRAfterProc),
+ [Disj | Disjs], !NonLocalRegionProc)
+ ;
+ Expr = switch(_, _, Cases),
+ list.foldl(collect_non_local_regions_in_ite_case(LRBeforeProc,
+ LRAfterProc),
+ Cases, !NonLocalRegionProc)
+ ;
+ Expr = negation(Goal),
+ collect_non_local_regions_in_ite(LRBeforeProc, LRAfterProc,
+ Goal, !NonLocalRegionProc)
+ ;
+ Expr = scope(_, Goal),
+ collect_non_local_regions_in_ite(LRBeforeProc, LRAfterProc,
+ Goal, !NonLocalRegionProc)
+ ;
+ Expr = if_then_else(_, Cond, Then, Else),
+ collect_non_local_regions_in_ite(LRBeforeProc, LRAfterProc,
+ Cond, !NonLocalRegionProc),
+ collect_non_local_regions_in_ite(LRBeforeProc, LRAfterProc,
+ Then, !NonLocalRegionProc),
+ collect_non_local_regions_in_ite(LRBeforeProc, LRAfterProc,
+ Else, !NonLocalRegionProc)
+ ;
+ ( Expr = unify(_, _, _, _, _)
+ ; Expr = plain_call(_, _, _, _, _, _)
+ ; Expr = conj(_, [])
+ ; Expr = disj([])
+ ; Expr = call_foreign_proc(_, _, _, _, _, _, _)
+ ; Expr = generic_call(_, _, _, _)
+ ; Expr = shorthand(_)
+ ),
+ unexpected(this_file,
+ "collect_non_local_regions_in_ite_compound_goal: "
+ ++ "encountered atomic or unsupported goal")
+ ).
+
+:- pred collect_non_local_regions_in_ite_case(pp_region_set_table::in,
+ pp_region_set_table::in, case::in, goal_path_regions_table::in,
+ goal_path_regions_table::out) is det.
+
+collect_non_local_regions_in_ite_case(LRBeforeProc, LRAfterProc, Case,
+ !NonLocalRegionProc) :-
+ Case = case(_, Goal),
+ collect_non_local_regions_in_ite(LRBeforeProc, LRAfterProc, Goal,
+ !NonLocalRegionProc).
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+%-----------------------------------------------------------------------------%
+%
+% Collect regions created inside condition goals of if-then-elses.
+%
+
+ % The process here is very similar to that of
+ % collect_non_local_regions_in_ite predicate.
+ % The difference is that this predicate is used only in the scope of
+ % a condition goal.
+ %
+:- pred collect_regions_created_in_condition(pp_region_set_table::in,
+ pp_region_set_table::in, hlds_goal::in, goal_path_regions_table::in,
+ goal_path_regions_table::out) is det.
+
+collect_regions_created_in_condition(LRBeforeProc, LRAfterProc, Cond,
+ !InCondRegionsProc) :-
+ Cond = hlds_goal(Expr, Info),
+ ( if goal_is_atomic(Expr)
+ then
+ ProgPoint = program_point_init(Info),
+ ProgPoint = pp(_, GoalPath),
+ map.lookup(LRBeforeProc, ProgPoint, LRBefore),
+ map.lookup(LRAfterProc, ProgPoint, LRAfter),
+
+ set.difference(LRAfter, LRBefore, Created),
+ record_regions_created_in_condition(GoalPath, Created,
+ !InCondRegionsProc)
+ else
+ collect_regions_created_in_condition_compound_goal(
+ LRBeforeProc, LRAfterProc, Cond,
+ !InCondRegionsProc)
+ ).
+
+ % The regions created inside the condition of an if-then-else will
+ % be attached to the goal path to the condition.
+ %
+ % We need to update the sets of all the conditions surrounding this
+ % program point.
+ %
+:- pred record_regions_created_in_condition(goal_path::in, region_set::in,
+ goal_path_regions_table::in, goal_path_regions_table::out) is det.
+
+record_regions_created_in_condition([], _, !InCondRegionsProc).
+record_regions_created_in_condition(Path, Created, !InCondRegionsProc) :-
+ Path = [Step | Steps],
+ (
+ Step = step_ite_cond
+ ->
+ ( if map.search(!.InCondRegionsProc, Path,
+ InCondRegions0)
+ then
+ set.union(InCondRegions0, Created,
+ InCondRegions)
+ else
+ InCondRegions = Created
+ ),
+ % Only record if the some region(s) is actually created inside
+ % the condition.
+ ( if set.empty(InCondRegions)
+ then
+ true
+ else
+ svmap.set(Path, InCondRegions,
+ !InCondRegionsProc)
+ )
+ ;
+ true
+ ),
+ record_regions_created_in_condition(Steps, Created,
+ !InCondRegionsProc).
+
+:- pred collect_regions_created_in_condition_compound_goal(
+ pp_region_set_table::in, pp_region_set_table::in, hlds_goal::in,
+ goal_path_regions_table::in, goal_path_regions_table::out) is det.
+
+collect_regions_created_in_condition_compound_goal(LRBeforeProc,
+ LRAfterProc, GoalInIte, !InCondRegionsProc) :-
+ GoalInIte = hlds_goal(Expr, _),
+ (
+ Expr = conj(_, [Conj | Conjs]),
+ list.foldl(collect_regions_created_in_condition(LRBeforeProc,
+ LRAfterProc), [Conj | Conjs], !InCondRegionsProc)
+ ;
+ Expr = disj([Disj | Disjs]),
+ list.foldl(collect_regions_created_in_condition(LRBeforeProc,
+ LRAfterProc), [Disj | Disjs], !InCondRegionsProc)
+ ;
+ Expr = switch(_, _, Cases),
+ list.foldl(
+ collect_regions_created_in_condition_case(LRBeforeProc,
+ LRAfterProc),
+ Cases, !InCondRegionsProc)
+ ;
+ Expr = negation(Goal),
+ collect_regions_created_in_condition(LRBeforeProc,
+ LRAfterProc, Goal, !InCondRegionsProc)
+ ;
+ Expr = scope(_, Goal),
+ collect_regions_created_in_condition(LRBeforeProc,
+ LRAfterProc, Goal, !InCondRegionsProc)
+ ;
+ Expr = if_then_else(_, Cond, Then, Else),
+ collect_regions_created_in_condition(LRBeforeProc, LRAfterProc,
+ Cond, !InCondRegionsProc),
+ collect_regions_created_in_condition(LRBeforeProc, LRAfterProc,
+ Then, !InCondRegionsProc),
+ collect_regions_created_in_condition(LRBeforeProc, LRAfterProc,
+ Else, !InCondRegionsProc)
+ ;
+ ( Expr = unify(_, _, _, _, _)
+ ; Expr = plain_call(_, _, _, _, _, _)
+ ; Expr = conj(_, [])
+ ; Expr = disj([])
+ ; Expr = call_foreign_proc(_, _, _, _, _, _, _)
+ ; Expr = generic_call(_, _, _, _)
+ ; Expr = shorthand(_)
+ ),
+ unexpected(this_file,
+ "collect_regions_created_in_condition_compound_goal: "
+ ++ "encountered atomic or unsupported goal")
+ ).
+
+:- pred collect_regions_created_in_condition_case(pp_region_set_table::in,
+ pp_region_set_table::in, case::in, goal_path_regions_table::in,
+ goal_path_regions_table::out) is det.
+
+collect_regions_created_in_condition_case(LRBeforeProc, LRAfterProc, Case,
+ !InCondRegionsProc) :-
+ Case = case(_, Goal),
+ collect_regions_created_in_condition(LRBeforeProc, LRAfterProc, Goal,
+ !InCondRegionsProc).
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+%-----------------------------------------------------------------------------%
+%
+% Collect regions that need to be renamed, i.e., both created in a condition
+% goal and non-local to the corresponding if-then-else.
+%
+
+ % After having the 2 pieces of information calculated above, this step
+ % is simple. The only thing to note here is that we will only store
+ % information for a procedure when the information exists.
+ % This means that a procedure in which no renaming is required will not
+ % be in the resulting table.
+ %
+collect_ite_renamed_regions(InCondRegionsTable, NonLocalRegionsTable,
+ IteRenamedRegionsTable) :-
+ map.foldl(collect_ite_renamed_regions_proc(NonLocalRegionsTable),
+ InCondRegionsTable, map.init, IteRenamedRegionsTable).
+
+:- pred collect_ite_renamed_regions_proc(proc_goal_path_regions_table::in,
+ pred_proc_id::in, goal_path_regions_table::in,
+ proc_goal_path_regions_table::in, proc_goal_path_regions_table::out)
+ is det.
+
+collect_ite_renamed_regions_proc(NonLocalRegionsTable, PPId,
+ InCondRegionsProc, !IteRenamedRegionTable) :-
+ ( if map.search(NonLocalRegionsTable, PPId, NonLocalRegionsProc)
+ then
+ map.foldl(collect_ite_renamed_regions_ite(
+ NonLocalRegionsProc),
+ InCondRegionsProc,
+ map.init, IteRenamedRegionProc),
+ ( if map.count(IteRenamedRegionProc) = 0
+ then
+ true
+ else
+ svmap.set(PPId, IteRenamedRegionProc,
+ !IteRenamedRegionTable)
+ )
+ else
+ true
+ ).
+
+:- pred collect_ite_renamed_regions_ite(goal_path_regions_table::in,
+ goal_path::in, region_set::in,
+ goal_path_regions_table::in, goal_path_regions_table::out) is det.
+
+collect_ite_renamed_regions_ite(NonLocalRegionsProc, PathToCond,
+ InCondRegions, !IteRenamedRegionProc) :-
+ ( if map.search(NonLocalRegionsProc, PathToCond, NonLocalRegions)
+ then
+ set.intersect(NonLocalRegions, InCondRegions,
+ RenamedRegions),
+ ( if set.empty(RenamedRegions)
+ then
+ true
+ else
+ svmap.set(PathToCond, RenamedRegions,
+ !IteRenamedRegionProc)
+ )
+ else
+ true
+ ).
+
+%-----------------------------------------------------------------------------%
+%
+% Derive necessary renaming.
+%
+
+ % This predicate ONLY traverses the procedures which requires
+ % condition renaming and for each condition goal in such a procedure
+ % it introduces the necessary renamings.
+ % The renaming information is stored in the form:
+ % a program point (in the condition goal) --> necessary renaming at
+ % the point.
+ % A new name for a region (variable) at a program point is:
+ % RegionName_ite_Number, where Number is the number of condition goals
+ % to which the program point belongs.
+ %
+collect_ite_renaming(ModuleInfo, RptaInfoTable, IteRenamedRegionTable,
+ IteRenamingTable) :-
+ map.foldl(collect_ite_renaming_proc(ModuleInfo, RptaInfoTable),
+ IteRenamedRegionTable, map.init, IteRenamingTable).
+
+:- pred collect_ite_renaming_proc(module_info::in, rpta_info_table::in,
+ pred_proc_id::in, goal_path_regions_table::in,
+ renaming_table::in, renaming_table::out) is det.
+
+collect_ite_renaming_proc(ModuleInfo, RptaInfoTable,
+ PPId, IteRenamedRegionProc, !IteRenamingTable) :-
+ module_info_proc_info(ModuleInfo, PPId, ProcInfo0),
+ fill_goal_path_slots(ModuleInfo, ProcInfo0, ProcInfo),
+ proc_info_get_goal(ProcInfo, Goal),
+ map.lookup(RptaInfoTable, PPId, RptaInfo),
+ RptaInfo = rpta_info(Graph, _),
+ collect_ite_renaming_goal(IteRenamedRegionProc, Graph, Goal,
+ map.init, IteRenamingProc),
+ svmap.set(PPId, IteRenamingProc, !IteRenamingTable).
+
+:- pred collect_ite_renaming_goal(goal_path_regions_table::in,
+ rpt_graph::in, hlds_goal::in, renaming_proc::in,
+ renaming_proc::out) is det.
+
+collect_ite_renaming_goal(IteRenamedRegionProc, Graph, Goal,
+ !IteRenamingProc) :-
+ Goal = hlds_goal(Expr, _),
+ collect_ite_renaming_expr(Expr, IteRenamedRegionProc, Graph,
+ !IteRenamingProc).
+
+:- pred collect_ite_renaming_expr(hlds_goal_expr::in,
+ goal_path_regions_table::in, rpt_graph::in, renaming_proc::in,
+ renaming_proc::out) is det.
+
+collect_ite_renaming_expr(conj(_, Conjs), IteRenamedRegionProc,
+ Graph, !IteRenamingProc) :-
+ list.foldl(collect_ite_renaming_goal(IteRenamedRegionProc, Graph),
+ Conjs, !IteRenamingProc).
+
+collect_ite_renaming_expr(plain_call(_, _, _, _, _, _), _, _,
+ !IteRenamingProc).
+collect_ite_renaming_expr(generic_call(_, _, _, _), _, _,
+ !IteRenamingProc).
+collect_ite_renaming_expr(call_foreign_proc(_, _, _, _, _, _, _),
+ _, _, !IteRenamingProc).
+
+collect_ite_renaming_expr(switch(_, _, Cases), IteRenamedRegionProc,
+ Graph, !IteRenamingProc) :-
+ list.foldl(
+ collect_ite_renaming_case(IteRenamedRegionProc, Graph),
+ Cases, !IteRenamingProc).
+collect_ite_renaming_expr(disj(Disjs), IteRenamedRegionProc, Graph,
+ !IteRenamingProc) :-
+ list.foldl(
+ collect_ite_renaming_goal(IteRenamedRegionProc, Graph),
+ Disjs, !IteRenamingProc).
+collect_ite_renaming_expr(negation(Goal), IteRenamedRegionProc, Graph,
+ !IteRenamingProc) :-
+ collect_ite_renaming_goal(IteRenamedRegionProc, Graph, Goal,
+ !IteRenamingProc).
+collect_ite_renaming_expr(unify(_, _, _, _, _), _, _, !IteRenamingProc).
+
+collect_ite_renaming_expr(scope(_, Goal), IteRenamedRegionProc,
+ Graph, !IteRenamingProc) :-
+ collect_ite_renaming_goal(IteRenamedRegionProc, Graph, Goal,
+ !IteRenamingProc).
+
+collect_ite_renaming_expr(shorthand(_), _, _, !IteRenamingProc) :-
+ unexpected(this_file,
+ "collect_ite_renaming_expr: shorthand not handled").
+
+collect_ite_renaming_expr(Expr, IteRenamedRegionProc, Graph,
+ !IteRenamingProc) :-
+ Expr = if_then_else(_, Cond, Then, Else),
+
+ % Renaming for if-then-else only happens in condition goals.
+ collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph, Cond,
+ !IteRenamingProc),
+
+ collect_ite_renaming_goal(IteRenamedRegionProc, Graph, Then,
+ !IteRenamingProc),
+ collect_ite_renaming_goal(IteRenamedRegionProc, Graph, Else,
+ !IteRenamingProc).
+
+:- pred collect_ite_renaming_case(goal_path_regions_table::in,
+ rpt_graph::in, case::in, renaming_proc::in,
+ renaming_proc::out) is det.
+
+collect_ite_renaming_case(IteRenamedRegionProc, Graph, Case,
+ !IteRenamingProc) :-
+ Case = case(_, Goal),
+ collect_ite_renaming_goal(IteRenamedRegionProc, Graph, Goal,
+ !IteRenamingProc).
+
+ % Introduce renaming for each program point in a condition goal.
+ %
+:- pred collect_ite_renaming_in_condition(
+ goal_path_regions_table::in, rpt_graph::in, hlds_goal::in,
+ renaming_proc::in, renaming_proc::out) is det.
+
+collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph, Cond,
+ !IteRenamingProc) :-
+ Cond = hlds_goal(Expr, Info),
+ ( if goal_is_atomic(Expr)
+ then
+ ProgPoint = program_point_init(Info),
+ % It is enough to look for the regions to be renamed
+ % at the closest condition because if a region is
+ % to be renamed for a compounding if-then-else of the
+ % closest if-then-else then it also needs to be renamed
+ % for the closest if-then-else.
+ ProgPoint = pp(_, GoalPath),
+ get_closest_condition_in_goal_path(GoalPath,
+ PathToClosestCond, 0, HowMany),
+ ( if map.search(IteRenamedRegionProc,
+ PathToClosestCond,
+ RenamedRegion)
+ then
+ set.fold(record_ite_renaming(ProgPoint,
+ HowMany, Graph),
+ RenamedRegion, !IteRenamingProc)
+ else
+ % No region needs to be renamed due to
+ % if-then-else covering this program
+ % point.
+ true
+ )
+ else
+ collect_ite_renaming_in_condition_compound_goal(
+ IteRenamedRegionProc, Graph, Cond,
+ !IteRenamingProc)
+ ).
+
+ % A renaming is of the form: R --> R_ite_HowMany.
+ %
+:- pred record_ite_renaming(program_point::in, int::in, rpt_graph::in,
+ rptg_node::in, renaming_proc::in, renaming_proc::out) is det.
+
+record_ite_renaming(ProgPoint, HowMany, Graph, Region, !IteRenamingProc) :-
+ RegName = rptg_lookup_region_name(Graph, Region),
+ NewName = RegName ++ "_ite_" ++ string.int_to_string(HowMany),
+ ( if map.search(!.IteRenamingProc, ProgPoint, IteRenaming0)
+ then
+ svmap.set(RegName, NewName, IteRenaming0, IteRenaming)
+ else
+ svmap.set(RegName, NewName, map.init, IteRenaming)
+ ),
+ svmap.set(ProgPoint, IteRenaming, !IteRenamingProc).
+
+:- pred collect_ite_renaming_in_condition_compound_goal(
+ goal_path_regions_table::in, rpt_graph::in, hlds_goal::in,
+ renaming_proc::in, renaming_proc::out) is det.
+
+collect_ite_renaming_in_condition_compound_goal(IteRenamedRegionProc,
+ Graph, GoalInCond, !IteRenamingProc) :-
+ GoalInCond = hlds_goal(Expr, _),
+ (
+ Expr = conj(_, [Conj | Conjs]),
+ list.foldl(collect_ite_renaming_in_condition(
+ IteRenamedRegionProc, Graph), [Conj | Conjs],
+ !IteRenamingProc)
+ ;
+ Expr = disj([Disj | Disjs]),
+ list.foldl(collect_ite_renaming_in_condition(
+ IteRenamedRegionProc, Graph), [Disj | Disjs],
+ !IteRenamingProc)
+ ;
+ Expr = switch(_, _, Cases),
+ list.foldl(
+ collect_ite_renaming_in_condition_case(
+ IteRenamedRegionProc, Graph), Cases,
+ !IteRenamingProc)
+ ;
+ Expr = negation(Goal),
+ collect_ite_renaming_in_condition(IteRenamedRegionProc,
+ Graph, Goal, !IteRenamingProc)
+ ;
+ Expr = scope(_, Goal),
+ collect_ite_renaming_in_condition(IteRenamedRegionProc,
+ Graph, Goal, !IteRenamingProc)
+ ;
+ Expr = if_then_else(_, Cond, Then, Else),
+ collect_ite_renaming_in_condition(IteRenamedRegionProc,
+ Graph, Cond, !IteRenamingProc),
+ collect_ite_renaming_in_condition(IteRenamedRegionProc,
+ Graph, Then, !IteRenamingProc),
+ collect_ite_renaming_in_condition(IteRenamedRegionProc,
+ Graph, Else, !IteRenamingProc)
+ ;
+ ( Expr = unify(_, _, _, _, _)
+ ; Expr = plain_call(_, _, _, _, _, _)
+ ; Expr = conj(_, [])
+ ; Expr = disj([])
+ ; Expr = call_foreign_proc(_, _, _, _, _, _, _)
+ ; Expr = generic_call(_, _, _, _)
+ ; Expr = shorthand(_)
+ ),
+ unexpected(this_file,
+ "collect_ite_renaming_in_condition_compound_goal: "
+ ++ "encountered atomic or unsupported goal")
+ ).
+
+:- pred collect_ite_renaming_in_condition_case(
+ goal_path_regions_table::in, rpt_graph::in, case::in,
+ renaming_proc::in, renaming_proc::out) is det.
+
+collect_ite_renaming_in_condition_case(IteRenamedRegionProc, Graph, Case,
+ !IteRenamingProc) :-
+ Case = case(_, Goal),
+ collect_ite_renaming_in_condition(IteRenamedRegionProc, Graph, Goal,
+ !IteRenamingProc).
+
+ % This predicate receives a goal path (to some goal) and returns
+ % the subpath to the closest condition containing the goal. It also
+ % returns the number of conditions that contain the goal.
+ % If the goal is in no condition, the output path is empty.
+ % e.g., ( if
+ % ( if
+ % goal
+ % ...
+ % then HowMany is 2.
+ %
+:- pred get_closest_condition_in_goal_path(goal_path::in,
+ goal_path::out, int::in, int::out) is det.
+get_closest_condition_in_goal_path([], [], !HowMany).
+get_closest_condition_in_goal_path([Step | Steps], PathToCond, !HowMany) :-
+ ( if Step = step_ite_cond
+ then
+ PathToCond = [Step | Steps],
+ get_closest_condition_in_goal_path(Steps, _, !.HowMany, HowMany),
+ !:HowMany = HowMany + 1
+ else
+ get_closest_condition_in_goal_path(Steps, PathToCond, !HowMany)
+ ).
+
+%-----------------------------------------------------------------------------%
+%
+% Derive necessary reversed renaming.
+%
+
+ % In the then branch of an if-then-else in which renaming happens we
+ % need to introduce reversed renaming annotation in the form of
+ % assignments, e.g., if R is renamed to R_ite_1 in the condition
+ % then we add R = R_ite_1 in the then branch.
+ % Because the if-then-else can lie inside the condition goals of
+ % other if-then-elses, we need to apply the renaming at the
+ % program point where the annotation is attached.
+ % E.g., At the point renaming R --> R_ite_2 exists, then the
+ % added annotation is R_ite_2 = R_ite_1.
+ %
+ % This predicate will also traverse only procedures in which renaming
+ % happens. For each Condition where renaming happens,
+ % it finds the first program point in the corresponding Then and
+ % introduces the reversed renaming annotation before that ponit.
+ %
+collect_ite_annotation(IteRenamedRegionTable, ExecPathTable,
+ RptaInfoTable, IteRenamingTable, IteAnnotationTable) :-
+ map.foldl(collect_ite_annotation_proc(ExecPathTable, RptaInfoTable,
+ IteRenamingTable),
+ IteRenamedRegionTable, map.init, IteAnnotationTable).
+
+:- pred collect_ite_annotation_proc(execution_path_table::in,
+ rpta_info_table::in, renaming_table::in, pred_proc_id::in,
+ goal_path_regions_table::in,
+ renaming_annotation_table::in, renaming_annotation_table::out) is det.
+
+collect_ite_annotation_proc(ExecPathTable, RptaInfoTable, IteRenamingTable,
+ PPId, IteRenamedRegionProc, !IteAnnotationTable) :-
+ map.lookup(ExecPathTable, PPId, ExecPaths),
+ map.lookup(RptaInfoTable, PPId, RptaInfo),
+ map.lookup(IteRenamingTable, PPId, IteRenamingProc),
+ RptaInfo = rpta_info(Graph, _),
+ map.foldl(collect_ite_annotation_region_set(ExecPaths, Graph,
+ IteRenamingProc),
+ IteRenamedRegionProc, map.init, IteAnnotationProc),
+ svmap.set(PPId, IteAnnotationProc, !IteAnnotationTable).
+
+:- pred collect_ite_annotation_region_set(list(execution_path)::in,
+ rpt_graph::in, renaming_proc::in, goal_path::in, region_set::in,
+ renaming_annotation_proc::in, renaming_annotation_proc::out) is det.
+
+collect_ite_annotation_region_set(ExecPaths, Graph, IteRenamingProc,
+ PathToCond, RenamedRegions, !IteAnnotationProc) :-
+ (
+ PathToCond = [],
+ unexpected(this_file,
+ "collect_ite_annotation_region_set: " ++
+ "empty path to condition.")
+ ;
+ PathToCond = [_ | Steps],
+ PathToThen = [step_ite_then | Steps],
+ get_closest_condition_in_goal_path(PathToCond, _, 0, HowMany),
+ list.foldl(collect_ite_annotation_exec_path(Graph,
+ IteRenamingProc, PathToThen,
+ RenamedRegions, HowMany), ExecPaths,
+ !IteAnnotationProc)
+ ).
+
+:- pred collect_ite_annotation_exec_path(rpt_graph::in,
+ renaming_proc::in, goal_path::in,
+ region_set::in, int::in, execution_path::in,
+ renaming_annotation_proc::in, renaming_annotation_proc::out) is det.
+
+collect_ite_annotation_exec_path(_, _, _, _, _, [], !IteAnnotationProc).
+collect_ite_annotation_exec_path(Graph, IteRenamingProc, PathToThen,
+ RenamedRegions, HowMany,
+ [ProgPoint - _ | ProgPoint_Goals], !IteAnnotationProc) :-
+ ProgPoint = pp(_, GoalPath),
+ ( if list.append(_, PathToThen, GoalPath)
+ then
+ % This is the first goal in the corresponding then
+ % branch, we need to introduce reversed renaming at
+ % this point.
+ set.fold(introduce_reversed_renaming(Graph, ProgPoint,
+ IteRenamingProc, HowMany),
+ RenamedRegions, !IteAnnotationProc)
+ else
+ collect_ite_annotation_exec_path(Graph, IteRenamingProc,
+ PathToThen, RenamedRegions, HowMany,
+ ProgPoint_Goals, !IteAnnotationProc)
+ ).
+
+ % The reversed renaming annotation is in the form: R = R_ite_HowMany.
+ % The annotation is attached to the program point but actually means
+ % to be added before the program point.
+ % If there exists a renaming at the program point related to R, e.g.,
+ % R --> R_1, then the annotation is R_1 = R_ite_HowMany.
+ %
+:- pred introduce_reversed_renaming(rpt_graph::in, program_point::in,
+ renaming_proc::in, int::in, rptg_node::in,
+ renaming_annotation_proc::in, renaming_annotation_proc::out) is det.
+
+introduce_reversed_renaming(Graph, ProgPoint, IteRenamingProc,
+ HowMany, RenamedRegion, !IteAnnotationProc) :-
+ RegName = rptg_lookup_region_name(Graph, RenamedRegion),
+ RightHand =
+ " = " ++ RegName ++ "_ite_" ++ string.int_to_string(HowMany),
+ ( if map.search(IteRenamingProc, ProgPoint, Renaming)
+ then
+ ( if map.search(Renaming, RegName, RenameTo)
+ then
+ Anno = RenameTo ++ RightHand
+ else
+ Anno = RegName ++ RightHand
+ )
+ else
+ % No renaming exists at this program point.
+ Anno = RegName ++ RightHand
+ ),
+ record_annotation(ProgPoint, Anno, !IteAnnotationProc).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "rbmm.condition_renaming.m".
+
+%-----------------------------------------------------------------------------%
+
Index: rbmm.execution_path.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.execution_path.m,v
retrieving revision 1.2
diff -u -u -r1.2 rbmm.execution_path.m
--- rbmm.execution_path.m 23 May 2007 09:41:43 -0000 1.2
+++ rbmm.execution_path.m 3 Jun 2007 11:56:39 -0000
@@ -134,15 +134,15 @@
execution_paths_covered_compound_goal(ProcInfo, CompoundGoal, !ExecPaths) :-
CompoundGoal = hlds_goal(Expr, _),
(
- Expr = conj(_ConjType, [Goal | Goals]),
- execution_paths_covered_conj(ProcInfo, [Goal | Goals], !ExecPaths)
+ Expr = conj(_ConjType, [Conj | Conjs]),
+ execution_paths_covered_conj(ProcInfo, [Conj | Conjs], !ExecPaths)
;
Expr = switch(_, _, Cases),
execution_paths_covered_cases(ProcInfo, CompoundGoal, Cases,
!ExecPaths)
;
- Expr = disj([Goal | Goals]),
- execution_paths_covered_disj(ProcInfo, [Goal | Goals],
+ Expr = disj([Disj | Disjs]),
+ execution_paths_covered_disj(ProcInfo, [Disj | Disjs],
!ExecPaths)
;
Expr = negation(Goal),
Index: rbmm.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/rbmm.m,v
retrieving revision 1.2
diff -u -u -r1.2 rbmm.m
--- rbmm.m 23 May 2007 09:41:45 -0000 1.2
+++ rbmm.m 6 Jun 2007 05:57:13 -0000
@@ -1,5 +1,5 @@
%-----------------------------------------------------------------------------%
-% Vim: ft=Mercury ts=4 sw=4
+% 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
@@ -16,6 +16,8 @@
:- module transform_hlds.rbmm.
:- interface.
+:- include_module actual_region_arguments.
+:- include_module condition_renaming.
:- include_module execution_path.
:- include_module interproc_region_lifetime.
:- include_module live_region_analysis.
@@ -25,49 +27,79 @@
:- include_module points_to_info.
:- include_module region_instruction.
:- include_module region_liveness_info.
+:- include_module region_resurrection_renaming.
:- import_module hlds.
:- import_module hlds.hlds_module.
+:- import_module io.
%-----------------------------------------------------------------------------%
-:- pred do_region_analysis(module_info::in, module_info::out) is det.
+:- pred do_region_analysis(module_info::in, module_info::out,
+ io::di, io::uo) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
+:- import_module transform_hlds.rbmm.actual_region_arguments.
+:- import_module transform_hlds.rbmm.condition_renaming.
:- import_module transform_hlds.rbmm.execution_path.
:- import_module transform_hlds.rbmm.interproc_region_lifetime.
:- import_module transform_hlds.rbmm.live_region_analysis.
:- import_module transform_hlds.rbmm.live_variable_analysis.
:- import_module transform_hlds.rbmm.points_to_analysis.
:- import_module transform_hlds.rbmm.region_instruction.
-
+:- import_module transform_hlds.rbmm.region_resurrection_renaming.
%-----------------------------------------------------------------------------%
-do_region_analysis(!ModuleInfo) :-
+do_region_analysis(!ModuleInfo, !IO) :-
region_points_to_analysis(RptaInfoTable, !ModuleInfo),
execution_path_analysis(!.ModuleInfo, ExecPathTable),
live_variable_analysis(!.ModuleInfo, ExecPathTable, LVBeforeTable,
LVAfterTable, VoidVarTable),
live_region_analysis(!.ModuleInfo, RptaInfoTable,
- LVBeforeTable, LVAfterTable, VoidVarTable,
- LRBeforeTable0, LRAfterTable0, VoidVarRegionTable0,
- InputRTable, OutputRTable, BornRTable0, DeadRTable0, LocalRTable0),
+ LVBeforeTable, LVAfterTable, VoidVarTable, LRBeforeTable0,
+ LRAfterTable0, VoidVarRegionTable0, InputRTable, OutputRTable,
+ BornRTable0, DeadRTable0, LocalRTable0),
compute_interproc_region_lifetime(!.ModuleInfo, RptaInfoTable,
ExecPathTable, LRBeforeTable0, LRAfterTable0, InputRTable,
- OutputRTable, ConstantRTable0, BornRTable0, BornRTable1,
- DeadRTable0, DeadRTable1),
+ OutputRTable, ConstantRTable0, BornRTable0, BornRTable1,
+ DeadRTable0, DeadRTable1),
ignore_primitive_regions(!.ModuleInfo, RptaInfoTable,
BornRTable1, BornRTable, DeadRTable1, DeadRTable,
- ConstantRTable0, _ConstantRTable, LocalRTable0, LocalRTable,
- LRBeforeTable0, LRBeforeTable, LRAfterTable0, LRAfterTable,
- VoidVarRegionTable0, VoidVarRegionTable),
+ ConstantRTable0, ConstantRTable, LocalRTable0, LocalRTable,
+ LRBeforeTable0, LRBeforeTable, LRAfterTable0, LRAfterTable,
+ VoidVarRegionTable0, VoidVarRegionTable),
transform(!.ModuleInfo, RptaInfoTable, ExecPathTable,
LRBeforeTable, LRAfterTable, VoidVarRegionTable, BornRTable,
- DeadRTable, LocalRTable, _AnnotationTable).
+ DeadRTable, LocalRTable, _AnnotationTable),
+
+ record_actual_region_arguments(!.ModuleInfo, RptaInfoTable,
+ ConstantRTable, DeadRTable, BornRTable,
+ _ActualRegionArgumentTable),
+
+ compute_resurrection_paths(ExecPathTable, LRBeforeTable, LRAfterTable,
+ BornRTable, LocalRTable, CreatedBeforeTable,
+ ResurrectionPathTable),
+ collect_region_resurrection_renaming(CreatedBeforeTable, LocalRTable,
+ RptaInfoTable, ResurrectionPathTable, ResurrectionRenameTable),
+ collect_join_points(ResurrectionRenameTable, ExecPathTable,
+ JoinPointTable),
+ collect_renaming_and_annotation(ResurrectionRenameTable, JoinPointTable,
+ LRBeforeTable, BornRTable, RptaInfoTable, ResurrectionPathTable,
+ ExecPathTable, _RenamingAnnotationTable, _RenamingTable),
+
+ collect_non_local_and_in_cond_regions(!.ModuleInfo, LRBeforeTable,
+ LRAfterTable, LocalRegionsTable, InCondRegionsTable),
+ collect_ite_renamed_regions(LocalRegionsTable, InCondRegionsTable,
+ RenamedRegionsTable),
+ collect_ite_renaming(!.ModuleInfo, RptaInfoTable, RenamedRegionsTable,
+ IteRenamingTable),
+ collect_ite_annotation(RenamedRegionsTable, ExecPathTable,
+ RptaInfoTable, IteRenamingTable, _IteAnnoTable).
+
%-----------------------------------------------------------------------------%
:- end_module transform_hlds.rbmm.
Index: rbmm.region_instruction.m
===================================================================
RCS file:
/home/mercury/mercury1/repository/mercury/compiler/rbmm.region_instruction.m,v
retrieving revision 1.1
diff -u -u -r1.1 rbmm.region_instruction.m
--- rbmm.region_instruction.m 23 May 2007 00:17:21 -0000 1.1
+++ rbmm.region_instruction.m 5 Jun 2007 07:04:31 -0000
@@ -232,30 +232,31 @@
region_set::in, rpta_info::in, proc_region_set_table::in,
annotation_proc::in, annotation_proc::out) is det.
-transformation_rule_1(Expr, ProgPoint, ToBeCreatedAndAllowed, RptaInfo,
+transformation_rule_1(Expr, ProgPoint, ToBeCreatedAndAllowed, CallerRptaInfo,
BornRTable, !AnnotationProc) :-
(
- Expr = plain_call(PredId_q, ProcId_q, _, _, _, _)
+ Expr = plain_call(CalleePredId, CalleeProcId, _, _, _, _)
->
- PPId_q = proc(PredId_q, ProcId_q),
- RptaInfo = rpta_info(Graph, AlphaMapping),
+ CalleePPId = proc(CalleePredId, CalleeProcId),
+ CallerRptaInfo = rpta_info(CallerGraph, AlphaMapping),
( if
% Currently we do not collect BornR for non-defined-in-module
% procedure, so if we cannot find one here then q is an
% imported.
- map.search(BornRTable, PPId_q, _)
+ map.search(BornRTable, CalleePPId, _)
then
map.lookup(AlphaMapping, ProgPoint, AlphaAtProgPoint),
- map.lookup(BornRTable, PPId_q, BornR_q),
+ map.lookup(BornRTable, CalleePPId, CalleeBornR),
map.foldl(process_mapping_rule_1(ProgPoint, ToBeCreatedAndAllowed,
- BornR_q, Graph), AlphaAtProgPoint, !AnnotationProc)
+ CalleeBornR, CallerGraph), AlphaAtProgPoint, !AnnotationProc)
else
% q is from an imported module, therefore we consider
% BornR of q empty, so just create whatever regions becoming
% live provided that they are in BornR or LocalR, i.e., p is
% allowed to create them.
- set.fold(record_instruction_before_prog_point(ProgPoint, Graph,
- "T1", "create"), ToBeCreatedAndAllowed, !AnnotationProc)
+ set.fold(record_instruction_before_prog_point(ProgPoint,
+ CallerGraph, "T1", "create"), ToBeCreatedAndAllowed,
+ !AnnotationProc)
)
;
(Expr = conj(_, [])
@@ -272,16 +273,16 @@
region_set::in, rpt_graph::in, rptg_node::in, rptg_node::in,
annotation_proc::in, annotation_proc::out) is det.
-process_mapping_rule_1(ProgPoint, ToBeCreatedAndAllowed, BornR_q, Graph_p,
- SourceRegion, TargetRegion, !AnnotationProc) :-
+process_mapping_rule_1(ProgPoint, ToBeCreatedAndAllowed, CalleeBornR,
+ CallerGraph, SourceRegion, TargetRegion, !AnnotationProc) :-
( if
(
set.contains(ToBeCreatedAndAllowed, TargetRegion),
- not set.contains(BornR_q, SourceRegion)
+ not set.contains(CalleeBornR, SourceRegion)
)
then
- record_instruction_before_prog_point(ProgPoint, Graph_p, "T1",
- "create", TargetRegion, !AnnotationProc)
+ record_instruction_before_prog_point(ProgPoint, CallerGraph,
+ "T1", "create", TargetRegion, !AnnotationProc)
else
true
).
@@ -343,28 +344,27 @@
region_set::in, rpta_info::in, proc_region_set_table::in,
annotation_proc::in, annotation_proc::out) is det.
-transformation_rule_3(Expr, ProgPoint, ToBeRemovedAndAllowed, RptaInfo,
+transformation_rule_3(Expr, ProgPoint, ToBeRemovedAndAllowed, CallerRptaInfo,
DeadRTable, !AnnotationProc) :-
(
- Expr = plain_call(PredId_q, ProcId_q, _, _, _, _)
+ Expr = plain_call(CalleePredId, CalleeProcId, _, _, _, _)
->
- PPId_q = proc(PredId_q, ProcId_q),
+ CalleePPId = proc(CalleePredId, CalleeProcId),
+ CallerRptaInfo = rpta_info(CallerGraph, AlphaMapping),
( if
- map.search(DeadRTable, PPId_q, _)
+ map.search(DeadRTable, CalleePPId, _)
then
- RptaInfo = rpta_info(Graph, AlphaMapping),
map.lookup(AlphaMapping, ProgPoint, AlphaAtProgPoint),
- map.lookup(DeadRTable, PPId_q, DeadR_q),
+ map.lookup(DeadRTable, CalleePPId, CalleeDeadR),
map.foldl(process_mapping_rule_3(ProgPoint,
- ToBeRemovedAndAllowed, DeadR_q, Graph),
+ ToBeRemovedAndAllowed, CalleeDeadR, CallerGraph),
AlphaAtProgPoint, !AnnotationProc)
else
% q is from an imported module. So just remove whatever regions
% become dead provided that p is allowed to remove those regions.
- RptaInfo = rpta_info(Graph_p, _),
- set.fold(record_instruction_after_prog_point(ProgPoint, Graph_p,
- "T3", "remove"),
+ set.fold(record_instruction_after_prog_point(ProgPoint,
+ CallerGraph, "T3", "remove"),
ToBeRemovedAndAllowed, !AnnotationProc)
)
;
@@ -382,16 +382,16 @@
region_set::in, rpt_graph::in, rptg_node::in, rptg_node::in,
annotation_proc::in, annotation_proc::out) is det.
-process_mapping_rule_3(ProgPoint, ToBeRemovedAndAllowed, DeadR_q, Graph_p,
- SourceRegion, TargetRegion, !AnnotationProc) :-
+process_mapping_rule_3(ProgPoint, ToBeRemovedAndAllowed, CalleeDeadR,
+ CallerGraph, SourceRegion, TargetRegion, !AnnotationProc) :-
( if
(
set.contains(ToBeRemovedAndAllowed, TargetRegion),
- not set.contains(DeadR_q, SourceRegion)
+ not set.contains(CalleeDeadR, SourceRegion)
)
then
- record_instruction_after_prog_point(ProgPoint, Graph_p, "T3",
- "remove", TargetRegion, !AnnotationProc)
+ record_instruction_after_prog_point(ProgPoint, CallerGraph,
+ "T3", "remove", TargetRegion, !AnnotationProc)
else
true
).
Index: rbmm.region_resurrection_renaming.m
===================================================================
RCS file: rbmm.region_resurrection_renaming.m
diff -N rbmm.region_resurrection_renaming.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ rbmm.region_resurrection_renaming.m 6 Jun 2007 01:56:49 -0000
@@ -0,0 +1,621 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% 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_resurrection_renaming.m.
+% Main author: Quan Phan.
+%
+% Region resurrection is the situation where the liveness of a region
+% variable along an execution path is like live, dead, live ..., i.e., the
+% variable becomes bound, then unbound, then bound again. This makes region
+% variables different from regular Mercury variables.
+% This module finds which renaming and reversed renaming of region variables
+% are needed so that region resurrection is resolved, and after applying
+% the renaming, region variables are regular Mercury variables.
+
+:- module transform_hlds.rbmm.region_resurrection_renaming.
+:- interface.
+
+:- import_module hlds.
+:- import_module hlds.hlds_pred.
+:- import_module transform_hlds.smm_common.
+:- import_module transform_hlds.rbmm.points_to_info.
+:- import_module transform_hlds.rbmm.region_liveness_info.
+
+:- import_module list.
+:- import_module map.
+:- import_module string.
+
+:- type renaming_table ==
+ map(pred_proc_id, renaming_proc).
+
+:- type renaming_proc ==
+ map(program_point, renaming).
+
+:- type renaming == map(string, string).
+
+:- type renaming_annotation_table ==
+ map(pred_proc_id, renaming_annotation_proc).
+
+:- type renaming_annotation_proc ==
+ map(program_point, list(string)).
+
+:- type proc_resurrection_path_table ==
+ map(pred_proc_id, exec_path_region_set_table).
+
+:- type exec_path_region_set_table == map(execution_path, region_set).
+
+:- type join_point_region_name_table ==
+ map(pred_proc_id, map(program_point, string)).
+
+:- 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_region_resurrection_renaming(proc_pp_region_set_table::in,
+ proc_region_set_table::in, rpta_info_table::in,
+ proc_resurrection_path_table::in,
+ renaming_table::out) is det.
+
+:- pred collect_join_points(renaming_table::in,
+ execution_path_table::in, join_point_region_name_table::out) is det.
+
+:- pred collect_renaming_and_annotation(renaming_table::in,
+ join_point_region_name_table::in, proc_pp_region_set_table::in,
+ proc_region_set_table::in, rpta_info_table::in,
+ proc_resurrection_path_table::in, execution_path_table::in,
+ renaming_annotation_table::out, renaming_table::out) is det.
+
+ % Record the annotation for a procedure.
+ %
+:- pred record_annotation(program_point::in, string::in,
+ renaming_annotation_proc::in, renaming_annotation_proc::out) is det.
+
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module hlds.hlds_goal.
+:- import_module libs.
+:- import_module libs.compiler_util.
+:- import_module transform_hlds.rbmm.points_to_graph.
+
+:- import_module assoc_list.
+:- import_module bool.
+:- import_module int.
+:- import_module pair.
+:- import_module set.
+:- import_module svmap.
+:- import_module svset.
+
+ % This predicate traveses execution paths and computes 2 pieces of
+ % 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.
+ %
+compute_resurrection_paths(ExecPathTable, LRBeforeTable, LRAfterTable,
+ BornRTable, LocalRTable, CreatedBeforeTable,
+ PathContainsResurrectionTable) :-
+ map.foldl2(compute_resurrection_paths_proc(LRBeforeTable, LRAfterTable,
+ BornRTable, LocalRTable), ExecPathTable,
+ map.init, CreatedBeforeTable,
+ map.init, PathContainsResurrectionTable).
+
+:- pred compute_resurrection_paths_proc(proc_pp_region_set_table::in,
+ proc_pp_region_set_table::in, proc_region_set_table::in,
+ proc_region_set_table::in, pred_proc_id::in, list(execution_path)::in,
+ proc_pp_region_set_table::in, proc_pp_region_set_table::out,
+ proc_resurrection_path_table::in, proc_resurrection_path_table::out)
+ is det.
+
+compute_resurrection_paths_proc(LRBeforeTable, LRAfterTable, BornRTable,
+ LocalRTable, PPId, ExecPaths, !CreatedBeforeTable,
+ !PathContainsResurrectionTable) :-
+ map.lookup(LRBeforeTable, PPId, LRBeforeProc),
+ map.lookup(LRAfterTable, PPId, LRAfterProc),
+ map.lookup(BornRTable, PPId, BornRProc),
+ map.lookup(LocalRTable, PPId, LocalRProc),
+ list.foldl2(compute_resurrection_paths_exec_path(LRBeforeProc,
+ LRAfterProc, set.union(BornRProc, LocalRProc)), ExecPaths,
+ map.init, CreatedBeforeProc, map.init, PathContainsResurrectionProc),
+ svmap.set(PPId, CreatedBeforeProc, !CreatedBeforeTable),
+ % We only want to include procedures in which resurrection happens
+ % in this map.
+ ( if map.count(PathContainsResurrectionProc) = 0
+ then
+ true
+ else
+ svmap.set(PPId, PathContainsResurrectionProc,
+ !PathContainsResurrectionTable)
+ ).
+
+:- pred compute_resurrection_paths_exec_path(pp_region_set_table::in,
+ pp_region_set_table::in, region_set::in, execution_path::in,
+ pp_region_set_table::in, pp_region_set_table::out,
+ exec_path_region_set_table::in, exec_path_region_set_table::out) is det.
+
+compute_resurrection_paths_exec_path(LRBeforeProc, LRAfterProc, Born_Local,
+ ExecPath, !CreatedBeforeProc, !ResurrectedRegionProc) :-
+ list.foldl3(compute_resurrection_paths_prog_point(LRBeforeProc,
+ LRAfterProc, Born_Local), ExecPath,
+ set.init, _, !CreatedBeforeProc,
+ set.init, ResurrectedRegionsInExecPath),
+ % We want to record only execution paths in which resurrections
+ % happen.
+ ( if set.empty(ResurrectedRegionsInExecPath)
+ then
+ true
+ else
+ svmap.set(ExecPath, ResurrectedRegionsInExecPath,
+ !ResurrectedRegionProc)
+ ).
+
+:- pred compute_resurrection_paths_prog_point(pp_region_set_table::in,
+ pp_region_set_table::in, region_set::in,
+ pair(program_point, hlds_goal)::in, region_set::in, region_set::out,
+ pp_region_set_table::in, pp_region_set_table::out,
+ region_set::in, region_set::out) is det.
+
+compute_resurrection_paths_prog_point(LRBeforeProc, LRAfterProc, Born_Local,
+ ProgPoint - _, !Candidates, !CreatedBeforeProc,
+ !ResurrectedRegionsInExecPath) :-
+ map.lookup(LRBeforeProc, ProgPoint, LRBeforeProgPoint),
+ map.lookup(LRAfterProc, ProgPoint, LRAfterProgPoint),
+
+ % Regions which are created before this program point.
+ set.intersect(Born_Local,
+ set.difference(LRAfterProgPoint, LRBeforeProgPoint),
+ CreatedBeforeProgPoint),
+ svmap.set(ProgPoint, CreatedBeforeProgPoint, !CreatedBeforeProc),
+
+ % Resurrected regions become live at more than one program point
+ % in an execution path.
+ set.intersect(!.Candidates, CreatedBeforeProgPoint, ResurrectedRegions),
+ set.union(ResurrectedRegions, !ResurrectedRegionsInExecPath),
+
+ % When a region is known to become live at one program point, it is
+ % considered a candidate for resurrection.
+ set.difference(set.union(!.Candidates, CreatedBeforeProgPoint),
+ !.ResurrectedRegionsInExecPath, !:Candidates).
+
+% ----------------------------------------------------------------------------%
+% ----------------------------------------------------------------------------%
+
+ % This predicate only traverses procedures with the execution paths
+ % containing resurrection and computes *renaming* at the points
+ % where a resurrected region becomes live.
+ % The result here will also only contain procedures in which resurrection
+ % happens and for each procedure only execution paths in which
+ % resurrection happens.
+ %
+collect_region_resurrection_renaming(CreatedBeforeTable, LocalRTable,
+ RptaInfoTable, PathContainsResurrectionTable,
+ ResurrectionRenameTable) :-
+ map.foldl(collect_region_resurrection_renaming_proc(CreatedBeforeTable,
+ LocalRTable, RptaInfoTable), PathContainsResurrectionTable,
+ map.init, ResurrectionRenameTable).
+
+:- pred collect_region_resurrection_renaming_proc(
+ proc_pp_region_set_table::in, proc_region_set_table::in,
+ rpta_info_table::in, pred_proc_id::in,
+ map(execution_path, region_set)::in, renaming_table::in,
+ renaming_table::out) is det.
+
+collect_region_resurrection_renaming_proc(CreatedBeforeTable, _LocalRTable,
+ RptaInfoTable, PPId, PathsContainResurrection,
+ !ResurrectionRenameTable) :-
+ map.lookup(CreatedBeforeTable, PPId, CreatedBeforeProc),
+ map.lookup(RptaInfoTable, PPId, RptaInfo),
+ RptaInfo = rpta_info(Graph, _),
+ map.foldl(collect_region_resurrection_renaming_exec_path(Graph,
+ CreatedBeforeProc),
+ PathsContainResurrection, map.init, ResurrectionRenameProc),
+ svmap.set(PPId, ResurrectionRenameProc, !ResurrectionRenameTable).
+
+:- pred collect_region_resurrection_renaming_exec_path(rpt_graph::in,
+ pp_region_set_table::in, execution_path::in,
+ region_set::in, renaming_proc::in,
+ renaming_proc::out) is det.
+
+collect_region_resurrection_renaming_exec_path(Graph, CreatedBeforeProc,
+ ExecPath, ResurrectedRegions, !ResurrectionRenameProc) :-
+ list.foldl2(collect_region_resurrection_renaming_prog_point(Graph,
+ CreatedBeforeProc, ResurrectedRegions), ExecPath, 1, _,
+ !ResurrectionRenameProc).
+
+:- pred collect_region_resurrection_renaming_prog_point(rpt_graph::in,
+ pp_region_set_table::in, region_set::in,
+ pair(program_point, hlds_goal)::in, int::in, int::out,
+ renaming_proc::in, renaming_proc::out) is det.
+
+collect_region_resurrection_renaming_prog_point(Graph, CreatedBeforeProc,
+ ResurrectedRegions, ProgPoint - _, !RenamingCounter,
+ !ResurrectionRenameProc) :-
+ map.lookup(CreatedBeforeProc, ProgPoint, CreatedBeforeProgPoint),
+ set.intersect(ResurrectedRegions, CreatedBeforeProgPoint,
+ ToBeRenamedRegions),
+ % We only record the program points where resurrection renaming exists.
+ ( if set.empty(ToBeRenamedRegions)
+ then
+ true
+ else
+ set.fold(record_renaming_prog_point(Graph, ProgPoint,
+ !.RenamingCounter), ToBeRenamedRegions,
+ !ResurrectionRenameProc)
+ ),
+ !:RenamingCounter = !.RenamingCounter + 1.
+
+:- pred record_renaming_prog_point(rpt_graph::in, program_point::in, int::in,
+ rptg_node::in, renaming_proc::in,
+ renaming_proc::out) is det.
+
+record_renaming_prog_point(Graph, ProgPoint, RenamingCounter, Region,
+ !ResurrectionRenameProc) :-
+ RegionName = rptg_lookup_region_name(Graph, Region),
+ Renamed = RegionName ++ "_Resur_"
+ ++ string.int_to_string(RenamingCounter),
+
+ ( if map.search(!.ResurrectionRenameProc, ProgPoint,
+ RenamingProgPoint0)
+ then
+ svmap.set(RegionName, Renamed,
+ RenamingProgPoint0, RenamingProgPoint)
+ else
+ svmap.det_insert(RegionName, Renamed, map.init, RenamingProgPoint)
+ ),
+ svmap.set(ProgPoint, RenamingProgPoint, !ResurrectionRenameProc).
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+ % Collect join points in procedures.
+ % We need to find the join points in a procedure because we need to use
+ % a specific region name for each renaming at a join point.
+ %
+ % A program point is a join point if it is in at least two execution
+ % paths and its previous points in some two execution paths are different.
+ %
+ % We will only collect join points in procedures where resurrection
+ % happens.
+ %
+ % We use ResurrectionRenameTable just for the PPIds of procedures in
+ % which resurrection happens.
+ %
+ % The new region name at a join point is formed by RegionName_jp_Number.
+ % If a region needs new names at several join points then Number will
+ % make the new names distinct.
+ %
+collect_join_points(ResurrectionRenameTable, ExecPathTable, JoinPointTable) :-
+ map.foldl(collect_join_points_proc(ExecPathTable),
+ ResurrectionRenameTable, map.init, JoinPointTable).
+
+:- pred collect_join_points_proc(execution_path_table::in,
+ pred_proc_id::in, renaming_proc::in,
+ join_point_region_name_table::in,
+ join_point_region_name_table::out) is det.
+
+collect_join_points_proc(ExecPathTable, PPId, _, !JoinPointTable) :-
+ map.lookup(ExecPathTable, PPId, ExecPaths),
+ list.foldr(pred(ExecPath::in, Ps0::in, Ps::out) is det :- (
+ assoc_list.keys(ExecPath, P),
+ Ps = [P | Ps0]
+ ), ExecPaths, [], Paths),
+ list.foldl3(collect_join_points_path(Paths), Paths,
+ 1, _, set.init, _JoinPoints, map.init, JoinPointProc),
+ svmap.set(PPId, JoinPointProc, !JoinPointTable).
+
+:- 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
+ ).
+
+ % This predicate succeeds if the first program point is a join point.
+ % That means it is at least in another execution path and is preceded
+ % by some program point, which is different from the second one.
+ %
+:- pred is_join_point(program_point::in, program_point::in,
+ list(list(program_point))::in) is semidet.
+
+is_join_point(ProgPoint, PrevProgPoint, [Path | Paths]) :-
+ ( if is_join_point_2(ProgPoint, PrevProgPoint, Path)
+ then
+ true
+ else
+ is_join_point(ProgPoint, PrevProgPoint, Paths)
+ ).
+
+:- pred is_join_point_2(program_point::in, program_point::in,
+ list(program_point)::in) is semidet.
+
+is_join_point_2(ProgPoint, PrevProgPoint, [P1, P2 | Ps]) :-
+ ( if P2 = ProgPoint
+ then
+ P1 \= PrevProgPoint
+ else
+ is_join_point_2(ProgPoint, PrevProgPoint, [P2 | Ps])
+ ).
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+%-----------------------------------------------------------------------------%
+%
+% Collect renaming at each program point.
+%
+% A renaming at a program point will be applied to annotations attached
+% to before and after it. If the associated (atomic) goal is procedure call
+% then the renaming is also applied to its actual region arguments. If the
+% goal is a construction the renaming is applied to the regions of the left
+% variable.
+
+ % This predicate collects *renaming* along the execution paths in
+ % procedures where region resurrection happens. It also computes
+ % the reversed renaming *annotations* to ensure the integrity use of
+ % regions.
+ %
+collect_renaming_and_annotation(ResurrectionRenameTable, JoinPointTable,
+ LRBeforeTable, BornRTable, RptaInfoTable, ResurrectionPathTable,
+ ExecPathTable, AnnotationTable, RenamingTable) :-
+ map.foldl2(collect_renaming_and_annotation_proc(ExecPathTable,
+ JoinPointTable, LRBeforeTable, BornRTable, RptaInfoTable,
+ ResurrectionPathTable), ResurrectionRenameTable,
+ map.init, AnnotationTable, map.init, RenamingTable).
+
+:- pred collect_renaming_and_annotation_proc(execution_path_table::in,
+ join_point_region_name_table::in, proc_pp_region_set_table::in,
+ proc_region_set_table::in, rpta_info_table::in,
+ proc_resurrection_path_table::in, pred_proc_id::in,
+ renaming_proc::in,
+ renaming_annotation_table::in, renaming_annotation_table::out,
+ renaming_table::in, renaming_table::out) is det.
+
+collect_renaming_and_annotation_proc(ExecPathTable, JoinPointTable,
+ LRBeforeTable, BornRTable, RptaInfoTable, ResurrectionPathTable,
+ PPId, ResurrectionRenameProc, !AnnotationTable, !RenamingTable) :-
+ map.lookup(JoinPointTable, PPId, JoinPointProc),
+ map.lookup(LRBeforeTable, PPId, LRBeforeProc),
+ map.lookup(BornRTable, PPId, BornR),
+ map.lookup(RptaInfoTable, PPId, RptaInfo),
+ RptaInfo = rpta_info(Graph, _),
+ % Here we find all regions which resurrects in this procedure.
+ % This information is used at a join point to introduce renamings
+ % for all resurrecting regions that become live at the join point.
+ map.lookup(ResurrectionPathTable, PPId, PathsContainResurrection),
+ map.values(PathsContainResurrection, ResurrectedRegionsInPaths),
+ list.foldl(pred(ResurRegions::in, R0::in, R::out) is det :- (
+ set.union(R0, ResurRegions, R)
+ ), ResurrectedRegionsInPaths,
+ set.init, ResurrectedRegionsProc),
+ map.lookup(ExecPathTable, PPId, ExecPaths),
+ list.foldl2(collect_renaming_and_annotation_exec_path(
+ ResurrectionRenameProc, JoinPointProc, LRBeforeProc, BornR,
+ Graph, ResurrectedRegionsProc), ExecPaths,
+ map.init, AnnotationProc, map.init, RenamingProc),
+ svmap.set(PPId, AnnotationProc, !AnnotationTable),
+ svmap.set(PPId, RenamingProc, !RenamingTable).
+
+ % The renaming along an execution path is built up. Let's see an
+ % example of renamings.
+ % (1) R1 --> R1_1 // i.e., R1 resurrects and therefore needs renaming.
+ % (2) R1 --> R1_1, R2 --> R2_1
+ % (3) R1 --> R1_2, R2 --> R2_1 //R1 becomes live again, needs a new name.
+ % ...
+ %
+:- pred collect_renaming_and_annotation_exec_path(renaming_proc::in,
+ map(program_point, string)::in, pp_region_set_table::in,
+ region_set::in, rpt_graph::in, region_set::in, execution_path::in,
+ renaming_annotation_proc::in, renaming_annotation_proc::out,
+ renaming_proc::in, renaming_proc::out) is det.
+
+collect_renaming_and_annotation_exec_path(_, _, _, _, _, _, [],
+ !AnnotationProc, !RenamingProc) :-
+ unexpected(this_file, "collect_renaming_and_annotation_exec_path: "
+ ++ "empty execution path encountered").
+
+ % This is the first program point in an execution path.
+ % It cannot be a join point. Renaming is needed at this point only
+ % when it is a resurrection point.
+ %
+collect_renaming_and_annotation_exec_path(ResurrectionRenameProc,
+ JoinPointProc, LRBeforeProc, BornR, Graph, ResurrectedRegions,
+ [ProgPoint - _ | ProgPoint_Goals], !AnnotationProc, !RenamingProc) :-
+ ( if map.search(ResurrectionRenameProc, ProgPoint, ResurRename)
+ then
+ svmap.set(ProgPoint, ResurRename, !RenamingProc)
+ else
+ svmap.set(ProgPoint, map.init, !RenamingProc)
+ ),
+ collect_renaming_and_annotation_exec_path_2(ResurrectionRenameProc,
+ JoinPointProc, LRBeforeProc, BornR, Graph, ResurrectedRegions,
+ ProgPoint, ProgPoint_Goals, !AnnotationProc, !RenamingProc).
+
+:- pred collect_renaming_and_annotation_exec_path_2(renaming_proc::in,
+ map(program_point, string)::in, pp_region_set_table::in,
+ region_set::in, rpt_graph::in, region_set::in, program_point::in,
+ execution_path::in,
+ renaming_annotation_proc::in, renaming_annotation_proc::out,
+ renaming_proc::in, renaming_proc::out) is det.
+
+ % This means the first program point is also the last.
+ % We do not need to do anything more.
+ %
+collect_renaming_and_annotation_exec_path_2(_, _, _, _, _, _, _, [],
+ !AnnotationProc, !RenamingProc).
+
+ % This is a program point which is not the first.
+ %
+ % A program point can belong to different execution paths, therefore
+ % it can be processed more than once. If a program point is a
+ % *join point*, the process in later execution paths may add new
+ % renaming information about some resurrected region(s) which does not
+ % resurrect in the already-processed paths covering this program point.
+ % To avoid updating information related to the already-processed paths
+ % whenever we process a join point we include the information about ALL
+ % resurrected regions that are live before the join point. This will
+ % ensure that no new renaming information arises when the program
+ % point is processed again.
+ %
+ % At a join point, we need to add suitable annotations to the previous
+ % point, i.e., ones related to the renaming at the previous point.
+ %
+ % At the last program point, we need to add annotations for any region
+ % parameters which resurrect.
+ %
+collect_renaming_and_annotation_exec_path_2(ResurrectionRenameProc,
+ JoinPointProc, LRBeforeProc, BornR, Graph, ResurrectedRegions,
+ PrevProgPoint, [ProgPoint - _ | ProgPoint_Goals],
+ !AnnotationProc, !RenamingProc) :-
+ map.lookup(!.RenamingProc, PrevProgPoint, PrevRenaming),
+ ( if map.search(ResurrectionRenameProc, ProgPoint, ResurRenaming)
+ then
+ % This is a resurrection point of some region(s). We need to
+ % merge the existing renaming at the previous point with the
+ % resurrection renaming here. When two renamings have the same
+ % key, i.e., the region resurrects, the resurrection renaming
+ % takes priority.
+ map.overlay(PrevRenaming, ResurRenaming, Renaming0),
+ svmap.set(ProgPoint, Renaming0, !RenamingProc)
+ else
+ % This is not a resurrection point (of any regions).
+ % Renaming at this point is the same as at its
+ % previous point
+ svmap.set(ProgPoint, PrevRenaming, !RenamingProc)
+ ),
+ ( if map.search(JoinPointProc, ProgPoint, JoinPointName)
+ then
+ % This is a join point.
+ % Add annotations to the previous point.
+ map.lookup(LRBeforeProc, ProgPoint, LRBeforeProgPoint),
+ set.intersect(ResurrectedRegions, LRBeforeProgPoint,
+ ResurrectedAndLiveRegions),
+ set.fold2(add_annotation_and_renaming(PrevProgPoint,
+ Graph, JoinPointName, PrevRenaming),
+ ResurrectedAndLiveRegions, !AnnotationProc,
+ map.init, Renaming),
+ % We will just overwrite any existing renaming
+ % information at this point.
+ svmap.set(ProgPoint, Renaming, !RenamingProc)
+ else
+ true
+ ),
+ (
+ % This is the last program point in this execution path.
+ ProgPoint_Goals = [],
+ % Add reversed renaming for regions in bornR.
+ set.intersect(ResurrectedRegions, BornR, ResurrectedAndBornRegions),
+ map.lookup(!.RenamingProc, ProgPoint, LastRenaming),
+ set.fold(add_annotation(ProgPoint, Graph, LastRenaming),
+ ResurrectedAndBornRegions, !AnnotationProc)
+ ;
+ ProgPoint_Goals = [_ | _],
+ collect_renaming_and_annotation_exec_path_2(ResurrectionRenameProc,
+ JoinPointProc, LRBeforeProc, BornR, Graph, ResurrectedRegions,
+ ProgPoint, ProgPoint_Goals, !AnnotationProc, !RenamingProc)
+ ).
+
+ % This predicate adds renaming annotation after the previous program
+ % point and records renaming from existing region name.
+ %
+:- pred add_annotation_and_renaming(program_point::in,
+ rpt_graph::in, string::in, renaming::in, rptg_node::in,
+ renaming_annotation_proc::in, renaming_annotation_proc::out,
+ renaming::in, renaming::out) is det.
+
+add_annotation_and_renaming(PrevProgPoint, Graph, JoinPointName,
+ PrevRenaming, Region, !AnnotationProc, !Renaming) :-
+ RegionName = rptg_lookup_region_name(Graph, Region),
+ NewName = RegionName ++ JoinPointName,
+
+ % Add renaming.
+ svmap.det_insert(RegionName, NewName, !Renaming),
+
+ % Add annotation to (after) the previous program point.
+ % Annotations are only added for resurrected regions that have been
+ % renamed in this execution path (i.e., the execution path contains
+ % PrevProgPoint and ProgPoint).
+ ( if map.search(PrevRenaming, RegionName, CurrentName)
+ then
+ Annotation = NewName ++ " = " ++ CurrentName,
+ record_annotation(PrevProgPoint, Annotation, !AnnotationProc)
+ else
+ true
+ ).
+
+:- pred add_annotation(program_point::in, rpt_graph::in, renaming::in,
+ rptg_node::in, renaming_annotation_proc::in,
+ renaming_annotation_proc::out) is det.
+
+add_annotation(ProgPoint, Graph, Renaming, Region, !AnnotationProc) :-
+ RegionName = rptg_lookup_region_name(Graph, Region),
+
+ % Add annotation to (after) the program point.
+ % Annotations are only added for resurrected regions that have been
+ % renamed in this execution path.
+ ( if map.search(Renaming, RegionName, CurrentName)
+ then
+ Annotation = RegionName ++ " = " ++ CurrentName,
+ record_annotation(ProgPoint, Annotation, !AnnotationProc)
+ else
+ true
+ ).
+
+record_annotation(ProgPoint, Annotation, !AnnotationProc) :-
+ ( if map.search(!.AnnotationProc, ProgPoint, Annotations0)
+ then
+ ( if list.member(Annotation, Annotations0)
+ then
+ Annotations = Annotations0
+ else
+ Annotations = [Annotation | Annotations0]
+ )
+ else
+ % No annotation exists at this program point yet.
+ Annotations = [Annotation]
+ ),
+ svmap.set(ProgPoint, Annotations, !AnnotationProc).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "rbmm.region_resurrection_renaming.m".
+
+%-----------------------------------------------------------------------------%
+
--------------------------------------------------------------------------
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