mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-19 15:54:18 +00:00
Estimated hours taken: 50 Rework the handling of types in higher_order.m. - Fix bugs in higher_order.m that stopped it working with --typeinfo-liveness. - Perform type and typeclass specialisation. compiler/polymorphism.m: Previously the type of typeclass_infos variables did not contain any information about the constraint about which the variable contains information. Now the type of a typeclass_info is `private_builtin:typeclass_info( private_builtin:constraint([ClassName, ConstrainedTypes]))'. This allows predicates such as type_list_subsumes to check that the class constraints match. Note that `private_builtin:constraint' has no declaration, so a lookup in the type definition map will fail. That's OK, because type_to_type_id will fail on it, so it will be treated as a type variable by any code which doesn't manipulate types directly. Added polymorphism__typeclass_info_class_constraint to get the class_constraint from a typeclass_info's type. This isn't used yet. Also, fix a bug in extract_type_info: an entry in the typeinfo_var_map was being overwritten using an entry from a dummy typevarset. Actually the optimization to overwrite the location of the type_info after extracting it from a typeclass_info was wrong because the type_info won't be in that location in other branches. compiler/higher_order.m: Rework the handling of type substitutions. Now the types of the called procedure are `inlined' into the calling procedure, rather than building up the types of the specialised version using the higher-order arguments. The advantage of this is that the code is a bit simpler and handles extra type_infos properly. The disadvantage is that the argument types for specialised versions may be more specific than they need to be, so in some cases more specialised versions will be created than before. Also, don't actually rebuild the higher-order terms in the specialised versions - just pass the terms through in case they are needed. Handle the extra typeinfos required for --typeinfo-liveness. Specialize calls to unify/2, index/2 and compare/3. Specialize class_method_calls. Specialize calls to the predicates in private_builtin.m which manipulate typeclass_infos. compiler/type_util.m: type_to_type_id now fails on the dummy `constraint' type. Remove typeinfos for non-variable types from the typeinfo_varmap after inlining and higher-order specialisation. compiler/inlining.m: Factor out some common code to handle type substitutions for use by higher_order.m. compiler/hlds_pred.m: Return the list of extra type_info variables added to the argument list. compiler/goal_util.m: Take a set of non-locals as an argument to goal_util__extra_nonlocal_typeinfos rather than extracting them from a goal. compiler/special_pred.m: Handle unmangled unify/compare/index in special_pred_get_type. compiler/base_type_layout.m: Don't generate references to the typeinfo for `private_builtin:constraint' - it doesn't exist. compiler/unused_args.m: Don't barf on specialised unification predicate names. compiler/options.m: Added options: `--type-specialization' (default off). `--higher-order-size-limit' - restrict the size of specialized versions produced by higher_order.m. `--disable-opt-for-trace' (default on) - where possible don't change the options to make the trace match the source code. compiler/handle_options.m: Don't disable higher_order.m when --typeinfo-liveness is set. Handle `--disable-opt-for-trace'. compiler/hlds_data.m: compiler/*.m: Add the instance number to `base_typeclass_info_const' cons_ids, so that higher_order.m can easily index into the list of instances for a class to find the methods. compiler/hlds_out.m: Use the correct varset when printing out the constraint proofs. Write the typeclass_info_varmap for each procedure. compiler/mercury_to_mercury.m: Print type variables with variable numbers. library/private_builtin.m: Add the argument to the typeclass_info type to hold the representation of the constraint. runtime/mercury_ho_call.c: Semidet and nondet class_method_calls where (0 < num_arg_typeclass_infos < 4) were aborting at runtime because arguments were being placed starting at r1 rather than at r(1 + num_arg_typeclass_infos). doc/user_guide.texi Document the new options. compiler/notes/compiler_design.html: Update the role of higher_order.m. tests/hard_coded/typeclasses/extra_typeinfo.m: Test case for the mercury_ho_call.c bug and the polymorphism.m extract_typeinfo bug and for updating the typeclass_info_varmap for specialised versions.
523 lines
21 KiB
Mathematica
523 lines
21 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1995-1998 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.
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module dependency_graph.
|
|
% Main author: bromage, conway.
|
|
|
|
% The dependency_graph records which procedures depend on which other
|
|
% procedures. It is defined as a relation (see hlds.m) R where xRy
|
|
% means that the definition of x depends on the definition of y.
|
|
%
|
|
% The other important structure is the dependency_ordering which is
|
|
% a list of the cliques (strongly-connected components) of this relation,
|
|
% in topological order. This is very handy for doing fixpoint iterations.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- interface.
|
|
:- import_module hlds_module, io.
|
|
|
|
:- pred module_info_ensure_dependency_info(module_info, module_info).
|
|
:- mode module_info_ensure_dependency_info(in, out) is det.
|
|
|
|
:- pred dependency_graph__write_dependency_graph(module_info, module_info,
|
|
io__state, io__state).
|
|
:- mode dependency_graph__write_dependency_graph(in, out, di, uo) is det.
|
|
|
|
% Output a form of the static call graph to a file for use by the
|
|
% profiler.
|
|
:- pred dependency_graph__write_prof_dependency_graph(module_info, module_info,
|
|
io__state, io__state).
|
|
:- mode dependency_graph__write_prof_dependency_graph(in, out, di, uo) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
:- import_module hlds_pred, hlds_goal, hlds_data, prog_data.
|
|
:- import_module mode_util, globals, options, code_util.
|
|
:- import_module llds, llds_out, mercury_to_mercury.
|
|
:- import_module int, bool, term, require, string.
|
|
:- import_module list, map, set, std_util.
|
|
:- import_module varset, relation.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Ensure that the dependency graph has been built by building
|
|
% it if necessary.
|
|
|
|
module_info_ensure_dependency_info(ModuleInfo0, ModuleInfo) :-
|
|
module_info_get_maybe_dependency_info(ModuleInfo0, MaybeDepInfo),
|
|
( MaybeDepInfo = yes(_) ->
|
|
ModuleInfo = ModuleInfo0
|
|
;
|
|
dependency_graph__build_dependency_graph(ModuleInfo0, ModuleInfo)
|
|
).
|
|
|
|
% Traverse the module structure, calling `dependency_graph__add_arcs'
|
|
% for each procedure body.
|
|
|
|
:- pred dependency_graph__build_dependency_graph(module_info, module_info).
|
|
:- mode dependency_graph__build_dependency_graph(in, out) is det.
|
|
|
|
dependency_graph__build_dependency_graph(ModuleInfo0, ModuleInfo) :-
|
|
module_info_predids(ModuleInfo0, PredIds),
|
|
relation__init(DepGraph0),
|
|
dependency_graph__add_pred_nodes(PredIds, ModuleInfo0,
|
|
DepGraph0, DepGraph1),
|
|
dependency_graph__add_pred_arcs(PredIds, ModuleInfo0,
|
|
DepGraph1, DepGraph),
|
|
hlds_dependency_info_init(DepInfo0),
|
|
hlds_dependency_info_set_dependency_graph(DepInfo0, DepGraph,
|
|
DepInfo1),
|
|
relation__atsort(DepGraph, DepOrd0),
|
|
dependency_graph__sets_to_lists(DepOrd0, [], DepOrd),
|
|
hlds_dependency_info_set_dependency_ordering(DepInfo1, DepOrd,
|
|
DepInfo),
|
|
module_info_set_dependency_info(ModuleInfo0, DepInfo, ModuleInfo).
|
|
|
|
:- pred dependency_graph__sets_to_lists( list(set(pred_proc_id)),
|
|
list(list(pred_proc_id)), list(list(pred_proc_id))).
|
|
:- mode dependency_graph__sets_to_lists(in, in, out) is det.
|
|
|
|
dependency_graph__sets_to_lists([], Xs, Xs).
|
|
dependency_graph__sets_to_lists([X | Xs], Ys, Zs) :-
|
|
set__to_sorted_list(X, Y),
|
|
dependency_graph__sets_to_lists(Xs, [Y | Ys], Zs).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred dependency_graph__add_pred_nodes(list(pred_id), module_info,
|
|
dependency_graph, dependency_graph).
|
|
:- mode dependency_graph__add_pred_nodes(in, in, in, out) is det.
|
|
|
|
dependency_graph__add_pred_nodes([], _ModuleInfo, DepGraph, DepGraph).
|
|
dependency_graph__add_pred_nodes([PredId | PredIds], ModuleInfo,
|
|
DepGraph0, DepGraph) :-
|
|
module_info_preds(ModuleInfo, PredTable),
|
|
map__lookup(PredTable, PredId, PredInfo),
|
|
(
|
|
% Don't bother adding nodes (or arcs) for predicates
|
|
% which which are imported (ie we don't have any `clauses'
|
|
% for).
|
|
pred_info_is_imported(PredInfo)
|
|
->
|
|
DepGraph1 = DepGraph0
|
|
;
|
|
pred_info_procids(PredInfo, ProcIds),
|
|
dependency_graph__add_proc_nodes(ProcIds, PredId, ModuleInfo,
|
|
DepGraph0, DepGraph1)
|
|
),
|
|
dependency_graph__add_pred_nodes(PredIds, ModuleInfo, DepGraph1, DepGraph).
|
|
|
|
:- pred dependency_graph__add_proc_nodes(list(proc_id), pred_id, module_info,
|
|
dependency_graph, dependency_graph).
|
|
:- mode dependency_graph__add_proc_nodes(in, in, in, in, out) is det.
|
|
|
|
dependency_graph__add_proc_nodes([], _PredId, _ModuleInfo, DepGraph, DepGraph).
|
|
dependency_graph__add_proc_nodes([ProcId | ProcIds], PredId, ModuleInfo,
|
|
DepGraph0, DepGraph) :-
|
|
relation__add_element(DepGraph0, proc(PredId, ProcId), _, DepGraph1),
|
|
dependency_graph__add_proc_nodes(ProcIds, PredId, ModuleInfo,
|
|
DepGraph1, DepGraph).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred dependency_graph__add_pred_arcs(list(pred_id), module_info,
|
|
dependency_graph, dependency_graph).
|
|
:- mode dependency_graph__add_pred_arcs(in, in, in, out) is det.
|
|
|
|
dependency_graph__add_pred_arcs([], _ModuleInfo, DepGraph, DepGraph).
|
|
dependency_graph__add_pred_arcs([PredId | PredIds], ModuleInfo,
|
|
DepGraph0, DepGraph) :-
|
|
module_info_preds(ModuleInfo, PredTable),
|
|
map__lookup(PredTable, PredId, PredInfo),
|
|
(
|
|
pred_info_is_imported(PredInfo)
|
|
->
|
|
DepGraph1 = DepGraph0
|
|
;
|
|
pred_info_procids(PredInfo, ProcIds),
|
|
dependency_graph__add_proc_arcs(ProcIds, PredId, ModuleInfo,
|
|
DepGraph0, DepGraph1)
|
|
),
|
|
dependency_graph__add_pred_arcs(PredIds, ModuleInfo, DepGraph1, DepGraph).
|
|
|
|
:- pred dependency_graph__add_proc_arcs(list(proc_id), pred_id, module_info,
|
|
dependency_graph, dependency_graph).
|
|
:- mode dependency_graph__add_proc_arcs(in, in, in, in, out) is det.
|
|
|
|
dependency_graph__add_proc_arcs([], _PredId, _ModuleInfo, DepGraph, DepGraph).
|
|
dependency_graph__add_proc_arcs([ProcId | ProcIds], PredId, ModuleInfo,
|
|
DepGraph0, DepGraph) :-
|
|
module_info_preds(ModuleInfo, PredTable0),
|
|
map__lookup(PredTable0, PredId, PredInfo0),
|
|
pred_info_procedures(PredInfo0, ProcTable0),
|
|
map__lookup(ProcTable0, ProcId, ProcInfo0),
|
|
|
|
proc_info_goal(ProcInfo0, Goal),
|
|
|
|
relation__lookup_element(DepGraph0, proc(PredId, ProcId), Caller),
|
|
dependency_graph__add_arcs_in_goal(Goal, Caller, DepGraph0, DepGraph1),
|
|
|
|
dependency_graph__add_proc_arcs(ProcIds, PredId, ModuleInfo,
|
|
DepGraph1, DepGraph).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred dependency_graph__add_arcs_in_goal(hlds_goal, relation_key,
|
|
dependency_graph, dependency_graph).
|
|
:- mode dependency_graph__add_arcs_in_goal(in, in, in, out) is det.
|
|
|
|
dependency_graph__add_arcs_in_goal(Goal - _GoalInfo, PPId,
|
|
DepGraph0, DepGraph) :-
|
|
dependency_graph__add_arcs_in_goal_2(Goal, PPId, DepGraph0, DepGraph).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred dependency_graph__add_arcs_in_goal_2(hlds_goal_expr, relation_key,
|
|
dependency_graph, dependency_graph).
|
|
:- mode dependency_graph__add_arcs_in_goal_2(in, in, in, out) is det.
|
|
|
|
dependency_graph__add_arcs_in_goal_2(conj(Goals), Caller,
|
|
DepGraph0, DepGraph) :-
|
|
dependency_graph__add_arcs_in_list(Goals, Caller, DepGraph0, DepGraph).
|
|
|
|
dependency_graph__add_arcs_in_goal_2(par_conj(Goals, _SM), Caller,
|
|
DepGraph0, DepGraph) :-
|
|
dependency_graph__add_arcs_in_list(Goals, Caller, DepGraph0, DepGraph).
|
|
|
|
dependency_graph__add_arcs_in_goal_2(disj(Goals, _), Caller,
|
|
DepGraph0, DepGraph) :-
|
|
dependency_graph__add_arcs_in_list(Goals, Caller, DepGraph0, DepGraph).
|
|
|
|
dependency_graph__add_arcs_in_goal_2(switch(_Var, _Det, Cases, _),
|
|
Caller, DepGraph0, DepGraph) :-
|
|
dependency_graph__add_arcs_in_cases(Cases, Caller, DepGraph0, DepGraph).
|
|
|
|
dependency_graph__add_arcs_in_goal_2(if_then_else(_Vars, Cond, Then, Else, _),
|
|
Caller, DepGraph0, DepGraph) :-
|
|
dependency_graph__add_arcs_in_goal(Cond, Caller, DepGraph0, DepGraph1),
|
|
dependency_graph__add_arcs_in_goal(Then, Caller, DepGraph1, DepGraph2),
|
|
dependency_graph__add_arcs_in_goal(Else, Caller, DepGraph2, DepGraph).
|
|
|
|
dependency_graph__add_arcs_in_goal_2(not(Goal), Caller, DepGraph0, DepGraph) :-
|
|
dependency_graph__add_arcs_in_goal(Goal, Caller, DepGraph0, DepGraph).
|
|
|
|
dependency_graph__add_arcs_in_goal_2(some(_Vars, Goal), Caller,
|
|
DepGraph0, DepGraph) :-
|
|
dependency_graph__add_arcs_in_goal(Goal, Caller, DepGraph0, DepGraph).
|
|
|
|
dependency_graph__add_arcs_in_goal_2(higher_order_call(_, _, _, _, _, _),
|
|
_Caller, DepGraph, DepGraph).
|
|
|
|
dependency_graph__add_arcs_in_goal_2(class_method_call(_, _, _, _, _, _),
|
|
_Caller, DepGraph, DepGraph).
|
|
|
|
dependency_graph__add_arcs_in_goal_2(call(PredId, ProcId, _, Builtin, _, _),
|
|
Caller, DepGraph0, DepGraph) :-
|
|
(
|
|
Builtin = inline_builtin
|
|
->
|
|
DepGraph = DepGraph0
|
|
;
|
|
(
|
|
% If the node isn't in the relation, then
|
|
% we didn't insert it because is was imported,
|
|
% and we don't consider it.
|
|
relation__search_element(DepGraph0,
|
|
proc(PredId, ProcId), Callee)
|
|
->
|
|
relation__add(DepGraph0, Caller, Callee, DepGraph)
|
|
;
|
|
DepGraph = DepGraph0
|
|
)
|
|
).
|
|
|
|
dependency_graph__add_arcs_in_goal_2(unify(_,_,_,Unify,_), Caller,
|
|
DepGraph0, DepGraph) :-
|
|
( Unify = assign(_, _),
|
|
DepGraph0 = DepGraph
|
|
; Unify = simple_test(_, _),
|
|
DepGraph0 = DepGraph
|
|
; Unify = construct(_, Cons, _, _),
|
|
dependency_graph__add_arcs_in_cons(Cons, Caller,
|
|
DepGraph0, DepGraph)
|
|
; Unify = deconstruct(_, Cons, _, _, _),
|
|
dependency_graph__add_arcs_in_cons(Cons, Caller,
|
|
DepGraph0, DepGraph)
|
|
; Unify = complicated_unify(_, _),
|
|
DepGraph0 = DepGraph
|
|
).
|
|
|
|
% There can be no dependencies within a pragma_c_code
|
|
dependency_graph__add_arcs_in_goal_2(pragma_c_code(_, _, _, _, _, _, _), _,
|
|
DepGraph, DepGraph).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred dependency_graph__add_arcs_in_list(list(hlds_goal), relation_key,
|
|
dependency_graph, dependency_graph).
|
|
:- mode dependency_graph__add_arcs_in_list(in, in, in, out) is det.
|
|
|
|
dependency_graph__add_arcs_in_list([], _Caller, DepGraph, DepGraph).
|
|
dependency_graph__add_arcs_in_list([Goal|Goals], Caller, DepGraph0, DepGraph) :-
|
|
dependency_graph__add_arcs_in_goal(Goal, Caller, DepGraph0, DepGraph1),
|
|
dependency_graph__add_arcs_in_list(Goals, Caller, DepGraph1, DepGraph).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred dependency_graph__add_arcs_in_cases(list(case), relation_key,
|
|
dependency_graph, dependency_graph).
|
|
:- mode dependency_graph__add_arcs_in_cases(in, in, in, out) is det.
|
|
|
|
dependency_graph__add_arcs_in_cases([], _Caller, DepGraph, DepGraph).
|
|
dependency_graph__add_arcs_in_cases([case(Cons, Goal) | Goals], Caller,
|
|
DepGraph0, DepGraph) :-
|
|
dependency_graph__add_arcs_in_cons(Cons, Caller, DepGraph0, DepGraph1),
|
|
dependency_graph__add_arcs_in_goal(Goal, Caller, DepGraph1, DepGraph2),
|
|
dependency_graph__add_arcs_in_cases(Goals, Caller, DepGraph2, DepGraph).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred dependency_graph__add_arcs_in_cons(cons_id, relation_key,
|
|
dependency_graph, dependency_graph).
|
|
:- mode dependency_graph__add_arcs_in_cons(in, in, in, out) is det.
|
|
dependency_graph__add_arcs_in_cons(cons(_, _), _Caller,
|
|
DepGraph, DepGraph).
|
|
dependency_graph__add_arcs_in_cons(int_const(_), _Caller,
|
|
DepGraph, DepGraph).
|
|
dependency_graph__add_arcs_in_cons(string_const(_), _Caller,
|
|
DepGraph, DepGraph).
|
|
dependency_graph__add_arcs_in_cons(float_const(_), _Caller,
|
|
DepGraph, DepGraph).
|
|
dependency_graph__add_arcs_in_cons(pred_const(Pred, Proc), Caller,
|
|
DepGraph0, DepGraph) :-
|
|
(
|
|
% If the node isn't in the relation, then
|
|
% we didn't insert it because is was imported,
|
|
% and we don't consider it.
|
|
relation__search_element(DepGraph0, proc(Pred, Proc), Callee)
|
|
->
|
|
relation__add(DepGraph0, Caller, Callee, DepGraph)
|
|
;
|
|
DepGraph = DepGraph0
|
|
).
|
|
dependency_graph__add_arcs_in_cons(code_addr_const(Pred, Proc), Caller,
|
|
DepGraph0, DepGraph) :-
|
|
(
|
|
% If the node isn't in the relation, then
|
|
% we didn't insert it because is was imported,
|
|
% and we don't consider it.
|
|
relation__search_element(DepGraph0, proc(Pred, Proc), Callee)
|
|
->
|
|
relation__add(DepGraph0, Caller, Callee, DepGraph)
|
|
;
|
|
DepGraph = DepGraph0
|
|
).
|
|
dependency_graph__add_arcs_in_cons(base_type_info_const(_, _, _), _Caller,
|
|
DepGraph, DepGraph).
|
|
dependency_graph__add_arcs_in_cons(base_typeclass_info_const(_, _, _, _),
|
|
_Caller, DepGraph, DepGraph).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
dependency_graph__write_dependency_graph(ModuleInfo0, ModuleInfo) -->
|
|
io__write_string("% Dependency graph\n"),
|
|
{ module_info_ensure_dependency_info(ModuleInfo0, ModuleInfo) },
|
|
{ module_info_dependency_info(ModuleInfo, DepInfo) },
|
|
{ hlds_dependency_info_get_dependency_graph(DepInfo, DepGraph) },
|
|
{ relation__domain(DepGraph, DomSet) },
|
|
{ set__to_sorted_list(DomSet, DomList) },
|
|
dependency_graph__write_dependency_graph_2(DomList, DepGraph,
|
|
ModuleInfo),
|
|
io__write_string("\n\n% Dependency ordering\n"),
|
|
{ hlds_dependency_info_get_dependency_ordering(DepInfo, DepOrd) },
|
|
dependency_graph__write_dependency_ordering(DepOrd, ModuleInfo, 1).
|
|
|
|
:- pred dependency_graph__write_dependency_graph_2(list(pred_proc_id),
|
|
dependency_graph, module_info, io__state, io__state).
|
|
:- mode dependency_graph__write_dependency_graph_2(in, in, in, di, uo) is det.
|
|
|
|
dependency_graph__write_dependency_graph_2([], _DepGraph, _ModuleInfo) --> [].
|
|
dependency_graph__write_dependency_graph_2([Node | Nodes], DepGraph,
|
|
ModuleInfo) -->
|
|
{ relation__lookup_element(DepGraph, Node, NodeKey) },
|
|
{ relation__lookup_from(DepGraph, NodeKey, SuccSet) },
|
|
{ set__to_sorted_list(SuccSet, SuccList) },
|
|
dependency_graph__write_dependency_graph_3(SuccList, Node, DepGraph,
|
|
ModuleInfo),
|
|
dependency_graph__write_dependency_graph_2(Nodes, DepGraph,
|
|
ModuleInfo).
|
|
|
|
:- pred dependency_graph__write_dependency_graph_3(list(relation_key),
|
|
pred_proc_id, dependency_graph, module_info,
|
|
io__state, io__state).
|
|
:- mode dependency_graph__write_dependency_graph_3(in, in, in, in,
|
|
di, uo) is det.
|
|
|
|
dependency_graph__write_dependency_graph_3([], _Node, _DepGraph,
|
|
_ModuleInfo) -->
|
|
[].
|
|
dependency_graph__write_dependency_graph_3([S | Ss], Node, DepGraph,
|
|
ModuleInfo) -->
|
|
{ relation__lookup_key(DepGraph, S, SNode) },
|
|
{ Node = proc(PPredId, PProcId) },
|
|
{ SNode = proc(CPredId, CProcId) },
|
|
{ module_info_pred_proc_info(ModuleInfo, PPredId, PProcId,
|
|
PPredInfo, PProcInfo) },
|
|
{ module_info_pred_proc_info(ModuleInfo, CPredId, CProcId,
|
|
CPredInfo, CProcInfo) },
|
|
{ pred_info_name(PPredInfo, PName) },
|
|
{ proc_info_declared_determinism(PProcInfo, PDet) },
|
|
{ proc_info_argmodes(PProcInfo, PModes) },
|
|
{ proc_info_context(PProcInfo, PContext) },
|
|
|
|
{ pred_info_name(CPredInfo, CName) },
|
|
{ proc_info_declared_determinism(CProcInfo, CDet) },
|
|
{ proc_info_argmodes(CProcInfo, CModes) },
|
|
{ proc_info_context(CProcInfo, CContext) },
|
|
|
|
{ varset__init(ModeVarSet) },
|
|
|
|
mercury_output_pred_mode_subdecl(ModeVarSet, unqualified(PName),
|
|
PModes, PDet, PContext),
|
|
io__write_string(" -> "),
|
|
mercury_output_pred_mode_subdecl(ModeVarSet, unqualified(CName),
|
|
CModes, CDet, CContext),
|
|
io__write_string(".\n"),
|
|
|
|
dependency_graph__write_dependency_graph_3(Ss, Node, DepGraph,
|
|
ModuleInfo).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred dependency_graph__write_dependency_ordering(list(list(pred_proc_id)),
|
|
module_info, int, io__state, io__state).
|
|
:- mode dependency_graph__write_dependency_ordering(in, in, in, di, uo) is det.
|
|
dependency_graph__write_dependency_ordering([], _ModuleInfo, _N) -->
|
|
io__write_string("\n").
|
|
dependency_graph__write_dependency_ordering([Clique | Rest], ModuleInfo, N) -->
|
|
io__write_string("% Clique "),
|
|
io__write_int(N),
|
|
io__write_string("\n"),
|
|
dependency_graph__write_clique(Clique, ModuleInfo),
|
|
{ N1 is N + 1 },
|
|
dependency_graph__write_dependency_ordering(Rest, ModuleInfo, N1).
|
|
|
|
:- pred dependency_graph__write_clique(list(pred_proc_id),
|
|
module_info, io__state, io__state).
|
|
:- mode dependency_graph__write_clique(in, in, di, uo) is det.
|
|
dependency_graph__write_clique([], _ModuleInfo) --> [].
|
|
dependency_graph__write_clique([proc(PredId, ProcId) | Rest], ModuleInfo) -->
|
|
{ module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
|
|
PredInfo, ProcInfo) },
|
|
{ pred_info_name(PredInfo, Name) },
|
|
{ proc_info_declared_determinism(ProcInfo, Det) },
|
|
{ proc_info_argmodes(ProcInfo, Modes) },
|
|
{ proc_info_context(ProcInfo, Context) },
|
|
{ varset__init(ModeVarSet) },
|
|
|
|
io__write_string("% "),
|
|
mercury_output_pred_mode_subdecl(ModeVarSet, unqualified(Name),
|
|
Modes, Det, Context),
|
|
io__write_string("\n"),
|
|
dependency_graph__write_clique(Rest, ModuleInfo).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% dependency_graph__write_prof_dependency_graph:
|
|
% Output's the static call graph of the current module in the form of
|
|
% CallerLabel (\t) CalleeLabel
|
|
%
|
|
dependency_graph__write_prof_dependency_graph(ModuleInfo0, ModuleInfo) -->
|
|
{ module_info_ensure_dependency_info(ModuleInfo0, ModuleInfo) },
|
|
{ module_info_dependency_info(ModuleInfo, DepInfo) },
|
|
{ hlds_dependency_info_get_dependency_graph(DepInfo, DepGraph) },
|
|
{ relation__domain(DepGraph, DomSet) },
|
|
{ set__to_sorted_list(DomSet, DomList) },
|
|
dependency_graph__write_prof_dependency_graph_2(DomList, DepGraph,
|
|
ModuleInfo).
|
|
|
|
:- pred dependency_graph__write_prof_dependency_graph_2(list(pred_proc_id),
|
|
dependency_graph, module_info, io__state, io__state).
|
|
:- mode dependency_graph__write_prof_dependency_graph_2(in, in, in, di, uo)
|
|
is det.
|
|
|
|
% dependency_graph__write_prof_dependency_graph_2:
|
|
% Scan's through list of caller's, then call's next predicate to get
|
|
% callee's
|
|
dependency_graph__write_prof_dependency_graph_2([], _DepGraph, _ModuleInfo) --> [].
|
|
dependency_graph__write_prof_dependency_graph_2([Node | Nodes], DepGraph,
|
|
ModuleInfo) -->
|
|
{ relation__lookup_element(DepGraph, Node, NodeKey) },
|
|
{ relation__lookup_from(DepGraph, NodeKey, SuccSet) },
|
|
{ set__to_sorted_list(SuccSet, SuccList) },
|
|
dependency_graph__write_prof_dependency_graph_3(SuccList, Node,
|
|
DepGraph, ModuleInfo),
|
|
dependency_graph__write_prof_dependency_graph_2(Nodes, DepGraph,
|
|
ModuleInfo).
|
|
|
|
|
|
% dependency_graph__write_prof_dependency_graph_3:
|
|
% Process all the callee's of a node.
|
|
% XXX We should only make the Caller label once and then pass it around.
|
|
:- pred dependency_graph__write_prof_dependency_graph_3(list(relation_key),
|
|
pred_proc_id, dependency_graph, module_info,
|
|
io__state, io__state).
|
|
:- mode dependency_graph__write_prof_dependency_graph_3(in, in, in, in,
|
|
di, uo) is det.
|
|
|
|
dependency_graph__write_prof_dependency_graph_3([], _Node, _DepGraph,
|
|
_ModuleInfo) -->
|
|
[].
|
|
dependency_graph__write_prof_dependency_graph_3([S | Ss], Node, DepGraph,
|
|
ModuleInfo) -->
|
|
{ relation__lookup_key(DepGraph, S, SNode) },
|
|
{ Node = proc(PPredId, PProcId) }, % Caller
|
|
{ SNode = proc(CPredId, CProcId) }, % Callee
|
|
dependency_graph__output_label(ModuleInfo, PPredId, PProcId),
|
|
io__write_string("\t"),
|
|
dependency_graph__output_label(ModuleInfo, CPredId, CProcId),
|
|
io__write_string("\n"),
|
|
dependency_graph__write_prof_dependency_graph_3(Ss, Node, DepGraph,
|
|
ModuleInfo).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% dependency_graph__output_label:
|
|
% Prints out the label corresponding to PredId and ProcId.
|
|
%
|
|
:- pred dependency_graph__output_label(module_info, pred_id, proc_id,
|
|
io__state, io__state).
|
|
:- mode dependency_graph__output_label(in, in, in, di, uo) is det.
|
|
|
|
dependency_graph__output_label(ModuleInfo, PredId, ProcId) -->
|
|
{ code_util__make_entry_label(ModuleInfo, PredId, ProcId, no,
|
|
Address) },
|
|
(
|
|
{ Address = label(local(ProcLabela)) }
|
|
->
|
|
output_label(local(ProcLabela))
|
|
;
|
|
{ Address = imported(ProcLabelb) }
|
|
->
|
|
output_proc_label(ProcLabelb)
|
|
;
|
|
{ Address = label(exported(ProcLabelc)) }
|
|
->
|
|
output_label(exported(ProcLabelc))
|
|
;
|
|
{ error("dependency_graph__output_label: label not of type local or imported or exported\n") }
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|