mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-09 02:43:21 +00:00
Estimated hours taken: 40 (+ unknown time by Zoltan)
Add support for memory profiling.
(A significant part of this change is actuallly Zoltan's work. Zoltan
did the changes to the compiler and a first go at the changes to the
runtime and library. I rewrote much of Zoltan's changes to the runtime
and library, added support for the new options/grades, added code to
interface with mprof, did the changes to the profiler, and wrote the
documentation.)
[TODO: add test cases.]
NEWS:
Mention support for memory profiling.
runtime/mercury_heap_profile.h:
runtime/mercury_heap_profile.c:
New files. These contain code to record heap profiling information.
runtime/mercury_heap.h:
Add new macros incr_hp_msg(), tag_incr_hp_msg(),
incr_hp_atomic_msg(), and tag_incr_hp_atomic_msg().
These are like the non-`msg' versions, except that if
PROFILE_MEMORY is defined, they also call MR_record_allocation()
from mercury_heap_profile.h to record heap profiling information.
Also, fix up the indentation in lots of places.
runtime/mercury_prof.h:
runtime/mercury_prof.c:
Added code to dump out memory profiling information to files
`Prof.MemoryWords' and `Prof.MemoryCells' (for use by mprof).
Change the format of the `Prof.Counts' file so that the
first line says what it is counting, the units, and a scale
factor. Prof.MemoryWords and Prof.MemoryCells can thus have
exactly the same format as Prof.Counts.
Also cleaned up the interface to mercury_prof.c a bit, and did
various other minor cleanups -- indentation changes, changes to
use MR_ prefixes, additional comments, etc.
runtime/mercury_prof_mem.h:
runtime/mercury_prof_mem.c:
Rename prof_malloc() as MR_prof_malloc().
Rename prof_make() as MR_PROF_NEW() and add MR_PROF_NEW_ARRAY().
runtime/mercury_wrapper.h:
Minor modifications to reflect the new interface to mercury_prof.c.
runtime/mercury_wrapper.c:
runtime/mercury_label.c:
Rename the old `-p' (primary cache size) option as `-C'.
Add a new `-p' option to disable profiling.
runtime/Mmakefile:
Add mercury_heap_profile.[ch].
Put the list of files in alphabetical order.
Delete some obsolete stuff for supporting `.mod' files.
Mention that libmer_dll.h and libmer_globals.h are
produced by Makefile.DLLs.
runtime/mercury_imp.h:
Mention that libmer_dll.h is produced by Makefile.DLLs.
runtime/mercury_dummy.c:
Change a comment to refer to libmer_dll.h rather than
libmer_globals.h.
compiler/llds.m:
Add a new field to `create' and `incr_hp' instructions
holding the name of the type, for heap profiling.
compiler/unify_gen.m:
Initialize the new field of `create' instructions with
the appropriate type name.
compiler/llds_out.m:
Output incr_hp_msg() / tag_incr_hp_msg() instead of
incr_hp() / tag_incr_hp().
compiler/*.m:
Minor changes to most files in the compiler back-end to
accomodate the new field in `incr_hp' and `create' instructions.
library/io.m:
Add `io__report_full_memory_stats'.
library/benchmarking.m:
Add `report_full_memory_stats'. This uses the information saved
by runtime/mercury_heap_profile.{c,h} to print out a report
of memory usage by procedures and by types.
Also modify `report_stats' to print out some of that information.
compiler/mercury_compile.m:
If `--statistics' is enabled, call io__report_full_memory_stats
at the end of main/2. This will print out full memory statistics,
if the compiler was compiled with memory profiling enabled.
compiler/options.m:
compiler/handle_options.m:
runtime/mercury_grade.h:
scripts/ml.in:
scripts/mgnuc.in:
scripts/init_grade_options.sh-subr:
scripts/parse_grade_options.sh-subr:
Add new option `--memory-profiling' and new grade `.memprof'.
Add `--time-profiling' as a new synonym for `--profiling'.
Also add `--profile-memory' for more fine-grained control:
`--memory-profiling' implies both `--profile-memory' and
`--profile-calls'.
scripts/mprof_merge_runs:
Update to handle the new format of Prof.Counts and to
also merge Prof.MemoryWords and Prof.MemoryCells.
profiler/options.m:
profiler/mercury_profile.m:
Add new options `--profile memory-words' (`-m'),
`--profile memory-cells' (`-M') and `--profile time' (`-t').
Thes options make the profiler select a different count file,
Prof.MemoryWords or Prof.MemoryCells instead of Prof.Counts.
specific to time profiling.
profiler/read.m:
profiler/process_file.m:
profiler/prof_info.m:
profiler/generate_output.m:
Update to handle the new format of the counts file.
When reading the counts file, look at the first line of
the file to determine what is being profiled.
profiler/globals.m:
Add a new global variable `what_to_profile' that records
what is being profiled.
profiler/output.m:
Change the headings to reflect what is being profiled.
doc/user_guide.texi:
Document memory profiling.
Document new options.
doc/user_guide.texi:
compiler/options.m:
Comment out the documentation for `.proftime'/`--profile-time',
since doing time and call profiling seperately doesn't work,
because the code addresses change when you recompile with a
different grade. Ditto for `.profmem'/`--profile-memory'.
Also comment out the documentation for
`.profcalls'/`--profile-calls', since it is redundant --
`.memprof' produces the same information and more.
configure.in:
Build a `.memprof' grade. (Hmm, should we do this only
if `--enable-all-grades' is specified?)
Don't ever build a `.profcalls' grade.
441 lines
14 KiB
Mathematica
441 lines
14 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1995-1997 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.
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% prof_info.m
|
|
|
|
% Main author: petdr.
|
|
%
|
|
% Declare the main data structures for mercury__profile and their access
|
|
% predicates, the actual types are exported as well. This is because some
|
|
% predicates need to access entire data structure.
|
|
% XXX Should maybe changed at a later date.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module prof_info.
|
|
|
|
:- interface.
|
|
|
|
:- import_module list, map.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
|
|
% prof: Data structure which contains ALL the relevant info for use
|
|
% in generating the output.
|
|
:- type prof.
|
|
|
|
% addrdecl = map(label_name, label_address)
|
|
:- type addrdecl == map(string, int).
|
|
|
|
% prof_node_map = map(label_address, prof_node)
|
|
:- type prof_node_map == map(int, prof_node).
|
|
|
|
% cycle_map == map(predicate_name, cycle it is in).
|
|
:- type cycle_map == map(string, int).
|
|
|
|
% prof_node: Contains all the info used for output, for a single pred.
|
|
:- type prof_node.
|
|
|
|
:- type pred_info.
|
|
|
|
:- type prof_node_type
|
|
---> predicate
|
|
; cycle.
|
|
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
|
|
% *** Get prof_node from via predicate name *** %
|
|
|
|
:- pred get_prof_node(string, addrdecl, prof_node_map, prof_node).
|
|
:- mode get_prof_node(in, in, in, out) is det.
|
|
|
|
:- pred update_prof_node(string,prof_node,addrdecl,prof_node_map,prof_node_map).
|
|
:- mode update_prof_node(in, in, in, in, out) is det.
|
|
|
|
|
|
% *** Initialise prof predicates *** %
|
|
|
|
:- pred prof_node_init(string, prof_node).
|
|
:- mode prof_node_init(in, out) is det.
|
|
|
|
:- pred prof_node_init_cycle(string, int, int, float, list(pred_info), int,
|
|
int, prof_node).
|
|
:- mode prof_node_init_cycle(in, in, in, in, in, in, in, out) is det.
|
|
|
|
|
|
% *** Access prof predicates *** %
|
|
|
|
:- pred prof_get_entire(prof,
|
|
float, string, int, addrdecl, prof_node_map, cycle_map).
|
|
:- mode prof_get_entire(in, out, out, out, out, out, out) is det.
|
|
|
|
:- pred prof_get_addrdeclmap(prof, addrdecl).
|
|
:- mode prof_get_addrdeclmap(in, out) is det.
|
|
|
|
:- pred prof_get_profnodemap(prof, prof_node_map).
|
|
:- mode prof_get_profnodemap(in, out) is det.
|
|
|
|
|
|
% *** Update prof predicates *** %
|
|
|
|
:- pred prof_set_entire(float, string, int, addrdecl, prof_node_map, cycle_map,
|
|
prof).
|
|
:- mode prof_set_entire(in, in, in, in, in, in, out) is det.
|
|
|
|
:- pred prof_set_profnodemap(prof_node_map, prof, prof).
|
|
:- mode prof_set_profnodemap(in, in, out) is det.
|
|
|
|
:- pred prof_set_cyclemap(cycle_map, prof, prof).
|
|
:- mode prof_set_cyclemap(in, in, out) is det.
|
|
|
|
|
|
% *** Special prof_node predicates *** %
|
|
|
|
:- pred prof_node_type(prof_node, prof_node_type).
|
|
:- mode prof_node_type(in, out) is det.
|
|
|
|
|
|
% *** Access Predicate for prof_node *** %
|
|
|
|
:- pred prof_node_get_entire_pred(prof_node, string, int, int, float,
|
|
list(pred_info), list(pred_info),
|
|
int, int, list(string)).
|
|
:- mode prof_node_get_entire_pred(in, out, out, out, out, out, out, out, out,
|
|
out) is det.
|
|
|
|
:- pred prof_node_get_entire_cycle(prof_node, string, int, int, float,
|
|
list(pred_info), int, int).
|
|
:- mode prof_node_get_entire_cycle(in,out,out,out,out,out,out,out) is det.
|
|
|
|
:- pred prof_node_get_pred_name(prof_node, string).
|
|
:- mode prof_node_get_pred_name(in, out) is det.
|
|
|
|
:- pred prof_node_get_cycle_number(prof_node, int).
|
|
:- mode prof_node_get_cycle_number(in, out) is det.
|
|
|
|
:- pred prof_node_get_initial_counts(prof_node, int).
|
|
:- mode prof_node_get_initial_counts(in, out) is det.
|
|
|
|
:- pred prof_node_get_propagated_counts(prof_node, float).
|
|
:- mode prof_node_get_propagated_counts(in, out) is det.
|
|
|
|
:- pred prof_node_get_parent_list(prof_node, list(pred_info)).
|
|
:- mode prof_node_get_parent_list(in, out) is det.
|
|
|
|
:- pred prof_node_get_child_list(prof_node, list(pred_info)).
|
|
:- mode prof_node_get_child_list(in, out) is det.
|
|
|
|
:- pred prof_node_get_total_calls(prof_node, int).
|
|
:- mode prof_node_get_total_calls(in, out) is det.
|
|
|
|
:- pred prof_node_get_self_calls(prof_node, int).
|
|
:- mode prof_node_get_self_calls(in, out) is det.
|
|
|
|
|
|
% *** Update prof_node predicates *** %
|
|
|
|
:- pred prof_node_set_cycle_num(int, prof_node, prof_node).
|
|
:- mode prof_node_set_cycle_num(in, in, out) is det.
|
|
|
|
:- pred prof_node_set_initial_counts(int, prof_node, prof_node).
|
|
:- mode prof_node_set_initial_counts(in, in, out) is det.
|
|
|
|
:- pred prof_node_set_propagated_counts(float, prof_node, prof_node).
|
|
:- mode prof_node_set_propagated_counts(in, in, out) is det.
|
|
|
|
:- pred prof_node_concat_to_parent(string, int, prof_node, prof_node).
|
|
:- mode prof_node_concat_to_parent(in, in, in, out) is det.
|
|
|
|
:- pred prof_node_concat_to_child(string, int, prof_node, prof_node).
|
|
:- mode prof_node_concat_to_child(in, in, in, out) is det.
|
|
|
|
:- pred prof_node_set_total_calls(int, prof_node, prof_node).
|
|
:- mode prof_node_set_total_calls(in, in, out) is det.
|
|
|
|
:- pred prof_node_set_self_calls(int, prof_node, prof_node).
|
|
:- mode prof_node_set_self_calls(in, in, out) is det.
|
|
|
|
:- pred prof_node_concat_to_name_list(string, prof_node, prof_node).
|
|
:- mode prof_node_concat_to_name_list(in, in, out) is det.
|
|
|
|
:- pred prof_node_concat_to_member(string, int, prof_node, prof_node).
|
|
:- mode prof_node_concat_to_member(in, in, in, out) is det.
|
|
|
|
|
|
% *** Init predicates for pred_info *** %
|
|
|
|
:- pred pred_info_init(string, int, pred_info).
|
|
:- mode pred_info_init(in, in, out) is det.
|
|
|
|
|
|
% *** Access predicates for pred_info *** %
|
|
|
|
:- pred pred_info_get_entire(pred_info, string, int).
|
|
:- mode pred_info_get_entire(in, out, out) is det.
|
|
|
|
:- pred pred_info_get_pred_name(pred_info, string).
|
|
:- mode pred_info_get_pred_name(in, out) is det.
|
|
|
|
:- pred pred_info_get_counts(pred_info, int).
|
|
:- mode pred_info_get_counts(in, out) is det.
|
|
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
|
|
:- implementation.
|
|
:- import_module require, std_util.
|
|
|
|
:- type prof --->
|
|
prof(
|
|
float, % Scaling factor
|
|
string, % Units
|
|
% (Each profiling count is
|
|
% equivalent to Scale Units)
|
|
int, % Total counts of the profile
|
|
% run
|
|
addrdecl, % Map between label name and
|
|
% label addr used to find key
|
|
% to look up prof_node_map.
|
|
prof_node_map, % Map between label addresses
|
|
% and all the relevant data
|
|
% about that predicate
|
|
cycle_map % Map between predicate name
|
|
% and it's cycle number.
|
|
).
|
|
|
|
|
|
:- type prof_node
|
|
--->
|
|
% A node which consists of just one predicate.
|
|
pred_node(
|
|
string, % current predicate (label)
|
|
int, % cycle number
|
|
int, % self counts
|
|
float, % propagated counts
|
|
list(pred_info), % Parent pred and the number
|
|
% of times it calls this
|
|
% predicate
|
|
list(pred_info), % Child pred and the number of
|
|
% times they are called from
|
|
% this predicate.
|
|
int, % total count of times this
|
|
% predicate called.
|
|
int, % Number of self recursive
|
|
% calls of this routine
|
|
list(string) % Alternative names for this
|
|
% predicate eg. Labels with
|
|
% different names but the same
|
|
% address.
|
|
)
|
|
;
|
|
% A node which is built up with more then one predicate
|
|
% and is a cycle.
|
|
cycle_node(
|
|
string, % cycle name
|
|
int, % cycle number
|
|
int, % self counts
|
|
float, % propagated counts
|
|
list(pred_info), % Cycle members plus total calls
|
|
% to that predicated
|
|
int, % total count of times this
|
|
% predicate called.
|
|
int % Number of calls to fellow
|
|
% cycle members
|
|
).
|
|
|
|
:- type pred_info --->
|
|
pred_info(
|
|
string, % predicate (label)
|
|
int % count (to or from)
|
|
).
|
|
|
|
:- type junk == unit.
|
|
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
|
|
% get_prof_node:
|
|
% Gets the prof_node given a label name.
|
|
%
|
|
get_prof_node(Pred, AddrMap, ProfNodeMap, ProfNode) :-
|
|
map__lookup(AddrMap, Pred, Key),
|
|
map__lookup(ProfNodeMap, Key, ProfNode).
|
|
|
|
|
|
update_prof_node(Pred, ProfNode, AddrMap, ProfNodeMap0, ProfNodeMap) :-
|
|
map__lookup(AddrMap, Pred, Key),
|
|
map__det_update(ProfNodeMap0, Key, ProfNode, ProfNodeMap).
|
|
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
|
|
% *** Access prof predicates *** %
|
|
|
|
prof_get_entire(prof(A, B, C, D, E, F), A, B, C, D, E, F).
|
|
|
|
prof_get_addrdeclmap(prof(_, _, _, AddrDeclMap, _, _), AddrDeclMap).
|
|
|
|
prof_get_profnodemap(prof(_, _, _, _, ProfNodeMap, _), ProfNodeMap).
|
|
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
|
|
% *** Update prof predicates *** %
|
|
|
|
prof_set_entire(A, B, C, D, E, F, prof(A, B, C, D, E, F)).
|
|
|
|
prof_set_profnodemap(ProfNodeMap, prof(A, B, C, D, _, F),
|
|
prof(A, B, C, D, ProfNodeMap, F)).
|
|
|
|
prof_set_cyclemap(CycleMap, prof(A, B, C, D, E, _),
|
|
prof(A, B, C, D, E, CycleMap)).
|
|
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
|
|
% *** Initialise predicates *** %
|
|
|
|
prof_node_init(PredName, pred_node(PredName, 0, 0, 0.0, [], [], 0, 0, [])).
|
|
|
|
prof_node_init_cycle(A, B, C, D, E, F, G, cycle_node(A, B, C, D, E, F, G)).
|
|
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
|
|
% *** Special prof_node predicates *** %
|
|
|
|
prof_node_type(pred_node(_,_,_,_,_,_,_,_,_), predicate).
|
|
prof_node_type(cycle_node(_,_,_,_,_,_,_), cycle).
|
|
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
|
|
% *** Access prof_node predicates *** %
|
|
|
|
prof_node_get_entire_pred(pred_node(A,B,C,D,E,F,G,H,I),A,B,C,D,E,F,G,H,I).
|
|
prof_node_get_entire_pred(cycle_node(_,_,_,_,_,_,_),_,_,_,_,_,_,_,_,_) :-
|
|
error("prof_node_get_entire_pred: not a pred\n").
|
|
|
|
prof_node_get_entire_cycle(cycle_node(A,B,C,D,E,F,G),A,B,C,D,E,F,G).
|
|
prof_node_get_entire_cycle(pred_node(_,_,_,_,_,_,_,_,_),_,_,_,_,_,_,_) :-
|
|
error("prof_node_get_entire_cycle: not a cycle\n").
|
|
|
|
prof_node_get_pred_name(pred_node(Name, _, _, _, _, _, _, _, _), Name).
|
|
prof_node_get_pred_name(cycle_node(Name, _, _, _, _, _, _), Name).
|
|
|
|
prof_node_get_cycle_number(pred_node(_, Cycle, _, _, _, _, _, _, _), Cycle).
|
|
prof_node_get_cycle_number(cycle_node(_, Cycle, _, _, _, _, _), Cycle).
|
|
|
|
prof_node_get_initial_counts(pred_node(_, _, Count, _, _, _, _, _, _), Count).
|
|
prof_node_get_initial_counts(cycle_node(_, _, Count, _, _, _, _), Count).
|
|
|
|
prof_node_get_propagated_counts(pred_node(_, _, _, Count, _, _, _, _, _),
|
|
Count).
|
|
prof_node_get_propagated_counts(cycle_node(_, _, _, Count, _, _, _), Count).
|
|
|
|
prof_node_get_parent_list(pred_node(_, _, _, _, PList, _, _, _, _), PList).
|
|
prof_node_get_parent_list(cycle_node(_, _, _, _, _, _, _), _) :-
|
|
error("prof_node_get_parent_list: cycle_node has no parent list\n").
|
|
|
|
prof_node_get_child_list(pred_node(_, _, _, _, _, Clist, _, _, _), Clist).
|
|
prof_node_get_child_list(cycle_node(_, _, _, _, _, _, _), _) :-
|
|
error("prof_node_get_child_list: cycle_node has no child list\n").
|
|
|
|
prof_node_get_total_calls(pred_node(_, _, _, _, _, _, Calls, _, _), Calls).
|
|
prof_node_get_total_calls(cycle_node(_, _, _, _, _, Calls, _), Calls).
|
|
|
|
prof_node_get_self_calls(pred_node(_, _, _, _, _, _, _, Calls, _), Calls).
|
|
prof_node_get_self_calls(cycle_node(_, _, _, _, _, _, Calls), Calls).
|
|
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
|
|
% *** Update prof_node predicates *** %
|
|
|
|
prof_node_set_cycle_num(Cycle, pred_node(A, _, C, D, E, F, G, H, I),
|
|
pred_node(A, Cycle, C, D, E, F, G, H, I)).
|
|
prof_node_set_cycle_num(Cycle, cycle_node(A, _, C, D, E, F, G),
|
|
cycle_node(A, Cycle, C, D, E, F, G)).
|
|
|
|
prof_node_set_initial_counts(Count, pred_node(A, B, _, D, E, F, G, H, I),
|
|
pred_node(A, B, Count, D, E, F, G, H, I)).
|
|
prof_node_set_initial_counts(Count, cycle_node(A, B, _, D, E, F, G),
|
|
cycle_node(A, B, Count, D, E, F, G)).
|
|
|
|
prof_node_set_propagated_counts(Count, pred_node(A, B, C, _, E, F, G, H, I),
|
|
pred_node(A, B, C, Count, E, F, G, H, I)).
|
|
prof_node_set_propagated_counts(Count, cycle_node(A, B, C, _, E, F, G),
|
|
cycle_node(A, B, C, Count, E, F, G)).
|
|
|
|
prof_node_concat_to_parent(Name,Count, pred_node(A, B, C, D, PList, F, G, H, I),
|
|
pred_node(A, B, C, D, [pred_info(Name,Count) | PList], F, G, H, I)).
|
|
prof_node_concat_to_parent(_, _, cycle_node(_, _, _, _, _, _, _), _) :-
|
|
error("prof_node_concat_to_parent: cycle_node has no parents\n").
|
|
|
|
prof_node_concat_to_child(Name, Count, pred_node(A, B, C, D, E, CList, G, H, I),
|
|
pred_node(A, B, C, D, E, [pred_info(Name,Count) | CList], G, H, I)).
|
|
prof_node_concat_to_child(_, _, cycle_node(_, _, _, _, _, _, _), _) :-
|
|
error("prof_node_concat_to_child: cycle_node has no child\n").
|
|
|
|
prof_node_set_total_calls(Calls, pred_node(A, B, C, D, E, F, _, H, I),
|
|
pred_node(A, B, C, D, E, F, Calls, H, I)).
|
|
prof_node_set_total_calls(Calls, cycle_node(A, B, C, D, E, _, G),
|
|
cycle_node(A, B, C, D, E, Calls, G)).
|
|
|
|
prof_node_set_self_calls(Calls, pred_node(A, B, C, D, E, F, G, _, I),
|
|
pred_node(A, B, C, D, E, F, G, Calls, I)).
|
|
prof_node_set_self_calls(Calls, cycle_node(A, B, C, D, E, F, _),
|
|
cycle_node(A, B, C, D, E, F, Calls)).
|
|
|
|
prof_node_concat_to_name_list(Name, pred_node(A, B, C, D, E, F, G, H, NL),
|
|
pred_node(A, B, C, D, E, F, G, H, [Name | NL])).
|
|
prof_node_concat_to_name_list(_, cycle_node(_, _, _, _, _, _, _), _) :-
|
|
error("prof_node_concat_to_name_list: cycle_node has no namelist\n").
|
|
|
|
prof_node_concat_to_member(Name, Count, cycle_node(A, B, C, D, CList, F, G),
|
|
cycle_node(A, B, C, D, [pred_info(Name,Count) | CList], F, G)).
|
|
prof_node_concat_to_member(_, _, pred_node(_, _, _, _, _, _, _, _, _), _) :-
|
|
error("prof_node_concat_to_member: pred_node has no members\n").
|
|
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
|
|
% *** Init predicates for pred_info *** %
|
|
|
|
pred_info_init(Name, Count, pred_info(Name, Count)).
|
|
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
|
|
% *** Access predicates for pred_info *** %
|
|
|
|
pred_info_get_entire(pred_info(A, B), A, B).
|
|
|
|
pred_info_get_pred_name(pred_info(Name, _), Name).
|
|
|
|
pred_info_get_counts(pred_info(_, Count), Count).
|
|
|
|
|
|
%-----------------------------------------------------------------------------%
|