Files
mercury/compiler/call_graph.m
Fergus Henderson ac4f8ba0fb Add copyright messages.
compiler/*:
	Add copyright messages.
	Change all occurences of *.nl in comments to *.m.

compiler/mercury_compile.pp:
	Change the output to the .dep files to use *.m rather than *.nl.
	(NOTE: this means that `mmake' will not work any more if you
	call your files *.nl!!!)
1995-03-30 21:03:41 +00:00

262 lines
10 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.
%-----------------------------------------------------------------------------%
:- module call_graph.
% Main author: conway.
% Computes the `call_graph', i.e. which variables are either live across a
% call or live at the start of a disjunction, allocates a stack slot for
% each of these variables, and stores this information in the call_info
% structure in the proc_info.
%-----------------------------------------------------------------------------%
:- interface.
:- import_module hlds, graph, io.
:- type pred_proc_id == pair(pred_id, proc_id).
:- type call_graph == graph(pred_proc_id, unit).
:- pred call_graph__build_call_graph(module_info, call_graph).
:- mode call_graph__build_call_graph(in, out) is det.
:- pred call_graph__write_call_graph(call_graph, module_info,
io__state, io__state).
:- mode call_graph__write_call_graph(in, in, di, uo) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module list, map, set, prog_io, std_util.
:- import_module mode_util, int, term, require, string.
:- import_module varset, mercury_to_mercury.
%-----------------------------------------------------------------------------%
% Traverse the module structure, calling `call_graph__add_arcs'
% for each procedure body.
call_graph__build_call_graph(ModuleInfo, CallGraph) :-
module_info_predids(ModuleInfo, PredIds),
graph__init(CallGraph0),
call_graph__build_pred_nodes(PredIds, ModuleInfo, CallGraph0, CallGraph1),
call_graph__add_pred_arcs(PredIds, ModuleInfo, CallGraph1, CallGraph).
:- pred call_graph__build_pred_nodes(list(pred_id), module_info,
call_graph, call_graph).
:- mode call_graph__build_pred_nodes(in, in, in, out) is det.
call_graph__build_pred_nodes([], _ModuleInfo, CallGraph, CallGraph).
call_graph__build_pred_nodes([PredId | PredIds], ModuleInfo,
CallGraph0, CallGraph) :-
module_info_preds(ModuleInfo, PredTable),
map__lookup(PredTable, PredId, PredInfo),
pred_info_procids(PredInfo, ProcIds),
call_graph__build_proc_nodes(ProcIds, PredId, ModuleInfo,
CallGraph0, CallGraph1),
call_graph__build_pred_nodes(PredIds, ModuleInfo, CallGraph1, CallGraph).
:- pred call_graph__build_proc_nodes(list(proc_id), pred_id, module_info,
call_graph, call_graph).
:- mode call_graph__build_proc_nodes(in, in, in, in, out) is det.
call_graph__build_proc_nodes([], _PredId, _ModuleInfo, CallGraph, CallGraph).
call_graph__build_proc_nodes([ProcId | ProcIds], PredId, ModuleInfo,
CallGraph0, CallGraph) :-
graph__insert_node(CallGraph0, PredId - ProcId, _Node, CallGraph1),
call_graph__build_proc_nodes(ProcIds, PredId, ModuleInfo,
CallGraph1, CallGraph).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- pred call_graph__add_pred_arcs(list(pred_id), module_info,
call_graph, call_graph).
:- mode call_graph__add_pred_arcs(in, in, in, out) is det.
call_graph__add_pred_arcs([], _ModuleInfo, CallGraph, CallGraph).
call_graph__add_pred_arcs([PredId | PredIds], ModuleInfo,
CallGraph0, CallGraph) :-
module_info_preds(ModuleInfo, PredTable),
map__lookup(PredTable, PredId, PredInfo),
(
pred_info_is_imported(PredInfo)
->
CallGraph1 = CallGraph0
;
pred_info_procids(PredInfo, ProcIds),
call_graph__add_proc_arcs(ProcIds, PredId, ModuleInfo,
CallGraph0, CallGraph1)
),
call_graph__add_pred_arcs(PredIds, ModuleInfo, CallGraph1, CallGraph).
:- pred call_graph__add_proc_arcs(list(proc_id), pred_id, module_info,
call_graph, call_graph).
:- mode call_graph__add_proc_arcs(in, in, in, in, out) is det.
call_graph__add_proc_arcs([], _PredId, _ModuleInfo, CallGraph, CallGraph).
call_graph__add_proc_arcs([ProcId | ProcIds], PredId, ModuleInfo,
CallGraph0, CallGraph) :-
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),
call_graph__add_arcs_in_goal(Goal, PredId - ProcId,
CallGraph0, CallGraph1),
call_graph__add_proc_arcs(ProcIds, PredId, ModuleInfo,
CallGraph1, CallGraph).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
% The call_info structure (map(var, lval)) is threaded through the traversal
% of the goal. The liveness information is computed from the liveness
% delta annotations.
:- pred call_graph__add_arcs_in_goal(hlds__goal, pred_proc_id,
call_graph, call_graph).
:- mode call_graph__add_arcs_in_goal(in, in, in, out) is det.
call_graph__add_arcs_in_goal(Goal - _GoalInfo, PPId, CallGraph0, CallGraph) :-
call_graph__add_arcs_in_goal_2(Goal, PPId, CallGraph0, CallGraph).
%-----------------------------------------------------------------------------%
% Here we process each of the different sorts of goals.
% `Liveness' is the set of live variables, i.e. vars which
% have been referenced and will be referenced again.
:- pred call_graph__add_arcs_in_goal_2(hlds__goal_expr, pred_proc_id,
call_graph, call_graph).
:- mode call_graph__add_arcs_in_goal_2(in, in, in, out) is det.
call_graph__add_arcs_in_goal_2(conj(Goals), Caller, CallGraph0, CallGraph) :-
call_graph__add_arcs_in_list(Goals, Caller, CallGraph0, CallGraph).
call_graph__add_arcs_in_goal_2(disj(Goals), Caller, CallGraph0, CallGraph) :-
call_graph__add_arcs_in_list(Goals, Caller, CallGraph0, CallGraph).
call_graph__add_arcs_in_goal_2(switch(_Var, _Det, Cases),
Caller, CallGraph0, CallGraph) :-
call_graph__add_arcs_in_cases(Cases, Caller, CallGraph0, CallGraph).
call_graph__add_arcs_in_goal_2(if_then_else(_Vars, Cond, Then, Else),
Caller, CallGraph0, CallGraph) :-
call_graph__add_arcs_in_goal(Cond, Caller, CallGraph0, CallGraph1),
call_graph__add_arcs_in_goal(Then, Caller, CallGraph1, CallGraph2),
call_graph__add_arcs_in_goal(Else, Caller, CallGraph2, CallGraph).
call_graph__add_arcs_in_goal_2(not(Goal), Caller, CallGraph0, CallGraph) :-
call_graph__add_arcs_in_goal(Goal, Caller, CallGraph0, CallGraph).
call_graph__add_arcs_in_goal_2(some(_Vars, Goal), Caller, CallGraph0, CallGraph) :-
call_graph__add_arcs_in_goal(Goal, Caller, CallGraph0, CallGraph).
call_graph__add_arcs_in_goal_2(
call(PredId, ProcId, _ArgTerms, Builtin, _SymName, _Follow),
Caller, CallGraph0, CallGraph) :-
(
is_builtin__is_inline(Builtin)
->
CallGraph = CallGraph0
;
graph__find_node(CallGraph0, Caller, PNode),
graph__find_node(CallGraph0, PredId - ProcId, CNode),
graph__insert_edge(CallGraph0, PNode, CNode, unit,
_Arc, CallGraph)
).
call_graph__add_arcs_in_goal_2(unify(_,_,_,_,_), _Caller, CallGraph, CallGraph).
%-----------------------------------------------------------------------------%
:- pred call_graph__add_arcs_in_list(list(hlds__goal), pred_proc_id,
call_graph, call_graph).
:- mode call_graph__add_arcs_in_list(in, in, in, out) is det.
call_graph__add_arcs_in_list([], _Caller, CallGraph, CallGraph).
call_graph__add_arcs_in_list([Goal|Goals], Caller, CallGraph0, CallGraph) :-
call_graph__add_arcs_in_goal(Goal, Caller, CallGraph0, CallGraph1),
call_graph__add_arcs_in_list(Goals, Caller, CallGraph1, CallGraph).
%-----------------------------------------------------------------------------%
:- pred call_graph__add_arcs_in_cases(list(case), pred_proc_id,
call_graph, call_graph).
:- mode call_graph__add_arcs_in_cases(in, in, in, out) is det.
call_graph__add_arcs_in_cases([], _Caller, CallGraph, CallGraph).
call_graph__add_arcs_in_cases([case(_Cons, Goal)|Goals], Caller,
CallGraph0, CallGraph) :-
call_graph__add_arcs_in_goal(Goal, Caller, CallGraph0, CallGraph1),
call_graph__add_arcs_in_cases(Goals, Caller, CallGraph1, CallGraph).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
call_graph__write_call_graph(CallGraph, ModuleInfo) -->
{ graph__nodes(CallGraph, NodeSet) },
{ set__to_sorted_list(NodeSet, NodeList) },
call_graph__write_call_graph_2(NodeList, CallGraph, ModuleInfo).
:- pred call_graph__write_call_graph_2(list(node(pred_proc_id)), call_graph,
module_info, io__state, io__state).
:- mode call_graph__write_call_graph_2(in, in, in, di, uo) is det.
call_graph__write_call_graph_2([], _CallGraph, _ModuleInfo) --> [].
call_graph__write_call_graph_2([Node|Nodes], CallGraph, ModuleInfo) -->
{ graph__successors(CallGraph, Node, SuccSet) },
{ set__to_sorted_list(SuccSet, SuccList) },
call_graph__write_call_graph_3(SuccList, Node, CallGraph, ModuleInfo),
call_graph__write_call_graph_2(Nodes, CallGraph, ModuleInfo).
:- pred call_graph__write_call_graph_3(list(node(pred_proc_id)),
node(pred_proc_id), call_graph,
module_info, io__state, io__state).
:- mode call_graph__write_call_graph_3(in, in, in, in, di, uo) is det.
call_graph__write_call_graph_3([], _Node, _CallGraph, _ModuleInfo) -->
[].
call_graph__write_call_graph_3([S|Ss], Node, CallGraph, ModuleInfo) -->
{ graph__lookup_node(CallGraph, Node, PPPId) },
{ graph__lookup_node(CallGraph, S, CPPId) },
{ PPPId = PPredId - PProcId },
{ CPPId = 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_mode_subdecl(ModeVarSet, unqualified(PName),
PModes, PDet, PContext),
io__write_string(" -> "),
mercury_output_mode_subdecl(ModeVarSet, unqualified(CName),
CModes, CDet, CContext),
io__write_string(".\n"),
call_graph__write_call_graph_3(Ss, Node, CallGraph, ModuleInfo).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%