mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-30 00:34:40 +00:00
Estimated hours taken: 30+
arg_info:
Fix allocation to work properly for --args compact.
bytecode*:
Handle complex deconstruction unifications. Not really tested because
I can't find a test case.
bytecode_gen, call_gen, code_util:
Use the new method to handle builtin predicates/functions. We now
handle reverse mode arithmetic and unary plus/minus as builtins.
code_gen, code_init, follow_vars, hlds_pred:
Put back the initial follow_vars field of the proc_info, since this
may allow the code generator to emit better code at the starts of
of predicates.
inlining:
Don't inline recursive predicates.
goals_util:
Add a predicate to find out if a goal calls a particular predicate.
Used in inlining to find out if a predicate is recursive.
unused_args:
Remove code that used to set the mode of unused args to free->free.
Since this changes the arg from top_in to top_unused *without* code
in other modules being aware of the change, this screws up --args
compact.
llds, llds_out, garbage_out:
Prepare for the move to the new type_info structure by adding a new
"module" type for defining structures holding type_infos. Not
currently generated or output.
llds, opt_debug, opt_util, vn_type, vn_cost, vn_temploc:
Change the argument of temp to be a reg, not an int, allowing
floating point temporaries.
vn_type:
Add information about the number of floating point registers and
temporaries to the parameter structure (these are currently unused).
llds, dupelim, frameopt, livemap, middle_rec, value_number, vn_filter,
vn_verify:
Add an extra field to blocks giving the number of float temporaries.
options:
Add parameters to configure the number of floating point registers
and temporaries.
mercury_compile:
Add an extra excess assign phase at the start of the middle pass.
This should reduce the size of the code manipulated by the other
phases, and gives more accurate size information to inlining.
(The excess assign phase before code generation is I think still
needed since optimizations can introduce such assignments.)
value_number:
Optimize code sequences before and after assignments to curfr
separately, since such assignments change the meaning of framevars.
This fixes the bug that caused singleton variable warnings to contain
garbage.
vn_block, vn_flush, vn_order, vn_util:
Add special handling of assignments to curfr. This is probably
unnecessary after my change to value_number, and will be removed
again shortly :-(
vn_flush:
Improve the code generated by value numbering (1) by computing values
into the place that needs them in some special circumstances, and
(2) by fixing a bug that did not consider special registers to be
as fast as r1 etc.
vn_util:
Improve the code generated by value numbering by removing duplicates
from the list of uses of a value before trying to find out if there
is more than one use.
simplify:
Avoid overzealous optimization of main --> { ..., error(...) }.
handle_options:
Fix an error message.
code_aux:
Break an excessive long line.
880 lines
32 KiB
Mathematica
880 lines
32 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1995 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.
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% This module defines the part of the HLDS that deals with predicates
|
|
% and procedures.
|
|
|
|
% Main authors: fjh, conway.
|
|
|
|
:- module hlds_pred.
|
|
|
|
:- interface.
|
|
|
|
:- import_module bool, int, string, list, map, std_util, varset.
|
|
:- import_module hlds_data, hlds_goal, hlds_module, prog_data.
|
|
|
|
:- implementation.
|
|
|
|
:- import_module make_hlds, prog_util, mode_util.
|
|
:- import_module set, require.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- interface.
|
|
|
|
% A proc_id is a mode number within a particular predicate -
|
|
% not to be confused with a mode_id, which is the name of a
|
|
% user-defined mode.
|
|
|
|
:- type proc_id == int.
|
|
:- type pred_id == int.
|
|
|
|
:- type pred_info.
|
|
:- type proc_info.
|
|
|
|
:- type proc_table == map(proc_id, proc_info).
|
|
|
|
:- type pred_call_id ---> sym_name / arity.
|
|
|
|
:- type pred_proc_id ---> proc(pred_id, proc_id).
|
|
:- type pred_proc_list == list(pred_proc_id).
|
|
|
|
:- type clauses_info ---> clauses_info(
|
|
varset, % variable names
|
|
map(var, type), % variable types
|
|
list(var), % head vars
|
|
list(clause)
|
|
).
|
|
|
|
:- type clause ---> clause(
|
|
list(proc_id), % modes for which
|
|
% this clause applies
|
|
hlds__goal, % Body
|
|
term__context
|
|
).
|
|
|
|
% The type of goals that have been given for a pred.
|
|
|
|
:- type goal_type ---> pragmas % pragma(c_code, ...)
|
|
; clauses
|
|
; none.
|
|
|
|
% Note: `liveness' and `liveness_info' record liveness in the sense
|
|
% used by code generation. This is *not* the same thing as the notion
|
|
% of liveness used by mode analysis! See compiler/notes/GLOSSARY.
|
|
|
|
:- type liveness_info == set(var). % The live variables
|
|
|
|
:- type liveness ---> live
|
|
; dead.
|
|
|
|
:- type arg_info ---> arg_info(
|
|
arg_loc, % stored location
|
|
arg_mode % mode of top functor
|
|
).
|
|
|
|
:- type arg_mode ---> top_in
|
|
; top_out
|
|
; top_unused.
|
|
|
|
:- type arg_loc == int.
|
|
|
|
% The type `import_status' describes whether an entity (a predicate,
|
|
% type, inst, or mode) is local to the current module, exported from
|
|
% the current module, or imported from some other module.
|
|
|
|
:- type import_status
|
|
---> imported % defined in the interface of some other module
|
|
% or `external' (in some other language)
|
|
; pseudo_imported % this is used for entities that are defined
|
|
% in the interface of some other module but
|
|
% for which we may generate some code in
|
|
% this module - in particular, this is used
|
|
% for unification predicates (see comments in
|
|
% unify_proc.m)
|
|
; exported % defined in the interface of this module
|
|
; pseudo_exported % the converse of pseudo_imported
|
|
% this means that only the (in, in) mode
|
|
% of a unification is exported
|
|
; local. % defined in the implementation of this module
|
|
|
|
% N-ary functions are converted into N+1-ary predicates.
|
|
% (Clauses are converted in make_hlds, but calls to functions
|
|
% cannot be converted until after type-checking, once we have
|
|
% resolved overloading. So we do that during mode analysis.)
|
|
% The `is_pred_or_func' field of the pred_info records whether
|
|
% a pred_info is really for a predicate or whether it is for
|
|
% what was originally a function.
|
|
|
|
:- type pred_or_func
|
|
---> predicate
|
|
; function.
|
|
|
|
% Predicates can be marked, to request that transformations be
|
|
% performed on them and to record that these transformations have been
|
|
% done and are still valid.
|
|
%
|
|
% The code that performs the transformation should remove the request
|
|
% marker status and substitute the done marker status.
|
|
%
|
|
% In the future, we can use markers to request the use of a different
|
|
% code generator for certain predicates, e.g. to generate RL instead
|
|
% of normal C code, with a C code stub to link to the RL.
|
|
|
|
:- type marker
|
|
---> infer_type % Requests type inference for the predicate
|
|
% These markers are inserted by make_hlds
|
|
% for undeclared predicates.
|
|
% The `done' status could be meaningful,
|
|
% but it is currently not used.
|
|
; infer_modes % Requests mode inference for the predicate
|
|
% These markers are inserted by make_hlds
|
|
% for undeclared predicates.
|
|
% The `done' status could be meaningful,
|
|
% but it is currently not used.
|
|
; obsolete % Requests warnings if this predicate is used.
|
|
% Used for pragma(obsolete).
|
|
% The `done' status is not meaningful.
|
|
; inline % Requests that this be predicate be inlined.
|
|
% Used for pragma(inline).
|
|
% Since the transformation affects *other*
|
|
% predicates, the `done' status is not
|
|
% meaningful
|
|
; dnf % Requests that this predicate be transformed
|
|
% into disjunctive normal form.
|
|
% Used for pragma(memo).
|
|
; magic % Requests that this predicate be transformed
|
|
% using the magic set transformation
|
|
% Used for pragma(memo).
|
|
; memo. % Requests that this predicate be evaluated
|
|
% using memoing.
|
|
% Used for pragma(memo).
|
|
|
|
:- type marker_status
|
|
---> request(marker)
|
|
; done(marker).
|
|
|
|
% Various predicates for accessing the information stored in the
|
|
% pred_id and pred_info data structures.
|
|
|
|
:- pred pred_info_init(module_name, sym_name, arity, tvarset, list(type),
|
|
condition, term__context, clauses_info, import_status,
|
|
bool, goal_type, pred_or_func, pred_info).
|
|
:- mode pred_info_init(in, in, in, in, in, in, in, in, in, in, in, in, out)
|
|
is det.
|
|
|
|
:- pred pred_info_create(module_name, sym_name, tvarset, list(type),
|
|
condition, term__context, import_status, list(marker_status),
|
|
pred_or_func, proc_info, proc_id, pred_info).
|
|
:- mode pred_info_create(in, in, in, in, in, in, in, in, in, in, out, out)
|
|
is det.
|
|
|
|
:- pred pred_info_set(tvarset, list(type), condition, clauses_info, proc_table,
|
|
term__context, module_name, string, arity, import_status,
|
|
tvarset, goal_type, list(marker_status), pred_or_func, pred_info).
|
|
:- mode pred_info_set(in, in, in, in, in, in, in, in, in, in, in, in, in, in,
|
|
out) is det.
|
|
|
|
:- pred pred_info_module(pred_info, module_name).
|
|
:- mode pred_info_module(in, out) is det.
|
|
|
|
:- pred pred_info_name(pred_info, string).
|
|
:- mode pred_info_name(in, out) is det.
|
|
|
|
:- pred pred_info_arity(pred_info, arity).
|
|
:- mode pred_info_arity(in, out) is det.
|
|
|
|
% Return a list of all the proc_ids for the different modes
|
|
% of this predicate.
|
|
:- pred pred_info_procids(pred_info, list(proc_id)).
|
|
:- mode pred_info_procids(in, out) is det.
|
|
|
|
% Return a list of the proc_ids for all the modes
|
|
% of this predicate that are not imported.
|
|
:- pred pred_info_non_imported_procids(pred_info, list(proc_id)).
|
|
:- mode pred_info_non_imported_procids(in, out) is det.
|
|
|
|
% Return a list of the proc_ids for all the modes
|
|
% of this predicate that are exported.
|
|
:- pred pred_info_exported_procids(pred_info, list(proc_id)).
|
|
:- mode pred_info_exported_procids(in, out) is det.
|
|
|
|
:- pred pred_info_arg_types(pred_info, tvarset, list(type)).
|
|
:- mode pred_info_arg_types(in, out, out) is det.
|
|
|
|
:- pred pred_info_set_arg_types(pred_info, tvarset, list(type), pred_info).
|
|
:- mode pred_info_set_arg_types(in, in, in, out) is det.
|
|
|
|
:- pred pred_info_clauses_info(pred_info, clauses_info).
|
|
:- mode pred_info_clauses_info(in, out) is det.
|
|
|
|
:- pred pred_info_set_clauses_info(pred_info, clauses_info, pred_info).
|
|
:- mode pred_info_set_clauses_info(in, in, out) is det.
|
|
|
|
:- pred pred_info_procedures(pred_info, proc_table).
|
|
:- mode pred_info_procedures(in, out) is det.
|
|
|
|
:- pred pred_info_set_procedures(pred_info, proc_table, pred_info).
|
|
:- mode pred_info_set_procedures(in, in, out) is det.
|
|
|
|
:- pred pred_info_context(pred_info, term__context).
|
|
:- mode pred_info_context(in, out) is det.
|
|
|
|
:- pred pred_info_import_status(pred_info::in, import_status::out) is det.
|
|
|
|
:- pred pred_info_is_imported(pred_info::in) is semidet.
|
|
|
|
:- pred pred_info_is_pseudo_imported(pred_info::in) is semidet.
|
|
|
|
:- pred pred_info_is_exported(pred_info::in) is semidet.
|
|
|
|
:- pred pred_info_is_pseudo_exported(pred_info::in) is semidet.
|
|
|
|
% Set the import_status of the predicate to `imported'.
|
|
% This is used for `:- external(foo/2).' declarations.
|
|
|
|
:- pred pred_info_mark_as_external(pred_info::in, pred_info::out) is det.
|
|
|
|
:- pred pred_info_set_status(pred_info::in, import_status::in,
|
|
pred_info::out) is det.
|
|
|
|
:- pred pred_info_typevarset(pred_info, tvarset).
|
|
:- mode pred_info_typevarset(in, out) is det.
|
|
|
|
:- pred pred_info_set_typevarset(pred_info, tvarset, pred_info).
|
|
:- mode pred_info_set_typevarset(in, in, out) is det.
|
|
|
|
:- pred pred_info_get_goal_type(pred_info, goal_type).
|
|
:- mode pred_info_get_goal_type(in, out) is det.
|
|
|
|
:- pred pred_info_set_goal_type(pred_info, goal_type, pred_info).
|
|
:- mode pred_info_set_goal_type(in, in, out) is det.
|
|
|
|
% Succeeds if there was a `:- pragma(inline, ...)' declaration
|
|
% for this predicate. Note that the compiler may decide
|
|
% to inline a predicate even if there was no pragma(inline, ...)
|
|
% declaration for that predicate.
|
|
|
|
:- pred pred_info_is_inlined(pred_info).
|
|
:- mode pred_info_is_inlined(in) is semidet.
|
|
|
|
:- pred pred_info_get_marker_list(pred_info, list(marker_status)).
|
|
:- mode pred_info_get_marker_list(in, out) is det.
|
|
|
|
:- pred pred_info_set_marker_list(pred_info, list(marker_status), pred_info).
|
|
:- mode pred_info_set_marker_list(in, in, out) is det.
|
|
|
|
:- pred pred_info_get_is_pred_or_func(pred_info, pred_or_func).
|
|
:- mode pred_info_get_is_pred_or_func(in, out) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
% The information specific to a predicate, as opposed to a procedure.
|
|
% Any changes in this type definition will almost certainly require
|
|
% corresponding changes in define.m.
|
|
|
|
:- type pred_info
|
|
---> predicate(
|
|
tvarset, % names of type vars
|
|
% in the predicate's type decl
|
|
list(type), % argument types
|
|
condition, % formal specification
|
|
% (not used)
|
|
|
|
clauses_info,
|
|
|
|
proc_table,
|
|
|
|
term__context, % the location (line #)
|
|
% of the :- pred decl.
|
|
|
|
module_name, % module in which pred occurs
|
|
string, % predicate name
|
|
arity, % the arity of the pred
|
|
import_status,
|
|
tvarset, % names of type vars
|
|
% in the predicate's type decl
|
|
% or in the variable type assignments
|
|
goal_type, % whether the goals seen so far for
|
|
% this pred are clauses,
|
|
% pragma(c_code, ...) decs, or none
|
|
list(marker_status),
|
|
% records which transformations
|
|
% have been done or are to be done
|
|
pred_or_func % whether this "predicate" was really
|
|
% a predicate or a function
|
|
).
|
|
|
|
pred_info_init(ModuleName, SymName, Arity, TypeVarSet, Types, Cond, Context,
|
|
ClausesInfo, Status, Inline, GoalType, PredOrFunc, PredInfo) :-
|
|
map__init(Procs),
|
|
unqualify_name(SymName, PredName),
|
|
sym_name_get_module_name(SymName, ModuleName, PredModuleName),
|
|
( Inline = yes ->
|
|
Markers = [request(inline)]
|
|
;
|
|
Markers = []
|
|
),
|
|
PredInfo = predicate(TypeVarSet, Types, Cond, ClausesInfo, Procs,
|
|
Context, PredModuleName, PredName, Arity, Status, TypeVarSet,
|
|
GoalType, Markers, PredOrFunc).
|
|
|
|
pred_info_create(ModuleName, SymName, TypeVarSet, Types, Cond, Context,
|
|
Status, Markers, PredOrFunc, ProcInfo, ProcId,
|
|
PredInfo) :-
|
|
map__init(Procs0),
|
|
proc_info_declared_determinism(ProcInfo, MaybeDetism),
|
|
next_mode_id(Procs0, MaybeDetism, ProcId),
|
|
map__set(Procs0, ProcId, ProcInfo, Procs),
|
|
list__length(Types, Arity),
|
|
proc_info_variables(ProcInfo, VarSet),
|
|
proc_info_vartypes(ProcInfo, VarTypes),
|
|
proc_info_headvars(ProcInfo, HeadVars),
|
|
unqualify_name(SymName, PredName),
|
|
% The empty list of clauses is a little white lie.
|
|
ClausesInfo = clauses_info(VarSet, VarTypes, HeadVars, []),
|
|
PredInfo = predicate(TypeVarSet, Types, Cond, ClausesInfo, Procs,
|
|
Context, ModuleName, PredName, Arity, Status, TypeVarSet,
|
|
clauses, Markers, PredOrFunc).
|
|
|
|
pred_info_set(HeadTVarSet, Types, Cond, ClausesInfo, Procs, Context,
|
|
PredModuleName, PredName, Arity, Status, AllTVarSet,
|
|
GoalType, Markers, PredOrFunc, PredInfo) :-
|
|
PredInfo = predicate(HeadTVarSet, Types, Cond, ClausesInfo, Procs,
|
|
Context, PredModuleName, PredName, Arity, Status, AllTVarSet,
|
|
GoalType, Markers, PredOrFunc).
|
|
|
|
pred_info_procids(PredInfo, ProcIds) :-
|
|
PredInfo = predicate(_, _, _, _, Procs, _, _, _, _, _, _, _, _, _),
|
|
map__keys(Procs, ProcIds).
|
|
|
|
pred_info_non_imported_procids(PredInfo, ProcIds) :-
|
|
pred_info_import_status(PredInfo, ImportStatus),
|
|
( ImportStatus = imported ->
|
|
ProcIds = []
|
|
; ImportStatus = pseudo_imported ->
|
|
pred_info_procids(PredInfo, ProcIds0),
|
|
% for pseduo_imported preds, procid 0 is imported
|
|
list__delete_all(ProcIds0, 0, ProcIds)
|
|
;
|
|
pred_info_procids(PredInfo, ProcIds)
|
|
).
|
|
|
|
pred_info_exported_procids(PredInfo, ProcIds) :-
|
|
pred_info_import_status(PredInfo, ImportStatus),
|
|
( ImportStatus = exported ->
|
|
pred_info_procids(PredInfo, ProcIds)
|
|
; ImportStatus = pseudo_exported ->
|
|
ProcIds = [0]
|
|
;
|
|
ProcIds = []
|
|
).
|
|
|
|
pred_info_clauses_info(PredInfo, Clauses) :-
|
|
PredInfo = predicate(_, _, _, Clauses, _, _, _, _, _, _, _, _, _, _).
|
|
|
|
pred_info_set_clauses_info(PredInfo0, Clauses, PredInfo) :-
|
|
PredInfo0 = predicate(A, B, C, _, E, F, G, H, I, J, K, L, M, N),
|
|
PredInfo = predicate(A, B, C, Clauses, E, F, G, H, I, J, K, L, M, N).
|
|
|
|
pred_info_arg_types(PredInfo, TypeVars, ArgTypes) :-
|
|
PredInfo = predicate(TypeVars, ArgTypes,
|
|
_, _, _, _, _, _, _, _, _, _, _, _).
|
|
|
|
pred_info_set_arg_types(PredInfo0, TypeVarSet, ArgTypes, PredInfo) :-
|
|
PredInfo0 = predicate(_, _, C, D, E, F, G, H, I, J, K, L, M, N),
|
|
PredInfo = predicate(TypeVarSet, ArgTypes,
|
|
C, D, E, F, G, H, I, J, K, L, M, N).
|
|
|
|
pred_info_procedures(PredInfo, Procs) :-
|
|
PredInfo = predicate(_, _, _, _, Procs, _, _, _, _, _, _, _, _, _).
|
|
|
|
pred_info_set_procedures(PredInfo0, Procedures, PredInfo) :-
|
|
PredInfo0 = predicate(A, B, C, D, _, F, G, H, I, J, K, L, M, N),
|
|
PredInfo = predicate(A, B, C, D, Procedures, F, G, H, I, J, K, L, M, N).
|
|
|
|
pred_info_context(PredInfo, Context) :-
|
|
PredInfo = predicate(_, _, _, _, _, Context, _, _, _, _, _, _, _, _).
|
|
|
|
pred_info_module(PredInfo, Module) :-
|
|
PredInfo = predicate(_, _, _, _, _, _, Module, _, _, _, _, _, _, _).
|
|
|
|
pred_info_name(PredInfo, PredName) :-
|
|
PredInfo = predicate(_, _, _, _, _, _, _, PredName, _, _, _, _, _, _).
|
|
|
|
pred_info_arity(PredInfo, Arity) :-
|
|
PredInfo = predicate(_, _, _, _, _, _, _, _, Arity, _, _, _, _, _).
|
|
|
|
pred_info_import_status(PredInfo, ImportStatus) :-
|
|
PredInfo = predicate(_, _, _, _, _, _, _, _, _, ImportStatus, _, _, _,
|
|
_).
|
|
|
|
pred_info_is_imported(PredInfo) :-
|
|
pred_info_import_status(PredInfo, ImportStatus),
|
|
ImportStatus = imported.
|
|
|
|
pred_info_is_pseudo_imported(PredInfo) :-
|
|
pred_info_import_status(PredInfo, ImportStatus),
|
|
ImportStatus = pseudo_imported.
|
|
|
|
pred_info_is_exported(PredInfo) :-
|
|
pred_info_import_status(PredInfo, ImportStatus),
|
|
ImportStatus = exported.
|
|
|
|
pred_info_is_pseudo_exported(PredInfo) :-
|
|
pred_info_import_status(PredInfo, ImportStatus),
|
|
ImportStatus = pseudo_exported.
|
|
|
|
pred_info_mark_as_external(PredInfo0, PredInfo) :-
|
|
PredInfo0 = predicate(A, B, C, D, E, F, G, H, I, _, K, L, M, N),
|
|
PredInfo = predicate(A, B, C, D, E, F, G, H, I, imported, K, L, M, N).
|
|
|
|
pred_info_set_status(PredInfo0, Status, PredInfo) :-
|
|
PredInfo0 = predicate(A, B, C, D, E, F, G, H, I, _, K, L, M, N),
|
|
PredInfo = predicate(A, B, C, D, E, F, G, H, I, Status, K, L, M, N).
|
|
|
|
pred_info_typevarset(PredInfo, TypeVarSet) :-
|
|
PredInfo = predicate(_, _, _, _, _, _, _, _, _, _, TypeVarSet, _, _, _).
|
|
|
|
pred_info_set_typevarset(PredInfo0, TypeVarSet, PredInfo) :-
|
|
PredInfo0 = predicate(A, B, C, D, E, F, G, H, I, J, _, L, M, N),
|
|
PredInfo = predicate(A, B, C, D, E, F, G, H, I, J, TypeVarSet, L, M,
|
|
N).
|
|
|
|
pred_info_get_goal_type(PredInfo, GoalType) :-
|
|
PredInfo = predicate(_, _, _, _, _, _, _, _, _, _, _, GoalType, _, _).
|
|
|
|
pred_info_set_goal_type(PredInfo0, GoalType, PredInfo) :-
|
|
PredInfo0 = predicate(A, B, C, D, E, F, G, H, I, J, K, _, M, N),
|
|
PredInfo = predicate(A, B, C, D, E, F, G, H, I, J, K, GoalType, M, N).
|
|
|
|
pred_info_is_inlined(PredInfo0) :-
|
|
pred_info_get_marker_list(PredInfo0, Markers),
|
|
list__member(request(inline), Markers).
|
|
|
|
pred_info_get_marker_list(PredInfo, Markers) :-
|
|
PredInfo = predicate(_, _, _, _, _, _, _, _, _, _, _, _, Markers, _).
|
|
|
|
pred_info_set_marker_list(PredInfo0, Markers, PredInfo) :-
|
|
PredInfo0 = predicate(A, B, C, D, E, F, G, H, I, J, K, L, _, N),
|
|
PredInfo = predicate(A, B, C, D, E, F, G, H, I, J, K, L, Markers, N).
|
|
|
|
pred_info_get_is_pred_or_func(PredInfo, IsPredOrFunc) :-
|
|
PredInfo = predicate(_, _, _, _, _, _, _, _, _, _, _, _, _,
|
|
IsPredOrFunc).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Various predicates for accessing the proc_info data structure.
|
|
|
|
:- interface.
|
|
|
|
:- pred proc_info_init(arity, list(mode), maybe(list(is_live)),
|
|
maybe(determinism), term__context, proc_info).
|
|
:- mode proc_info_init(in, in, in, in, in, out) is det.
|
|
|
|
:- pred proc_info_set(maybe(determinism), varset, map(var, type), list(var),
|
|
list(mode), maybe(list(is_live)), hlds__goal, term__context, call_info,
|
|
determinism, bool, list(arg_info), liveness_info, follow_vars,
|
|
proc_info).
|
|
:- mode proc_info_set(in, in, in, in, in, in, in, in, in, in, in, in, in, in,
|
|
out) is det.
|
|
|
|
:- pred proc_info_create(varset, map(var, type), list(var), list(mode),
|
|
determinism, hlds__goal, term__context, proc_info).
|
|
:- mode proc_info_create(in, in, in, in, in, in, in, out) is det.
|
|
|
|
:- pred proc_info_set_body(proc_info, varset, map(var, type), list(var),
|
|
hlds__goal, proc_info).
|
|
:- mode proc_info_set_body(in, in, in, in, in, out) is det.
|
|
|
|
:- pred proc_info_declared_determinism(proc_info, maybe(determinism)).
|
|
:- mode proc_info_declared_determinism(in, out) is det.
|
|
|
|
:- pred proc_info_inferred_determinism(proc_info, determinism).
|
|
:- mode proc_info_inferred_determinism(in, out) is det.
|
|
|
|
:- pred proc_info_interface_determinism(proc_info, determinism).
|
|
:- mode proc_info_interface_determinism(in, out) is det.
|
|
|
|
:- pred proc_info_interface_code_model(proc_info, code_model).
|
|
:- mode proc_info_interface_code_model(in, out) is det.
|
|
|
|
:- pred proc_info_variables(proc_info, varset).
|
|
:- mode proc_info_variables(in, out) is det.
|
|
|
|
:- pred proc_info_set_varset(proc_info, varset, proc_info).
|
|
:- mode proc_info_set_varset(in, in, out) is det.
|
|
|
|
:- pred proc_info_set_variables(proc_info, varset, proc_info).
|
|
:- mode proc_info_set_variables(in, in, out) is det.
|
|
|
|
:- pred proc_info_vartypes(proc_info, map(var, type)).
|
|
:- mode proc_info_vartypes(in, out) is det.
|
|
|
|
:- pred proc_info_set_vartypes(proc_info, map(var, type), proc_info).
|
|
:- mode proc_info_set_vartypes(in, in, out) is det.
|
|
|
|
:- pred proc_info_headvars(proc_info, list(var)).
|
|
:- mode proc_info_headvars(in, out) is det.
|
|
|
|
:- pred proc_info_set_headvars(proc_info, list(var), proc_info).
|
|
:- mode proc_info_set_headvars(in, in, out) is det.
|
|
|
|
:- pred proc_info_argmodes(proc_info, list(mode)).
|
|
:- mode proc_info_argmodes(in, out) is det.
|
|
|
|
:- pred proc_info_set_argmodes(proc_info, list(mode), proc_info).
|
|
:- mode proc_info_set_argmodes(in, in, out) is det.
|
|
|
|
:- pred proc_info_arglives(proc_info, module_info, list(is_live)).
|
|
:- mode proc_info_arglives(in, in, out) is det.
|
|
|
|
:- pred proc_info_maybe_arglives(proc_info, maybe(list(is_live))).
|
|
:- mode proc_info_maybe_arglives(in, out) is det.
|
|
|
|
:- pred proc_info_set_maybe_arglives(proc_info, maybe(list(is_live)),
|
|
proc_info).
|
|
:- mode proc_info_set_maybe_arglives(in, in, out) is det.
|
|
|
|
:- pred proc_info_goal(proc_info, hlds__goal).
|
|
:- mode proc_info_goal(in, out) is det.
|
|
|
|
:- pred proc_info_context(proc_info, term__context).
|
|
:- mode proc_info_context(in, out) is det.
|
|
|
|
:- pred proc_info_call_info(proc_info, call_info).
|
|
:- mode proc_info_call_info(in, out) is det.
|
|
|
|
:- pred proc_info_liveness_info(proc_info, liveness_info).
|
|
:- mode proc_info_liveness_info(in, out) is det.
|
|
|
|
:- pred proc_info_follow_vars(proc_info, follow_vars).
|
|
:- mode proc_info_follow_vars(in, out) is det.
|
|
|
|
:- pred proc_info_can_process(proc_info, bool).
|
|
:- mode proc_info_can_process(in, out) is det.
|
|
|
|
:- pred proc_info_set_inferred_determinism(proc_info, determinism, proc_info).
|
|
:- mode proc_info_set_inferred_determinism(in, in, out) is det.
|
|
|
|
:- pred proc_info_set_goal(proc_info, hlds__goal, proc_info).
|
|
:- mode proc_info_set_goal(in, in, out) is det.
|
|
|
|
:- pred proc_info_arg_info(proc_info, list(arg_info)).
|
|
:- mode proc_info_arg_info(in, out) is det.
|
|
|
|
:- pred proc_info_set_arg_info(proc_info, list(arg_info), proc_info).
|
|
:- mode proc_info_set_arg_info(in, in, out) is det.
|
|
|
|
:- pred proc_info_get_initial_instmap(proc_info, module_info, instmap).
|
|
:- mode proc_info_get_initial_instmap(in, in, out) is det.
|
|
|
|
:- pred proc_info_set_liveness_info(proc_info, liveness_info, proc_info).
|
|
:- mode proc_info_set_liveness_info(in, in, out) is det.
|
|
|
|
:- pred proc_info_set_follow_vars(proc_info, follow_vars, proc_info).
|
|
:- mode proc_info_set_follow_vars(in, in, out) is det.
|
|
|
|
:- pred proc_info_set_call_info(proc_info, call_info, proc_info).
|
|
:- mode proc_info_set_call_info(in, in, out) is det.
|
|
|
|
:- pred proc_info_set_can_process(proc_info, bool, proc_info).
|
|
:- mode proc_info_set_can_process(in, in, out) is det.
|
|
|
|
:- implementation.
|
|
|
|
:- type proc_info
|
|
---> procedure(
|
|
maybe(determinism),
|
|
% _declared_ determinism
|
|
% or `no' if there was no detism decl
|
|
varset, % variable names
|
|
map(var, type), % variable types
|
|
list(var), % head vars
|
|
list(mode), % modes of args
|
|
maybe(list(is_live)),
|
|
% liveness (in the mode analysis sense)
|
|
% of the arguments
|
|
hlds__goal, % Body
|
|
term__context, % The context of the `:- mode' decl
|
|
% (or the context of the first clause,
|
|
% if there was no mode declaration).
|
|
call_info, % stack allocations
|
|
determinism, % _inferred_ det'ism
|
|
bool, % no if we must not process this
|
|
% procedure yet (used to delay
|
|
% mode checking etc. for complicated
|
|
% modes of unification procs until
|
|
% the end of the unique_modes pass.)
|
|
list(arg_info), % calling convention of each arg:
|
|
% information computed by arg_info.m
|
|
% (based on the modes etc.)
|
|
% and used by code generation
|
|
% to determine how each argument
|
|
% should be passed.
|
|
liveness_info, % the initial liveness,
|
|
% for code generation
|
|
follow_vars % initial followvars
|
|
).
|
|
|
|
|
|
% Some parts of the procedure aren't known yet. We initialize
|
|
% them to any old garbage which we will later throw away.
|
|
|
|
% If the source code doesn't specify any determinism annotation,
|
|
% inferred determinism should get initialized to `erroneous'.
|
|
% This is what `det_analysis.m' wants. det_analysis.m
|
|
% will later provide the correct inferred determinism for it.
|
|
% XXX As a work-around for bugs in det_analysis, we need
|
|
% to set the initial InferredDet to `det', not `erroneous',
|
|
% because det_analysis incorrectly deletes code if it is `erroneous'.
|
|
% This means we never infer a determinism of `erroneous' or `failure',
|
|
% but that is not nearly as bad a bug as generating incorrect code.
|
|
|
|
proc_info_init(Arity, Modes, MaybeArgLives, MaybeDet, MContext, NewProc) :-
|
|
map__init(BodyTypes),
|
|
goal_info_init(GoalInfo),
|
|
varset__init(BodyVarSet0),
|
|
make_n_fresh_vars("HeadVar__", Arity, BodyVarSet0,
|
|
HeadVars, BodyVarSet),
|
|
( MaybeDet = yes(erroneous) ->
|
|
InferredDet = erroneous
|
|
; MaybeDet = yes(failure) ->
|
|
InferredDet = erroneous
|
|
;
|
|
InferredDet = det
|
|
),
|
|
map__init(CallInfo),
|
|
set__init(InitialLiveness),
|
|
ArgInfo = [],
|
|
ClauseBody = conj([]) - GoalInfo,
|
|
map__init(FollowVars),
|
|
CanProcess = yes,
|
|
NewProc = procedure(
|
|
MaybeDet, BodyVarSet, BodyTypes, HeadVars, Modes, MaybeArgLives,
|
|
ClauseBody, MContext, CallInfo, InferredDet, CanProcess,
|
|
ArgInfo, InitialLiveness, FollowVars
|
|
).
|
|
|
|
proc_info_set(DeclaredDetism, BodyVarSet, BodyTypes, HeadVars, HeadModes,
|
|
HeadLives, Goal,
|
|
Context, CallInfo, InferredDetism, CanProcess,
|
|
ArgInfo, Liveness, FollowVars, ProcInfo) :-
|
|
ProcInfo = procedure(
|
|
DeclaredDetism, BodyVarSet, BodyTypes, HeadVars, HeadModes,
|
|
HeadLives, Goal, Context, CallInfo, InferredDetism, CanProcess,
|
|
ArgInfo, Liveness, FollowVars).
|
|
|
|
proc_info_create(VarSet, VarTypes, HeadVars, HeadModes, Detism, Goal,
|
|
Context, ProcInfo) :-
|
|
map__init(CallInfo),
|
|
set__init(Liveness),
|
|
map__init(FollowVars),
|
|
MaybeHeadLives = no,
|
|
ProcInfo = procedure(yes(Detism), VarSet, VarTypes, HeadVars, HeadModes,
|
|
MaybeHeadLives, Goal, Context, CallInfo, Detism, yes, [],
|
|
Liveness, FollowVars).
|
|
|
|
proc_info_set_body(ProcInfo0, VarSet, VarTypes, HeadVars, Goal, ProcInfo) :-
|
|
ProcInfo0 = procedure(A, _, _, _, E, F, _,
|
|
H, I, J, K, L, M, N),
|
|
ProcInfo = procedure(A, VarSet, VarTypes, HeadVars, E, F, Goal,
|
|
H, I, J, K, L, M, N).
|
|
|
|
proc_info_interface_determinism(ProcInfo, Determinism) :-
|
|
proc_info_declared_determinism(ProcInfo, MaybeDeterminism),
|
|
(
|
|
MaybeDeterminism = no,
|
|
proc_info_inferred_determinism(ProcInfo, Determinism)
|
|
;
|
|
MaybeDeterminism = yes(Determinism)
|
|
).
|
|
|
|
proc_info_interface_code_model(ProcInfo, CodeModel) :-
|
|
proc_info_interface_determinism(ProcInfo, Determinism),
|
|
determinism_to_code_model(Determinism, CodeModel).
|
|
|
|
proc_info_arglives(ProcInfo, ModuleInfo, ArgLives) :-
|
|
proc_info_maybe_arglives(ProcInfo, MaybeArgLives),
|
|
( MaybeArgLives = yes(ArgLives0) ->
|
|
ArgLives = ArgLives0
|
|
;
|
|
proc_info_argmodes(ProcInfo, Modes),
|
|
get_arg_lives(Modes, ModuleInfo, ArgLives)
|
|
).
|
|
|
|
proc_info_get_initial_instmap(ProcInfo, ModuleInfo, reachable(InstMapping)) :-
|
|
proc_info_headvars(ProcInfo, HeadVars),
|
|
proc_info_argmodes(ProcInfo, ArgModes),
|
|
mode_list_get_initial_insts(ArgModes, ModuleInfo, InitialInsts),
|
|
/***********
|
|
% propagate type information into the modes
|
|
proc_info_vartypes(ProcInfo, VarTypes),
|
|
propagate_type_info_inst_list(VarTypes, ModuleInfo, InitialInsts0,
|
|
InitialInsts),
|
|
***********/
|
|
map__from_corresponding_lists(HeadVars, InitialInsts, InstMapping).
|
|
|
|
proc_info_declared_determinism(ProcInfo, Detism) :-
|
|
ProcInfo = procedure(Detism, _, _, _, _, _, _, _, _, _, _, _, _, _).
|
|
proc_info_variables(ProcInfo, VarSet) :-
|
|
ProcInfo = procedure(_, VarSet, _, _, _, _, _, _, _, _, _, _, _, _).
|
|
proc_info_vartypes(ProcInfo, VarTypes) :-
|
|
ProcInfo = procedure(_, _, VarTypes, _, _, _, _, _, _, _, _, _, _, _).
|
|
proc_info_headvars(ProcInfo, HeadVars) :-
|
|
ProcInfo = procedure(_, _, _, HeadVars, _, _, _, _, _, _, _, _, _, _).
|
|
proc_info_argmodes(ProcInfo, Modes) :-
|
|
ProcInfo = procedure(_, _, _, _, Modes, _, _, _, _, _, _, _, _, _).
|
|
proc_info_maybe_arglives(ProcInfo, ArgLives) :-
|
|
ProcInfo = procedure(_, _, _, _, _, ArgLives, _, _, _, _, _, _, _, _).
|
|
proc_info_goal(ProcInfo, Goal) :-
|
|
ProcInfo = procedure(_, _, _, _, _, _, Goal, _, _, _, _, _, _, _).
|
|
proc_info_context(ProcInfo, Context) :-
|
|
ProcInfo = procedure(_, _, _, _, _, _, _, Context, _, _, _, _, _, _).
|
|
proc_info_call_info(ProcInfo, CallInfo) :-
|
|
ProcInfo = procedure(_, _, _, _, _, _, _, _, CallInfo, _, _, _, _, _).
|
|
proc_info_inferred_determinism(ProcInfo, Detism) :-
|
|
ProcInfo = procedure(_, _, _, _, _, _, _, _, _, Detism, _, _, _, _).
|
|
proc_info_can_process(ProcInfo, CanProcess) :-
|
|
ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, CanProcess, _, _, _).
|
|
proc_info_arg_info(ProcInfo, ArgInfo) :-
|
|
ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, _, ArgInfo, _, _).
|
|
proc_info_liveness_info(ProcInfo, Liveness) :-
|
|
ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, _, _, Liveness, _).
|
|
proc_info_follow_vars(ProcInfo, Follow) :-
|
|
ProcInfo = procedure(_, _, _, _, _, _, _, _, _, _, _, _, _, Follow).
|
|
|
|
% :- type proc_info ---> procedure(
|
|
% A maybe(determinism),% _declared_ detism
|
|
% B varset, % variable names
|
|
% C map(var, type), % variable types
|
|
% D list(var), % head vars
|
|
% E list(mode), % modes of args
|
|
% F list(is_live), % liveness of args
|
|
% G hlds__goal, % Body
|
|
% H term__context, % The context of
|
|
% % the :- mode decl,
|
|
% % not the clause.
|
|
% I call_info, % stack allocations
|
|
% J determinism, % _inferred_ detism
|
|
% K bool, % can_process
|
|
% L list(arg_info), % information about
|
|
% % the arguments
|
|
% % derived from the
|
|
% % modes etc
|
|
% M liveness_info % the initial liveness
|
|
% N follow_vars % initial followvars
|
|
% ).
|
|
|
|
proc_info_set_varset(ProcInfo0, VarSet, ProcInfo) :-
|
|
ProcInfo0 = procedure(A, _, C, D, E, F, G, H, I, J, K, L, M, N),
|
|
ProcInfo = procedure(A, VarSet, C, D, E, F, G, H, I, J, K, L, M, N).
|
|
|
|
proc_info_set_variables(ProcInfo0, Vars, ProcInfo) :-
|
|
ProcInfo0 = procedure(A, _, C, D, E, F, G, H, I, J, K, L, M, N),
|
|
ProcInfo = procedure(A, Vars, C, D, E, F, G, H, I, J, K, L, M, N).
|
|
|
|
proc_info_set_vartypes(ProcInfo0, Vars, ProcInfo) :-
|
|
ProcInfo0 = procedure(A, B, _, D, E, F, G, H, I, J, K, L, M, N),
|
|
ProcInfo = procedure(A, B, Vars, D, E, F, G, H, I, J, K, L, M, N).
|
|
|
|
proc_info_set_headvars(ProcInfo0, HeadVars, ProcInfo) :-
|
|
ProcInfo0 = procedure(A, B, C, _, E, F, G, H, I, J, K, L, M, N),
|
|
ProcInfo = procedure(A, B, C, HeadVars, E, F, G, H, I, J, K, L, M, N).
|
|
|
|
proc_info_set_argmodes(ProcInfo0, ArgModes, ProcInfo) :-
|
|
ProcInfo0 = procedure(A, B, C, D, _, F, G, H, I, J, K, L, M, N),
|
|
ProcInfo = procedure(A, B, C, D, ArgModes, F, G, H, I, J, K, L, M, N).
|
|
|
|
proc_info_set_maybe_arglives(ProcInfo0, ArgLives, ProcInfo) :-
|
|
ProcInfo0 = procedure(A, B, C, D, E, _, G, H, I, J, K, L, M, N),
|
|
ProcInfo = procedure(A, B, C, D, E, ArgLives, G, H, I, J, K, L, M, N).
|
|
|
|
proc_info_set_inferred_determinism(ProcInfo0, Detism, ProcInfo) :-
|
|
ProcInfo0 = procedure(A, B, C, D, E, F, G, H, I, _, K, L, M, N),
|
|
ProcInfo = procedure(A, B, C, D, E, F, G, H, I, Detism, K, L, M, N).
|
|
|
|
proc_info_set_can_process(ProcInfo0, CanProcess, ProcInfo) :-
|
|
ProcInfo0 = procedure(A, B, C, D, E, F, G, H, I, J, _, L, M, N),
|
|
ProcInfo = procedure(A, B, C, D, E, F, G, H, I, J, CanProcess, L, M, N).
|
|
|
|
proc_info_set_goal(ProcInfo0, Goal, ProcInfo) :-
|
|
ProcInfo0 = procedure(A, B, C, D, E, F, _, H, I, J, K, L, M, N),
|
|
ProcInfo = procedure(A, B, C, D, E, F, Goal, H, I, J, K, L, M, N).
|
|
|
|
proc_info_set_call_info(ProcInfo0, CallInfo, ProcInfo) :-
|
|
ProcInfo0 = procedure(A, B, C, D, E, F, G, H, _, J, K, L, M, N),
|
|
ProcInfo = procedure(A, B, C, D, E, F, G, H, CallInfo, J, K, L, M, N).
|
|
|
|
proc_info_set_arg_info(ProcInfo0, ArgInfo, ProcInfo) :-
|
|
ProcInfo0 = procedure(A, B, C, D, E, F, G, H, I, J, K, _, M, N),
|
|
ProcInfo = procedure(A, B, C, D, E, F, G, H, I, J, K, ArgInfo, M, N).
|
|
|
|
proc_info_set_liveness_info(ProcInfo0, Liveness, ProcInfo) :-
|
|
ProcInfo0 = procedure(A, B, C, D, E, F, G, H, I, J, K, L, _, N),
|
|
ProcInfo = procedure(A, B, C, D, E, F, G, H, I, J, K, L, Liveness, N).
|
|
|
|
proc_info_set_follow_vars(ProcInfo0, Follow, ProcInfo) :-
|
|
ProcInfo0 = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, _),
|
|
ProcInfo = procedure(A, B, C, D, E, F, G, H, I, J, K, L, M, Follow).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- interface.
|
|
|
|
% make_n_fresh_vars(Name, N, VarSet0, Vars, VarSet):
|
|
% `Vars' is a list of `N' fresh variables allocated from
|
|
% `VarSet0'. The variables will be named "<Name>1", "<Name>2",
|
|
% "<Name>3", and so on, where <Name> is the value of `Name'.
|
|
% `VarSet' is the resulting varset.
|
|
|
|
:- pred make_n_fresh_vars(string, int, varset, list(var), varset).
|
|
:- mode make_n_fresh_vars(in, in, in, out, out) is det.
|
|
|
|
% given the list of predicate arguments for a predicate that
|
|
% is really a function, split that list into the function arguments
|
|
% and the function return type.
|
|
:- pred pred_args_to_func_args(list(T), list(T), T).
|
|
:- mode pred_args_to_func_args(in, out, out) is det.
|
|
|
|
:- implementation.
|
|
|
|
make_n_fresh_vars(BaseName, N, VarSet0, Vars, VarSet) :-
|
|
make_n_fresh_vars_2(BaseName, 0, N, VarSet0, Vars, VarSet).
|
|
|
|
:- pred make_n_fresh_vars_2(string, int, int, varset, list(var), varset).
|
|
:- mode make_n_fresh_vars_2(in, in, in, in, out, out) is det.
|
|
|
|
make_n_fresh_vars_2(BaseName, N, Max, VarSet0, Vars, VarSet) :-
|
|
(N = Max ->
|
|
VarSet = VarSet0,
|
|
Vars = []
|
|
;
|
|
N1 is N + 1,
|
|
varset__new_var(VarSet0, Var, VarSet1),
|
|
string__int_to_string(N1, Num),
|
|
string__append(BaseName, Num, VarName),
|
|
varset__name_var(VarSet1, Var, VarName, VarSet2),
|
|
Vars = [Var | Vars1],
|
|
make_n_fresh_vars_2(BaseName, N1, Max, VarSet2, Vars1, VarSet)
|
|
).
|
|
|
|
pred_args_to_func_args(PredArgs, FuncArgs, FuncReturn) :-
|
|
list__length(PredArgs, NumPredArgs),
|
|
NumFuncArgs is NumPredArgs - 1,
|
|
( list__split_list(NumFuncArgs, PredArgs, FuncArgs0, [FuncReturn0]) ->
|
|
FuncArgs = FuncArgs0,
|
|
FuncReturn = FuncReturn0
|
|
;
|
|
error("pred_args_to_func_args: function missing return value?")
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|