mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-17 10:23:46 +00:00
Since this is the first converted module that dumps out goals when
debugging trace flags are enabled, this required generalizing the code
that does that, to take either varsets or var_tables as a means of
specifying the names of variables. We do this via a new type,
var_name_source, which contains either a varset or a var_table.
Almost all of this diff is there to implement this generalization.
A large part of it affects code in the parse_tree package that we use
to write out the parts of HLDS goals that are defined by types defined
in that package. Since we want to avoid making any part of the parse_tree
package dependent on the hlds package, this required defining the
var_name_source type in the parse_tree package, which in turn requires
var_table.m to be in that same package.
compiler/lco.m:
Convert this module to use var_tables instead of varsets and vartypes.
compiler/var_table.m:
Move this module from the hlds package to the parse_tree package.
To make this, possible, move the parts that required access to the HLDS
to hlds_pred.m, from where it was usually invoked.
Export some utility predicates to allow the moved code to work
in hlds_pred.m without access to the actual definition of the
var_table type.
Define the var_name_source type.
Add some utility functions for use by code writing out variable names.
compiler/hlds_pred.m:
Add the code moved from var_table.m.
compiler/vartypes.m:
Move this module from the hlds package to the parse_tree package,
for symmetry with var_table.m. It did not depend on being in hlds
in any way.
compiler/hlds.m:
compiler/parse_tree.m:
Move vartypes.m and var_table.m from the hlds package
to the parse_tree package.
compiler/hlds_out_goal.m:
Change all the predicates in this module to take a var_name_source
instead of a prog_varset.
Fix some comments.
compiler/hlds_out_util.m:
Change some of the predicates in this module (those called from
hlds_out_goal.m) to take a var_name_source instead of a prog_varset.
compiler/parse_tree_out_term.m:
Provide variants of some existing predicates and functions that take
var_name_sources instead of varsets. The code of the copies
duplicates the logic of the originals, though I hope that this
duplication can be done away with at the end of the transition.
(The best solution would be to use a typeclass with methods
that convert vars to their names, but we would want to ensure
that the compiler can specialize all the affected predicates
and functions to the two instances of this typeclass, which is
something that we cannot do yet. In the meantime, the lack of
any generalization in the old versions preserves their performance.)
tools/sort_imports:
tools/filter_sort_imports:
A new tool that automatically sorts any occurrences of consecutive
":- import_module" declarations in the named files. The sorting is done
in filter_sort_imports; sort_imports loops over the named files.
After automatically replacing all occurrences of hlds.{vartypes,var_table}
in import_module declarations with their parse_tree versions, the updated
import_module declarations were usually out of order with respect to
their neighbours. I used this script to fix that, and some earlier
out-of-order imports.
compiler/accumulator.m:
compiler/add_class.m:
compiler/add_clause.m:
compiler/add_foreign_proc.m:
compiler/add_heap_ops.m:
compiler/add_pragma_type_spec.m:
compiler/add_pred.m:
compiler/add_trail_ops.m:
compiler/analysis.m:
compiler/arg_info.m:
compiler/build_mode_constraints.m:
compiler/bytecode_gen.m:
compiler/call_gen.m:
compiler/check_promise.m:
compiler/closure_analysis.m:
compiler/closure_gen.m:
compiler/code_info.m:
compiler/code_loc_dep.m:
compiler/common.m:
compiler/compile_target_code.m:
compiler/complexity.m:
compiler/const_prop.m:
compiler/constraint.m:
compiler/continuation_info.m:
compiler/convert_parse_tree.m:
compiler/coverage_profiling.m:
compiler/cse_detection.m:
compiler/ctgc.datastruct.m:
compiler/ctgc.util.m:
compiler/dead_proc_elim.m:
compiler/deep_profiling.m:
compiler/deforest.m:
compiler/delay_construct.m:
compiler/delay_partial_inst.m:
compiler/dep_par_conj.m:
compiler/det_analysis.m:
compiler/det_report.m:
compiler/det_util.m:
compiler/direct_arg_in_out.m:
compiler/disj_gen.m:
compiler/distance_granularity.m:
compiler/equiv_type_hlds.m:
compiler/exception_analysis.m:
compiler/file_names.m:
compiler/float_regs.m:
compiler/follow_vars.m:
compiler/format_call.m:
compiler/generate_dep_d_files.m:
compiler/get_dependencies.m:
compiler/goal_expr_to_goal.m:
compiler/goal_mode.m:
compiler/goal_path.m:
compiler/goal_store.m:
compiler/goal_util.m:
compiler/granularity.m:
compiler/hhf.m:
compiler/higher_order.m:
compiler/hlds_clauses.m:
compiler/hlds_code_util.m:
compiler/hlds_error_util.m:
compiler/hlds_goal.m:
compiler/hlds_llds.m:
compiler/hlds_out_pred.m:
compiler/hlds_rtti.m:
compiler/hlds_statistics.m:
compiler/inlining.m:
compiler/inst_check.m:
compiler/inst_test.m:
compiler/inst_user.m:
compiler/instance_method_clauses.m:
compiler/instmap.m:
compiler/intermod.m:
compiler/intermod_analysis.m:
compiler/interval.m:
compiler/introduce_exists_casts.m:
compiler/introduce_parallelism.m:
compiler/item_util.m:
compiler/lambda.m:
compiler/live_vars.m:
compiler/liveness.m:
compiler/llds.m:
compiler/llds_out_data.m:
compiler/llds_out_file.m:
compiler/llds_out_util.m:
compiler/lookup_switch.m:
compiler/loop_inv.m:
compiler/make.module_target.m:
compiler/make.util.m:
compiler/make_goal.m:
compiler/make_hlds_separate_items.m:
compiler/make_hlds_types.m:
compiler/mark_tail_calls.m:
compiler/mercury_compile_mlds_back_end.m:
compiler/middle_rec.m:
compiler/ml_accurate_gc.m:
compiler/ml_args_util.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_gen_info.m:
compiler/ml_lookup_switch.m:
compiler/ml_proc_gen.m:
compiler/ml_simplify_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
compiler/ml_unify_gen.m:
compiler/ml_unify_gen_construct.m:
compiler/ml_unify_gen_deconstruct.m:
compiler/ml_unify_gen_test.m:
compiler/ml_unify_gen_util.m:
compiler/mlds_to_c_data.m:
compiler/mlds_to_c_func.m:
compiler/mlds_to_c_global.m:
compiler/mlds_to_cs_class.m:
compiler/mlds_to_cs_file.m:
compiler/mlds_to_java_data.m:
compiler/mlds_to_java_file.m:
compiler/mlds_to_java_stmt.m:
compiler/mlds_to_java_type.m:
compiler/mmc_analysis.m:
compiler/mode_comparison.m:
compiler/mode_constraints.m:
compiler/mode_debug.m:
compiler/mode_errors.m:
compiler/mode_info.m:
compiler/mode_ordering.m:
compiler/modecheck_call.m:
compiler/modecheck_coerce.m:
compiler/modecheck_goal.m:
compiler/modecheck_unify.m:
compiler/modecheck_util.m:
compiler/modes.m:
compiler/module_cmds.m:
compiler/old_type_constraints.m:
compiler/opt_debug.m:
compiler/optimize.m:
compiler/options_file.m:
compiler/ordering_mode_constraints.m:
compiler/par_loop_control.m:
compiler/parse_item.m:
compiler/parse_string_format.m:
compiler/parse_tree_out_inst.m:
compiler/parse_tree_to_term.m:
compiler/parse_util.m:
compiler/pd_debug.m:
compiler/pd_info.m:
compiler/pd_util.m:
compiler/peephole.m:
compiler/polymorphism.m:
compiler/polymorphism_info.m:
compiler/polymorphism_lambda.m:
compiler/polymorphism_type_class_info.m:
compiler/polymorphism_type_info.m:
compiler/post_typecheck.m:
compiler/pragma_c_gen.m:
compiler/pred_name.m:
compiler/pred_table.m:
compiler/prog_item.m:
compiler/prog_rep.m:
compiler/prop_mode_constraints.m:
compiler/purity.m:
compiler/push_goals_together.m:
compiler/qual_info.m:
compiler/quantification.m:
compiler/rbmm.execution_path.m:
compiler/rbmm.m:
compiler/rbmm.points_to_analysis.m:
compiler/rbmm.points_to_graph.m:
compiler/rbmm.points_to_info.m:
compiler/rbmm.region_resurrection_renaming.m:
compiler/rbmm.region_transformation.m:
compiler/recompilation.used_file.m:
compiler/recompilation.version.m:
compiler/recompute_instmap_deltas.m:
compiler/resolve_unify_functor.m:
compiler/rtti.m:
compiler/rtti_out.m:
compiler/rtti_to_mlds.m:
compiler/saved_vars.m:
compiler/set_of_var.m:
compiler/simplify_goal_call.m:
compiler/simplify_goal_conj.m:
compiler/simplify_goal_disj.m:
compiler/simplify_goal_ite.m:
compiler/simplify_goal_scope.m:
compiler/simplify_goal_switch.m:
compiler/simplify_goal_unify.m:
compiler/simplify_info.m:
compiler/simplify_proc.m:
compiler/size_prof.m:
compiler/smm_common.m:
compiler/ssdebug.m:
compiler/stack_alloc.m:
compiler/stack_layout.m:
compiler/stack_opt.m:
compiler/stm_expand.m:
compiler/store_alloc.m:
compiler/structure_reuse.analysis.m:
compiler/structure_reuse.direct.choose_reuse.m:
compiler/structure_reuse.direct.detect_garbage.m:
compiler/structure_reuse.domain.m:
compiler/structure_reuse.indirect.m:
compiler/structure_reuse.lbu.m:
compiler/structure_reuse.lfu.m:
compiler/structure_sharing.analysis.m:
compiler/structure_sharing.domain.m:
compiler/superhomogeneous.m:
compiler/switch_detection.m:
compiler/switch_gen.m:
compiler/switch_util.m:
compiler/table_gen.m:
compiler/tabling_analysis.m:
compiler/term_constr_build.m:
compiler/term_constr_data.m:
compiler/term_constr_initial.m:
compiler/term_constr_main.m:
compiler/term_constr_main_types.m:
compiler/term_constr_util.m:
compiler/term_pass1.m:
compiler/term_traversal.m:
compiler/term_util.m:
compiler/trace_gen.m:
compiler/trailing_analysis.m:
compiler/transform_llds.m:
compiler/try_expand.m:
compiler/tupling.m:
compiler/type_assign.m:
compiler/type_ctor_info.m:
compiler/type_util.m:
compiler/typecheck.m:
compiler/typecheck_debug.m:
compiler/typecheck_errors.m:
compiler/typecheck_info.m:
compiler/unify_gen_construct.m:
compiler/unify_gen_deconstruct.m:
compiler/unify_proc.m:
compiler/unique_modes.m:
compiler/unneeded_code.m:
compiler/untupling.m:
compiler/unused_args.m:
compiler/unused_imports.m:
compiler/var_locn.m:
compiler/write_deps_file.m:
compiler/write_module_interface_files.m:
Conform to the changes above.
859 lines
33 KiB
Mathematica
859 lines
33 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2002-2007, 2009-2011 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: hlds_llds.m.
|
|
% Author: zs.
|
|
%
|
|
% This module defines annotations on HLDS goals that are used by the LLDS
|
|
% back end.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module hlds.hlds_llds.
|
|
:- interface.
|
|
|
|
:- import_module hlds.hlds_goal.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.prog_rename.
|
|
:- import_module parse_tree.set_of_var.
|
|
:- import_module parse_tree.var_table.
|
|
|
|
:- import_module bool.
|
|
:- import_module list.
|
|
:- import_module map.
|
|
:- import_module maybe.
|
|
|
|
% reg_r are the general purpose registers.
|
|
%
|
|
% reg_f are float registers.
|
|
% They are only present when float is wider than a word.
|
|
%
|
|
:- type reg_type
|
|
---> reg_r
|
|
; reg_f.
|
|
|
|
:- type stack_slot
|
|
---> det_slot(int, stack_slot_width)
|
|
; parent_det_slot(int, stack_slot_width)
|
|
; nondet_slot(int).
|
|
|
|
:- type stack_slot_width
|
|
---> single_width
|
|
; double_width. % occupies slots N and N+1
|
|
|
|
% Maps variables to their stack slots.
|
|
%
|
|
:- type stack_slots == map(prog_var, stack_slot).
|
|
|
|
:- func explain_stack_slots(var_table, stack_slots) = string.
|
|
|
|
:- type abs_locn
|
|
---> any_reg
|
|
; abs_reg(reg_type, int)
|
|
; abs_stackvar(int, stack_slot_width)
|
|
; abs_parent_stackvar(int, stack_slot_width)
|
|
; abs_framevar(int).
|
|
|
|
:- type abs_follow_vars_map == map(prog_var, abs_locn).
|
|
|
|
% Advisory information about where variables ought to be put next.
|
|
% Variables may or may not appear in the map. If they do, then the
|
|
% associated locn says where the value of that variable ought to be put
|
|
% when it is computed, or, if the locn is any_reg, it says that it
|
|
% should be put into any available register. The two integers give the
|
|
% first regular and float registers, respectively, that are not reserved
|
|
% for other purposes, and so are free to hold such variables.
|
|
%
|
|
:- type abs_follow_vars
|
|
---> abs_follow_vars(
|
|
afv_map :: abs_follow_vars_map,
|
|
afv_next_non_res_reg_r :: int,
|
|
afv_next_non_res_reg_f :: int
|
|
).
|
|
|
|
% Authoritative information about where variables must be put
|
|
% at the ends of branches of branched control structures.
|
|
% However, between the follow_vars and store_alloc passes,
|
|
% these fields temporarily hold follow_vars information.
|
|
% The final value is not allowed to map any variable to any_reg.
|
|
%
|
|
:- type abs_store_map == map(prog_var, abs_locn).
|
|
|
|
% see compiler/notes/allocation.html for what these alternatives mean
|
|
:- type resume_point
|
|
---> resume_point(set_of_progvar, resume_locs)
|
|
; no_resume_point.
|
|
|
|
:- type resume_locs
|
|
---> resume_locs_orig_only
|
|
; resume_locs_stack_only
|
|
; resume_locs_orig_then_stack
|
|
; resume_locs_stack_then_orig.
|
|
|
|
% When code in live_vars.m finds out what variables need to be saved
|
|
% across calls (including generic calls and foreign_procs that can call
|
|
% back to Mercury), at resume points, and in parallel conjunctions, it
|
|
% records the results in the code_gen_details field of hlds_goal_infos.
|
|
% It does so in values of types need_across_call, need_in_resume and
|
|
% need_in_par_conj.
|
|
|
|
% call_forward_vars contains the set of variables that need to be saved
|
|
% across a call because they are needed when the call succeeds.
|
|
% call_resume vars contains the set of variables that need to be saved
|
|
% across a call because they are needed when the call fails, and
|
|
% execution backtracks to a resume point to the call's left.
|
|
% call_nondet_vars contains the set of variables that need to be on
|
|
% the stack across a call because they are needed by a model_non goal
|
|
% to the left of the call.
|
|
|
|
:- type need_across_call
|
|
---> need_across_call(
|
|
call_forward_vars :: set_of_progvar,
|
|
call_resume_vars :: set_of_progvar,
|
|
call_nondet_vars :: set_of_progvar
|
|
).
|
|
|
|
% resume_vars_on_stack is true if the resume point has a stack label.
|
|
% resume_resume vars contains the set of variables that need to be
|
|
% saved at a resume point because they are needed when execution
|
|
% backtracks to this resume point, or to a resume point on its left.
|
|
% resume_nondet_vars contains the set of variables that need to be on
|
|
% the stack at a resume point because they are needed by a model_non
|
|
% goal to the left of the resume point.
|
|
|
|
:- type need_in_resume
|
|
---> need_in_resume(
|
|
resume_vars_on_stack :: bool,
|
|
resume_resume_vars :: set_of_progvar,
|
|
resume_nondet_vars :: set_of_progvar
|
|
).
|
|
|
|
% par_conj_engine_vars gives the set of variables that the execution
|
|
% mechanism of the parallel conjunction requires to be stored in stack
|
|
% slots.
|
|
%
|
|
:- type need_in_par_conj
|
|
---> need_in_par_conj(
|
|
par_conj_engine_vars :: set_of_progvar
|
|
).
|
|
|
|
% loop_control_distinct_stackvars gives sets of variables that must not
|
|
% have overlapping stack slot allocations so that concurrent access to the
|
|
% same stack frame is safe.
|
|
%
|
|
:- type need_for_loop_control
|
|
---> need_for_loop_control(
|
|
loop_control_distinct_stackvars :: list(set_of_progvar)
|
|
).
|
|
|
|
:- type llds_code_gen_details.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Instead of recording the liveness of every variable at every part of the
|
|
% goal, we just keep track of the initial liveness and the changes in
|
|
% liveness. Note that when traversing forwards through a goal, deaths must be
|
|
% applied before births; this is necessary to handle certain circumstances
|
|
% where a variable can occur in both the post-death and post-birth sets, or in
|
|
% both the pre-death and pre-birth sets.
|
|
|
|
:- pred goal_info_get_pre_births(hlds_goal_info::in,
|
|
set_of_progvar::out) is det.
|
|
|
|
:- pred goal_info_get_post_births(hlds_goal_info::in,
|
|
set_of_progvar::out) is det.
|
|
|
|
:- pred goal_info_get_pre_deaths(hlds_goal_info::in,
|
|
set_of_progvar::out) is det.
|
|
|
|
:- pred goal_info_get_post_deaths(hlds_goal_info::in,
|
|
set_of_progvar::out) is det.
|
|
|
|
:- pred goal_info_get_follow_vars(hlds_goal_info::in,
|
|
maybe(abs_follow_vars)::out) is det.
|
|
|
|
:- pred goal_info_get_store_map(hlds_goal_info::in,
|
|
abs_store_map::out) is det.
|
|
|
|
:- pred goal_info_get_resume_point(hlds_goal_info::in,
|
|
resume_point::out) is det.
|
|
|
|
:- pred goal_info_get_maybe_need_across_call(hlds_goal_info::in,
|
|
maybe(need_across_call)::out) is det.
|
|
|
|
:- pred goal_info_get_maybe_need_in_resume(hlds_goal_info::in,
|
|
maybe(need_in_resume)::out) is det.
|
|
|
|
:- pred goal_info_get_maybe_need_in_par_conj(hlds_goal_info::in,
|
|
maybe(need_in_par_conj)::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred goal_info_maybe_get_pre_births(hlds_goal_info::in,
|
|
set_of_progvar::out) is semidet.
|
|
|
|
:- pred goal_info_maybe_get_post_births(hlds_goal_info::in,
|
|
set_of_progvar::out) is semidet.
|
|
|
|
:- pred goal_info_maybe_get_pre_deaths(hlds_goal_info::in,
|
|
set_of_progvar::out) is semidet.
|
|
|
|
:- pred goal_info_maybe_get_post_deaths(hlds_goal_info::in,
|
|
set_of_progvar::out) is semidet.
|
|
|
|
:- pred goal_info_maybe_get_follow_vars(hlds_goal_info::in,
|
|
maybe(abs_follow_vars)::out) is semidet.
|
|
|
|
:- pred goal_info_maybe_get_store_map(hlds_goal_info::in,
|
|
abs_store_map::out) is semidet.
|
|
|
|
:- pred goal_info_maybe_get_resume_point(hlds_goal_info::in,
|
|
resume_point::out) is semidet.
|
|
|
|
:- pred goal_info_maybe_get_maybe_need_across_call(hlds_goal_info::in,
|
|
maybe(need_across_call)::out) is semidet.
|
|
|
|
:- pred goal_info_maybe_get_maybe_need_in_resume(hlds_goal_info::in,
|
|
maybe(need_in_resume)::out) is semidet.
|
|
|
|
:- pred goal_info_maybe_get_maybe_need_in_par_conj(hlds_goal_info::in,
|
|
maybe(need_in_par_conj)::out) is semidet.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% goal_info_initialize_liveness_info(PreBirths, PostBirths,
|
|
% PreDeaths, PostDeaths, ResumePoint, !GoalInfo):
|
|
% Updates !GoalInfo by overwriting the previous values of its
|
|
% pre_births, post_births, pre_deaths, post_deaths and resume_point fields.
|
|
%
|
|
:- pred goal_info_initialize_liveness_info(
|
|
set_of_progvar::in, set_of_progvar::in,
|
|
set_of_progvar::in, set_of_progvar::in,
|
|
resume_point::in, hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
:- pred goal_info_set_pre_births(set_of_progvar::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
:- pred goal_info_set_post_births(set_of_progvar::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
:- pred goal_info_set_pre_deaths(set_of_progvar::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
:- pred goal_info_set_post_deaths(set_of_progvar::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
:- pred goal_info_set_follow_vars(maybe(abs_follow_vars)::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
:- pred goal_info_set_store_map(abs_store_map::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
:- pred goal_info_set_resume_point(resume_point::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
:- pred goal_info_set_need_across_call(need_across_call::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
:- pred goal_info_set_need_in_resume(need_in_resume::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
:- pred goal_info_set_need_in_par_conj(need_in_par_conj::in,
|
|
hlds_goal_info::in, hlds_goal_info::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred goal_set_follow_vars(maybe(abs_follow_vars)::in,
|
|
hlds_goal::in, hlds_goal::out) is det.
|
|
|
|
:- pred goal_set_resume_point(resume_point::in,
|
|
hlds_goal::in, hlds_goal::out) is det.
|
|
|
|
:- pred goal_info_resume_vars_and_loc(resume_point::in,
|
|
set_of_progvar::out, resume_locs::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% rename_vars_in_llds_code_gen_info(Must, Rename, Details0, Details):
|
|
%
|
|
% Rename all the variables in Details0 according to the substitution
|
|
% Rename, yielding Details. If Must is must_rename, then require every
|
|
% variable in Details0 to be in the domain of Rename. If Must is
|
|
% need_not_rename, then leave variables not in the domain of Rename
|
|
% unchanged.
|
|
%
|
|
:- pred rename_vars_in_llds_code_gen_info(must_rename::in,
|
|
map(prog_var, prog_var)::in,
|
|
llds_code_gen_details::in, llds_code_gen_details::out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- func stack_slot_num(stack_slot) = int.
|
|
|
|
:- func stack_slot_to_abs_locn(stack_slot) = abs_locn.
|
|
:- func key_stack_slot_to_abs_locn(_, stack_slot) = abs_locn.
|
|
|
|
:- pred abs_locn_to_string(abs_locn::in, string::out, maybe(string)::out)
|
|
is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module assoc_list.
|
|
:- import_module pair.
|
|
:- import_module require.
|
|
:- import_module string.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
explain_stack_slots(VarTable, StackSlots) = Explanation :-
|
|
map.to_assoc_list(StackSlots, StackSlotsList),
|
|
explain_stack_slots_2(VarTable, StackSlotsList, "", Explanation1),
|
|
Explanation = "\nStack slot assignments (if any):\n" ++ Explanation1.
|
|
|
|
:- pred explain_stack_slots_2(var_table::in,
|
|
assoc_list(prog_var, stack_slot)::in, string::in, string::out) is det.
|
|
|
|
explain_stack_slots_2(_, [], !Explanation).
|
|
explain_stack_slots_2(VarTable, [Var - Slot | VarsSlots], !Explanation) :-
|
|
explain_stack_slots_2(VarTable, VarsSlots, !Explanation),
|
|
(
|
|
Slot = det_slot(SlotNum, Width),
|
|
StackStr = "sv"
|
|
;
|
|
Slot = parent_det_slot(SlotNum, Width),
|
|
StackStr = "parent_sv"
|
|
;
|
|
Slot = nondet_slot(SlotNum),
|
|
Width = single_width,
|
|
StackStr = "fv"
|
|
),
|
|
int_to_string(SlotNum, SlotStr),
|
|
(
|
|
Width = single_width,
|
|
WidthStr = ""
|
|
;
|
|
Width = double_width,
|
|
WidthStr = " (double width)"
|
|
),
|
|
VarName = var_table_entry_name(VarTable, Var),
|
|
string.format("%s\t ->\t%s%s%s\n%s",
|
|
[s(VarName), s(StackStr), s(SlotStr), s(WidthStr), s(!.Explanation)],
|
|
!:Explanation).
|
|
|
|
%----------------------------------------------------------------------------%
|
|
|
|
% For the meaning of this type, see the documentation of the
|
|
% maybe_need field of llds_code_gen_details below.
|
|
%
|
|
:- type maybe_need
|
|
---> no_need
|
|
; need_call(need_across_call)
|
|
; need_resume(need_in_resume)
|
|
; need_par_conj(need_in_par_conj).
|
|
|
|
:- type llds_code_gen_details
|
|
---> llds_code_gen_details(
|
|
% All four of these fields are computed by liveness.m.
|
|
% For atomic goals, the post-deadness should be applied
|
|
% _before_ the goal.
|
|
pre_births :: set_of_progvar,
|
|
post_births :: set_of_progvar,
|
|
pre_deaths :: set_of_progvar,
|
|
post_deaths :: set_of_progvar,
|
|
|
|
% Initially set to `no' for all goals, which means the absence
|
|
% of the advisory information. Can be set to `yes' by the
|
|
% follow_vars pass, if it is invoked. Can be set to `yes'
|
|
% for any kind of goal.
|
|
%
|
|
% For the semantics of the value inside a `yes',
|
|
% see the documentation of the follow_vars type.
|
|
follow_vars :: maybe(abs_follow_vars),
|
|
|
|
% This annotation is meaningful only after the store_alloc
|
|
% pass, and even then only if attached to a goal representing
|
|
% a branched control structure, i.e. an if_then_else, switch
|
|
% or disj goal. For those goals, the map will have an entry
|
|
% for every variable that is forward live after the goal,
|
|
% and will map each of those variables to the location where
|
|
% all the branches will leave the value of the variable.
|
|
% The code after the branched goal can therefore pick it
|
|
% up from there.
|
|
%
|
|
% This field should contain an empty map if its contents
|
|
% are not meaningful.
|
|
store_map :: abs_store_map,
|
|
|
|
% If this goal establishes a resumption point, i.e. it is
|
|
% the second or later disjunct of a disjunction or if it is
|
|
% the condition of an if-then-else, this field will state
|
|
% what variables need to be saved for that resumption point,
|
|
% and which entry labels of the resumption point will be
|
|
% needed. (See compiler/notes/allocation.html)
|
|
%
|
|
% This field is filled in during the liveness pass. Before
|
|
% then, and after then if the goal does not establish a
|
|
% resumption point, it should contain no_resume_point.
|
|
resume_point :: resume_point,
|
|
|
|
% This field is filled in during the stackvars pass.
|
|
% It is not meaningful before then, and should contain
|
|
% `no_need'.
|
|
%
|
|
% For calls, generic calls, and for foreign_proc goals
|
|
% that may call back to Mercury, the stackvars pass will set
|
|
% this argument to need_call(NC), where NC specifies what
|
|
% variables need to be stored on the stack across the call.
|
|
%
|
|
% For disjunctions, if-then-elses and negations, the stackvars
|
|
% pass will set this argument to need_resume(NR), where NR
|
|
% specifies what variables need to be stored on the stack
|
|
% at the resumption point established by the goal.
|
|
%
|
|
% For parallel conjunctions and loop control scopes, the
|
|
% stackvars pass will set this argument to need_par_conj(NPC),
|
|
% where NPC specifies what variables are required to be stored
|
|
% on the stack by the parallel conjunction and loop control
|
|
% execution mechanisms.
|
|
maybe_need :: maybe_need
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
goal_info_get_pre_births(GoalInfo, PreBirths) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
( if PreBirthsPrime = CodeGenInfo ^ llds_code_gen ^ pre_births then
|
|
PreBirths = PreBirthsPrime
|
|
else
|
|
unexpected($pred, "no code_gen_info")
|
|
).
|
|
|
|
goal_info_get_post_births(GoalInfo, PostBirths) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
( if PostBirthsPrime = CodeGenInfo ^ llds_code_gen ^ post_births then
|
|
PostBirths = PostBirthsPrime
|
|
else
|
|
unexpected($pred, "no code_gen_info")
|
|
).
|
|
|
|
goal_info_get_pre_deaths(GoalInfo, PreDeaths) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
( if PreDeathsPrime = CodeGenInfo ^ llds_code_gen ^ pre_deaths then
|
|
PreDeaths = PreDeathsPrime
|
|
else
|
|
unexpected($pred, "no code_gen_info")
|
|
).
|
|
|
|
goal_info_get_post_deaths(GoalInfo, PostDeaths) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
( if PostDeathsPrime = CodeGenInfo ^ llds_code_gen ^ post_deaths then
|
|
PostDeaths = PostDeathsPrime
|
|
else
|
|
unexpected($pred, "no code_gen_info")
|
|
).
|
|
|
|
goal_info_get_follow_vars(GoalInfo, FollowVars) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
( if FollowVarsPrime = CodeGenInfo ^ llds_code_gen ^ follow_vars then
|
|
FollowVars = FollowVarsPrime
|
|
else
|
|
unexpected($pred, "no code_gen_info")
|
|
).
|
|
|
|
goal_info_get_store_map(GoalInfo, StoreMap) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
( if StoreMapPrime = CodeGenInfo ^ llds_code_gen ^ store_map then
|
|
StoreMap = StoreMapPrime
|
|
else
|
|
unexpected($pred, "no code_gen_info")
|
|
).
|
|
|
|
goal_info_get_resume_point(GoalInfo, ResumePoint) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
( if ResumePointPrime = CodeGenInfo ^ llds_code_gen ^ resume_point then
|
|
ResumePoint = ResumePointPrime
|
|
else
|
|
unexpected($pred, "no code_gen_info")
|
|
).
|
|
|
|
goal_info_get_maybe_need_across_call(GoalInfo, MaybeNeedAtCall) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
( if MaybeNeed = CodeGenInfo ^ llds_code_gen ^ maybe_need then
|
|
(
|
|
MaybeNeed = need_call(NeedAtCall),
|
|
MaybeNeedAtCall = yes(NeedAtCall)
|
|
;
|
|
( MaybeNeed = need_resume(_)
|
|
; MaybeNeed = need_par_conj(_)
|
|
; MaybeNeed = no_need
|
|
),
|
|
MaybeNeedAtCall = no
|
|
)
|
|
else
|
|
unexpected($pred, "no code_gen_info")
|
|
).
|
|
|
|
goal_info_get_maybe_need_in_resume(GoalInfo, MaybeNeedInResume) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
( if MaybeNeed = CodeGenInfo ^ llds_code_gen ^ maybe_need then
|
|
(
|
|
MaybeNeed = need_resume(NeedInResume),
|
|
MaybeNeedInResume = yes(NeedInResume)
|
|
;
|
|
( MaybeNeed = need_call(_)
|
|
; MaybeNeed = need_par_conj(_)
|
|
; MaybeNeed = no_need
|
|
),
|
|
MaybeNeedInResume = no
|
|
)
|
|
else
|
|
unexpected($pred, "no code_gen_info")
|
|
).
|
|
|
|
goal_info_get_maybe_need_in_par_conj(GoalInfo, MaybeNeedInParConj) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
( if MaybeNeed = CodeGenInfo ^ llds_code_gen ^ maybe_need then
|
|
(
|
|
MaybeNeed = need_par_conj(NeedInParConj),
|
|
MaybeNeedInParConj = yes(NeedInParConj)
|
|
;
|
|
( MaybeNeed = need_call(_)
|
|
; MaybeNeed = need_resume(_)
|
|
; MaybeNeed = no_need
|
|
),
|
|
MaybeNeedInParConj = no
|
|
)
|
|
else
|
|
unexpected($pred, "no code_gen_info")
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
goal_info_maybe_get_pre_births(GoalInfo, PreBirths) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
PreBirths = CodeGenInfo ^ llds_code_gen ^ pre_births.
|
|
|
|
goal_info_maybe_get_post_births(GoalInfo, PostBirths) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
PostBirths = CodeGenInfo ^ llds_code_gen ^ post_births.
|
|
|
|
goal_info_maybe_get_pre_deaths(GoalInfo, PreDeaths) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
PreDeaths = CodeGenInfo ^ llds_code_gen ^ pre_deaths.
|
|
|
|
goal_info_maybe_get_post_deaths(GoalInfo, PostDeaths) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
PostDeaths = CodeGenInfo ^ llds_code_gen ^ post_deaths.
|
|
|
|
goal_info_maybe_get_follow_vars(GoalInfo, FollowVars) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
FollowVars = CodeGenInfo ^ llds_code_gen ^ follow_vars.
|
|
|
|
goal_info_maybe_get_store_map(GoalInfo, StoreMap) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
StoreMap = CodeGenInfo ^ llds_code_gen ^ store_map.
|
|
|
|
goal_info_maybe_get_resume_point(GoalInfo, ResumePoint) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
ResumePoint = CodeGenInfo ^ llds_code_gen ^ resume_point.
|
|
|
|
goal_info_maybe_get_maybe_need_across_call(GoalInfo, MaybeNeedAcrossCall) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
MaybeNeed = CodeGenInfo ^ llds_code_gen ^ maybe_need,
|
|
MaybeNeed = need_call(NeedAcrossCall),
|
|
MaybeNeedAcrossCall = yes(NeedAcrossCall).
|
|
|
|
goal_info_maybe_get_maybe_need_in_resume(GoalInfo, MaybeNeedInResume) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
MaybeNeed = CodeGenInfo ^ llds_code_gen ^ maybe_need,
|
|
MaybeNeed = need_resume(NeedInResume),
|
|
MaybeNeedInResume = yes(NeedInResume).
|
|
|
|
goal_info_maybe_get_maybe_need_in_par_conj(GoalInfo, MaybeNeedInParConj) :-
|
|
CodeGenInfo = goal_info_get_code_gen_info(GoalInfo),
|
|
MaybeNeed = CodeGenInfo ^ llds_code_gen ^ maybe_need,
|
|
MaybeNeed = need_par_conj(NeedInParConj),
|
|
MaybeNeedInParConj = yes(NeedInParConj).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
goal_info_initialize_liveness_info(PreBirths, PostBirths,
|
|
PreDeaths, PostDeaths, ResumePoint, !GoalInfo) :-
|
|
CodeGenInfo0 = goal_info_get_code_gen_info(!.GoalInfo),
|
|
some [!LLDSInfo] (
|
|
!:LLDSInfo = get_details(CodeGenInfo0),
|
|
!LLDSInfo ^ pre_births := PreBirths,
|
|
!LLDSInfo ^ post_births := PostBirths,
|
|
!LLDSInfo ^ pre_deaths := PreDeaths,
|
|
!LLDSInfo ^ post_deaths := PostDeaths,
|
|
!LLDSInfo ^ resume_point := ResumePoint,
|
|
CodeGenInfo = llds_code_gen_info(!.LLDSInfo)
|
|
),
|
|
goal_info_set_code_gen_info(CodeGenInfo, !GoalInfo).
|
|
|
|
goal_info_set_pre_births(PreBirths, !GoalInfo) :-
|
|
CodeGenInfo0 = goal_info_get_code_gen_info(!.GoalInfo),
|
|
LLDSInfo0 = get_details(CodeGenInfo0),
|
|
LLDSInfo = LLDSInfo0 ^ pre_births := PreBirths,
|
|
CodeGenInfo = llds_code_gen_info(LLDSInfo),
|
|
goal_info_set_code_gen_info(CodeGenInfo, !GoalInfo).
|
|
|
|
goal_info_set_post_births(PostBirths, !GoalInfo) :-
|
|
CodeGenInfo0 = goal_info_get_code_gen_info(!.GoalInfo),
|
|
LLDSInfo0 = get_details(CodeGenInfo0),
|
|
LLDSInfo = LLDSInfo0 ^ post_births := PostBirths,
|
|
CodeGenInfo = llds_code_gen_info(LLDSInfo),
|
|
goal_info_set_code_gen_info(CodeGenInfo, !GoalInfo).
|
|
|
|
goal_info_set_pre_deaths(PreDeaths, !GoalInfo) :-
|
|
CodeGenInfo0 = goal_info_get_code_gen_info(!.GoalInfo),
|
|
LLDSInfo0 = get_details(CodeGenInfo0),
|
|
LLDSInfo = LLDSInfo0 ^ pre_deaths := PreDeaths,
|
|
CodeGenInfo = llds_code_gen_info(LLDSInfo),
|
|
goal_info_set_code_gen_info(CodeGenInfo, !GoalInfo).
|
|
|
|
goal_info_set_post_deaths(PostDeaths, !GoalInfo) :-
|
|
CodeGenInfo0 = goal_info_get_code_gen_info(!.GoalInfo),
|
|
LLDSInfo0 = get_details(CodeGenInfo0),
|
|
LLDSInfo = LLDSInfo0 ^ post_deaths := PostDeaths,
|
|
CodeGenInfo = llds_code_gen_info(LLDSInfo),
|
|
goal_info_set_code_gen_info(CodeGenInfo, !GoalInfo).
|
|
|
|
goal_info_set_follow_vars(FollowVars, !GoalInfo) :-
|
|
CodeGenInfo0 = goal_info_get_code_gen_info(!.GoalInfo),
|
|
LLDSInfo0 = get_details(CodeGenInfo0),
|
|
LLDSInfo = LLDSInfo0 ^ follow_vars := FollowVars,
|
|
CodeGenInfo = llds_code_gen_info(LLDSInfo),
|
|
goal_info_set_code_gen_info(CodeGenInfo, !GoalInfo).
|
|
|
|
goal_info_set_store_map(StoreMap, !GoalInfo) :-
|
|
CodeGenInfo0 = goal_info_get_code_gen_info(!.GoalInfo),
|
|
LLDSInfo0 = get_details(CodeGenInfo0),
|
|
LLDSInfo = LLDSInfo0 ^ store_map := StoreMap,
|
|
CodeGenInfo = llds_code_gen_info(LLDSInfo),
|
|
goal_info_set_code_gen_info(CodeGenInfo, !GoalInfo).
|
|
|
|
goal_info_set_resume_point(ResumePoint, !GoalInfo) :-
|
|
CodeGenInfo0 = goal_info_get_code_gen_info(!.GoalInfo),
|
|
LLDSInfo0 = get_details(CodeGenInfo0),
|
|
LLDSInfo = LLDSInfo0 ^ resume_point := ResumePoint,
|
|
CodeGenInfo = llds_code_gen_info(LLDSInfo),
|
|
goal_info_set_code_gen_info(CodeGenInfo, !GoalInfo).
|
|
|
|
goal_info_set_need_across_call(NeedAcrossCall, !GoalInfo) :-
|
|
CodeGenInfo0 = goal_info_get_code_gen_info(!.GoalInfo),
|
|
LLDSInfo0 = get_details(CodeGenInfo0),
|
|
LLDSInfo = LLDSInfo0 ^ maybe_need := need_call(NeedAcrossCall),
|
|
CodeGenInfo = llds_code_gen_info(LLDSInfo),
|
|
goal_info_set_code_gen_info(CodeGenInfo, !GoalInfo).
|
|
|
|
goal_info_set_need_in_resume(NeedInResume, !GoalInfo) :-
|
|
CodeGenInfo0 = goal_info_get_code_gen_info(!.GoalInfo),
|
|
LLDSInfo0 = get_details(CodeGenInfo0),
|
|
LLDSInfo = LLDSInfo0 ^ maybe_need := need_resume(NeedInResume),
|
|
CodeGenInfo = llds_code_gen_info(LLDSInfo),
|
|
goal_info_set_code_gen_info(CodeGenInfo, !GoalInfo).
|
|
|
|
goal_info_set_need_in_par_conj(NeedInParConj, !GoalInfo) :-
|
|
CodeGenInfo0 = goal_info_get_code_gen_info(!.GoalInfo),
|
|
LLDSInfo0 = get_details(CodeGenInfo0),
|
|
LLDSInfo = LLDSInfo0 ^ maybe_need := need_par_conj(NeedInParConj),
|
|
CodeGenInfo = llds_code_gen_info(LLDSInfo),
|
|
goal_info_set_code_gen_info(CodeGenInfo, !GoalInfo).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
goal_set_follow_vars(FollowVars, hlds_goal(GoalExpr, GoalInfo0),
|
|
hlds_goal(GoalExpr, GoalInfo)) :-
|
|
goal_info_set_follow_vars(FollowVars, GoalInfo0, GoalInfo).
|
|
|
|
goal_set_resume_point(ResumePoint, hlds_goal(GoalExpr, GoalInfo0),
|
|
hlds_goal(GoalExpr, GoalInfo)) :-
|
|
goal_info_set_resume_point(ResumePoint, GoalInfo0, GoalInfo).
|
|
|
|
goal_info_resume_vars_and_loc(Resume, Vars, Locs) :-
|
|
(
|
|
Resume = resume_point(Vars, Locs)
|
|
;
|
|
Resume = no_resume_point,
|
|
unexpected($pred, "no resume point")
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- func get_details(hlds_goal_code_gen_info) = llds_code_gen_details.
|
|
|
|
get_details(no_code_gen_info) = init_llds_code_gen_details.
|
|
get_details(llds_code_gen_info(LLDSInfo)) = LLDSInfo.
|
|
|
|
:- func init_llds_code_gen_details = llds_code_gen_details.
|
|
|
|
init_llds_code_gen_details =
|
|
llds_code_gen_details(set_of_var.init, set_of_var.init,
|
|
set_of_var.init, set_of_var.init,
|
|
no, map.init, no_resume_point, no_need).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
rename_vars_in_llds_code_gen_info(Must, Subn, Details0, Details) :-
|
|
Details0 = llds_code_gen_details(PreBirths0, PostBirths0,
|
|
PreDeaths0, PostDeaths0, MaybeFollowVars0, StoreMap0,
|
|
ResumePoint0, MaybeNeed0),
|
|
rename_vars_in_set_of_var(Must, Subn, PreBirths0, PreBirths),
|
|
rename_vars_in_set_of_var(Must, Subn, PostBirths0, PostBirths),
|
|
rename_vars_in_set_of_var(Must, Subn, PreDeaths0, PreDeaths),
|
|
rename_vars_in_set_of_var(Must, Subn, PostDeaths0, PostDeaths),
|
|
(
|
|
MaybeFollowVars0 = no,
|
|
MaybeFollowVars = no
|
|
;
|
|
MaybeFollowVars0 = yes(FollowVars0),
|
|
FollowVars0 = abs_follow_vars(FollowVarsMap0, FirstFreeRegR,
|
|
FirstFreeRegF),
|
|
rename_vars_in_var_locn_map(Must, Subn,
|
|
FollowVarsMap0, FollowVarsMap),
|
|
FollowVars = abs_follow_vars(FollowVarsMap, FirstFreeRegR,
|
|
FirstFreeRegF),
|
|
MaybeFollowVars = yes(FollowVars)
|
|
),
|
|
rename_vars_in_var_locn_map(Must, Subn, StoreMap0, StoreMap),
|
|
(
|
|
ResumePoint0 = no_resume_point,
|
|
ResumePoint = no_resume_point
|
|
;
|
|
ResumePoint0 = resume_point(ResumePointVars0, ResumeLocs),
|
|
rename_vars_in_set_of_var(Must, Subn,
|
|
ResumePointVars0, ResumePointVars),
|
|
ResumePoint = resume_point(ResumePointVars, ResumeLocs)
|
|
),
|
|
(
|
|
MaybeNeed0 = no_need,
|
|
MaybeNeed = no_need
|
|
;
|
|
MaybeNeed0 = need_call(NeedAcrossCall0),
|
|
NeedAcrossCall0 = need_across_call(ForwardVars0,
|
|
CallResumeVars0, CallNondetLiveVars0),
|
|
rename_vars_in_set_of_var(Must, Subn, ForwardVars0, ForwardVars),
|
|
rename_vars_in_set_of_var(Must, Subn, CallResumeVars0, CallResumeVars),
|
|
rename_vars_in_set_of_var(Must, Subn,
|
|
CallNondetLiveVars0, CallNondetLiveVars),
|
|
NeedAcrossCall = need_across_call(ForwardVars,
|
|
CallResumeVars, CallNondetLiveVars),
|
|
MaybeNeed = need_call(NeedAcrossCall)
|
|
;
|
|
MaybeNeed0 = need_resume(NeedInResume0),
|
|
NeedInResume0 = need_in_resume(OnStack, ResumeVars0, NondetLiveVars0),
|
|
rename_vars_in_set_of_var(Must, Subn, ResumeVars0, ResumeVars),
|
|
rename_vars_in_set_of_var(Must, Subn, NondetLiveVars0, NondetLiveVars),
|
|
NeedInResume = need_in_resume(OnStack, ResumeVars, NondetLiveVars),
|
|
MaybeNeed = need_resume(NeedInResume)
|
|
;
|
|
MaybeNeed0 = need_par_conj(NeedInParConj0),
|
|
NeedInParConj0 = need_in_par_conj(ParConjVars0),
|
|
rename_vars_in_set_of_var(Must, Subn, ParConjVars0, ParConjVars),
|
|
NeedInParConj = need_in_par_conj(ParConjVars),
|
|
MaybeNeed = need_par_conj(NeedInParConj)
|
|
),
|
|
Details = llds_code_gen_details(PreBirths, PostBirths,
|
|
PreDeaths, PostDeaths, MaybeFollowVars, StoreMap,
|
|
ResumePoint, MaybeNeed).
|
|
|
|
:- pred rename_vars_in_var_locn_map(must_rename::in,
|
|
map(prog_var, prog_var)::in,
|
|
map(prog_var, abs_locn)::in, map(prog_var, abs_locn)::out) is det.
|
|
|
|
rename_vars_in_var_locn_map(Must, Subn, VarLocnMap0, VarLocnMap) :-
|
|
map.to_assoc_list(VarLocnMap0, VarLocnList0),
|
|
rename_vars_in_var_locn_list(Must, Subn, VarLocnList0, VarLocnList),
|
|
map.from_assoc_list(VarLocnList, VarLocnMap).
|
|
|
|
:- pred rename_vars_in_var_locn_list(must_rename::in,
|
|
map(prog_var, prog_var)::in,
|
|
assoc_list(prog_var, abs_locn)::in, assoc_list(prog_var, abs_locn)::out)
|
|
is det.
|
|
|
|
rename_vars_in_var_locn_list(_Must, _Subn, [], []).
|
|
rename_vars_in_var_locn_list(Must, Subn,
|
|
[Var0 - Locn | VarLocns0], [Var - Locn | VarLocns]) :-
|
|
rename_var(Must, Subn, Var0, Var),
|
|
rename_vars_in_var_locn_list(Must, Subn, VarLocns0, VarLocns).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
stack_slot_num(StackSlot) = N :-
|
|
(
|
|
StackSlot = det_slot(N, Width)
|
|
;
|
|
StackSlot = parent_det_slot(N, Width)
|
|
;
|
|
StackSlot = nondet_slot(N),
|
|
Width = single_width
|
|
),
|
|
(
|
|
Width = single_width
|
|
;
|
|
Width = double_width,
|
|
unexpected($pred, "double_width")
|
|
).
|
|
|
|
stack_slot_to_abs_locn(StackSlot) = AbsLocn :-
|
|
(
|
|
StackSlot = det_slot(N, Width),
|
|
AbsLocn = abs_stackvar(N, Width)
|
|
;
|
|
StackSlot = parent_det_slot(N, Width),
|
|
AbsLocn = abs_parent_stackvar(N, Width)
|
|
;
|
|
StackSlot = nondet_slot(N),
|
|
AbsLocn = abs_framevar(N)
|
|
).
|
|
|
|
key_stack_slot_to_abs_locn(_, Slot) =
|
|
stack_slot_to_abs_locn(Slot).
|
|
|
|
abs_locn_to_string(Locn, Str, MaybeWidth) :-
|
|
(
|
|
Locn = any_reg,
|
|
Str = "any_reg",
|
|
MaybeWidth = no
|
|
;
|
|
Locn = abs_reg(reg_r, N),
|
|
Str = "r" ++ int_to_string(N),
|
|
MaybeWidth = no
|
|
;
|
|
Locn = abs_reg(reg_f, N),
|
|
Str = "f" ++ int_to_string(N),
|
|
MaybeWidth = no
|
|
;
|
|
Locn = abs_stackvar(N, Width),
|
|
Str = "stackvar" ++ int_to_string(N),
|
|
MaybeWidth = stack_slot_width_to_string(Width)
|
|
;
|
|
Locn = abs_parent_stackvar(N, Width),
|
|
Str = "parent_stackvar" ++ int_to_string(N),
|
|
MaybeWidth = stack_slot_width_to_string(Width)
|
|
;
|
|
Locn = abs_framevar(N),
|
|
Str = "framevar" ++ int_to_string(N),
|
|
MaybeWidth = no
|
|
).
|
|
|
|
:- func stack_slot_width_to_string(stack_slot_width) = maybe(string).
|
|
|
|
stack_slot_width_to_string(single_width) = no.
|
|
stack_slot_width_to_string(double_width) = yes("(double width)").
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module hlds.hlds_llds.
|
|
%-----------------------------------------------------------------------------%
|