mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-19 15:54:18 +00:00
Estimated hours taken: 4 Branches: main compiler/*.m: Use expect/3 in place of require/2 throughout most of the compiler. Use unexpected/2 (or sorry/2) in place of error/1 in more places. Fix more dodgy assertion error messages. s/map(prog_var, mer_type)/vartypes/ where the latter is meant.
220 lines
8.4 KiB
Mathematica
220 lines
8.4 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2000-2005 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: mark_static_terms.m.
|
|
% Main author: fjh.
|
|
|
|
% This module traverses the HLDS, updating the `how_to_construct' field of
|
|
% construction unifications. For each construction which can be done
|
|
% statically, i.e. whose arguments are all static, it replaces this field with
|
|
% `construct_statically'. This field is then used by the MLDS back-end to
|
|
% determine when it can generate static initialized constants rather than
|
|
% using new_object() MLDS statements.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module ml_backend__mark_static_terms.
|
|
:- interface.
|
|
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module hlds.hlds_pred.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
|
|
:- pred mark_static_terms(module_info::in, proc_info::in, proc_info::out)
|
|
is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module hlds.hlds_data.
|
|
:- import_module hlds.hlds_goal.
|
|
:- import_module libs.compiler_util.
|
|
:- import_module parse_tree.prog_data.
|
|
|
|
:- import_module bool.
|
|
:- import_module int.
|
|
:- import_module list.
|
|
:- import_module map.
|
|
:- import_module std_util.
|
|
:- import_module svmap.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% As we traverse the goal, we keep track of which variables are static at
|
|
% the current program point, and for each such variable, we keep
|
|
% information on how to construct it.
|
|
%
|
|
:- type static_info == map(prog_var, static_cons).
|
|
|
|
mark_static_terms(_ModuleInfo, !Proc) :-
|
|
% The ModuleInfo argument is there just for passes_aux.
|
|
proc_info_goal(!.Proc, Goal0),
|
|
map__init(StaticInfo0),
|
|
goal_mark_static_terms(Goal0, Goal, StaticInfo0, _StaticInfo),
|
|
proc_info_set_goal(Goal, !Proc).
|
|
|
|
:- pred goal_mark_static_terms(hlds_goal::in, hlds_goal::out,
|
|
static_info::in, static_info::out) is det.
|
|
|
|
goal_mark_static_terms(GoalExpr0 - GoalInfo, GoalExpr - GoalInfo, !SI) :-
|
|
goal_expr_mark_static_terms(GoalExpr0, GoalExpr, !SI).
|
|
|
|
:- pred goal_expr_mark_static_terms(hlds_goal_expr::in, hlds_goal_expr::out,
|
|
static_info::in, static_info::out) is det.
|
|
|
|
goal_expr_mark_static_terms(conj(Goals0), conj(Goals), !SI) :-
|
|
conj_mark_static_terms(Goals0, Goals, !SI).
|
|
|
|
goal_expr_mark_static_terms(par_conj(Goals0), par_conj(Goals), !SI) :-
|
|
% It's OK to treat parallel conjunctions as if they were sequential here,
|
|
% since if we mark any variables as static, the computation of those
|
|
% variables will be done at compile time.
|
|
conj_mark_static_terms(Goals0, Goals, !SI).
|
|
|
|
goal_expr_mark_static_terms(disj(Goals0), disj(Goals), !SI) :-
|
|
% We revert to the original static_info at the end of branched goals.
|
|
disj_mark_static_terms(Goals0, Goals, !.SI).
|
|
|
|
goal_expr_mark_static_terms(switch(A, B, Cases0), switch(A, B, Cases), !SI) :-
|
|
% We revert to the original static_info at the end of branched goals.
|
|
cases_mark_static_terms(Cases0, Cases, !.SI).
|
|
|
|
goal_expr_mark_static_terms(not(Goal0), not(Goal), !SI) :-
|
|
% We revert to the original static_info at the end of the negation.
|
|
goal_mark_static_terms(Goal0, Goal, !.SI, _SI).
|
|
|
|
goal_expr_mark_static_terms(scope(A, Goal0), scope(A, Goal), !SI) :-
|
|
goal_mark_static_terms(Goal0, Goal, !SI).
|
|
|
|
goal_expr_mark_static_terms(if_then_else(A, Cond0, Then0, Else0),
|
|
if_then_else(A, Cond, Then, Else), SI0, SI0) :-
|
|
% We run the Cond and the Then in sequence, and we run the Else
|
|
% in parallel with that, and then we throw away the static_infos
|
|
% we computed and revert to the original static_info at the end,
|
|
% since this was a branched goal.
|
|
goal_mark_static_terms(Cond0, Cond, SI0, SI_Cond),
|
|
goal_mark_static_terms(Then0, Then, SI_Cond, _SI_Then),
|
|
goal_mark_static_terms(Else0, Else, SI0, _SI_Else).
|
|
|
|
goal_expr_mark_static_terms(Goal @ call(_, _, _, _, _, _), Goal, !SI).
|
|
|
|
goal_expr_mark_static_terms(Goal @ generic_call(_, _, _, _), Goal, !SI).
|
|
|
|
goal_expr_mark_static_terms(unify(LHS, RHS, Mode, Unification0, Context),
|
|
unify(LHS, RHS, Mode, Unification, Context), !SI) :-
|
|
unification_mark_static_terms(Unification0, Unification, !SI).
|
|
|
|
goal_expr_mark_static_terms(Goal @ foreign_proc(_, _, _, _, _, _), Goal, !SI).
|
|
|
|
goal_expr_mark_static_terms(shorthand(_), _, !SI) :-
|
|
% These should have been expanded out by now.
|
|
unexpected(this_file, "fill_expr_slots: unexpected shorthand").
|
|
|
|
:- pred conj_mark_static_terms(hlds_goals::in, hlds_goals::out,
|
|
static_info::in, static_info::out) is det.
|
|
|
|
conj_mark_static_terms(Goals0, Goals, !SI) :-
|
|
list__map_foldl(goal_mark_static_terms, Goals0, Goals, !SI).
|
|
|
|
:- pred disj_mark_static_terms(hlds_goals::in, hlds_goals::out,
|
|
static_info::in) is det.
|
|
|
|
disj_mark_static_terms([], [], _).
|
|
disj_mark_static_terms([Goal0 | Goals0], [Goal | Goals], SI0) :-
|
|
% We throw away the static_info obtained after each branch.
|
|
goal_mark_static_terms(Goal0, Goal, SI0, _SI),
|
|
disj_mark_static_terms(Goals0, Goals, SI0).
|
|
|
|
:- pred cases_mark_static_terms(list(case)::in, list(case)::out,
|
|
static_info::in) is det.
|
|
|
|
cases_mark_static_terms([], [], _SI0).
|
|
cases_mark_static_terms([Case0 | Cases0], [Case | Cases], SI0) :-
|
|
Case0 = case(ConsId, Goal0),
|
|
% We throw away the static_info obtained after each branch.
|
|
goal_mark_static_terms(Goal0, Goal, SI0, _SI),
|
|
Case = case(ConsId, Goal),
|
|
cases_mark_static_terms(Cases0, Cases, SI0).
|
|
|
|
:- pred unification_mark_static_terms(unification::in, unification::out,
|
|
static_info::in, static_info::out) is det.
|
|
|
|
unification_mark_static_terms(Unification0, Unification, !StaticVars) :-
|
|
(
|
|
Unification0 = construct(Var, ConsId, ArgVars, D, HowToConstruct0,
|
|
F, G),
|
|
(
|
|
% If all the arguments are static, then the newly constructed
|
|
% variable is static too.
|
|
list__map(map__search(!.StaticVars), ArgVars, StaticArgs)
|
|
->
|
|
HowToConstruct = construct_statically(StaticArgs),
|
|
svmap__det_insert(Var, static_cons(ConsId, ArgVars, StaticArgs),
|
|
!StaticVars)
|
|
;
|
|
HowToConstruct = HowToConstruct0
|
|
),
|
|
( HowToConstruct = HowToConstruct0 ->
|
|
% This is a minor optimization to improve the efficiency of the
|
|
% compiler: don't bother allocating memory if we don't need to.
|
|
Unification = Unification0
|
|
;
|
|
Unification = construct(Var, ConsId, ArgVars, D, HowToConstruct,
|
|
F, G)
|
|
)
|
|
;
|
|
Unification0 = deconstruct(_Var, _ConsId, _ArgVars, _UniModes,
|
|
_CanFail, _CanCGC),
|
|
Unification = Unification0
|
|
% (
|
|
% % if the variable being deconstructed is static,
|
|
% % and the deconstruction cannot fail,
|
|
% % then the newly extracted argument variables
|
|
% % are static too
|
|
% % (XXX is the "cannot fail" bit really necessary?)
|
|
% map__search(StaticVars0, Var, Data),
|
|
% CanFail = cannot_fail
|
|
% ->
|
|
% XXX insert ArgVars into StaticVars0
|
|
% ;
|
|
% true
|
|
% )
|
|
;
|
|
Unification0 = assign(TargetVar, SourceVar),
|
|
Unification = Unification0,
|
|
(
|
|
% If the variable being assign from is static,
|
|
% then the variable being assigned to is static too.
|
|
map__search(!.StaticVars, SourceVar, Data)
|
|
->
|
|
svmap__det_insert(TargetVar, Data, !StaticVars)
|
|
;
|
|
true
|
|
)
|
|
;
|
|
Unification0 = simple_test(_, _),
|
|
Unification = Unification0
|
|
;
|
|
Unification0 = complicated_unify(_, _, _),
|
|
Unification = Unification0
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- func this_file = string.
|
|
|
|
this_file = "mark_static_terms.m".
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module mark_static_terms.
|
|
%-----------------------------------------------------------------------------%
|