mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-23 13:23:47 +00:00
The reason for this is that without such limits,
- the generation of a HLDS dump for the valid/inst_perf_bug_2 test case
takes almost forever, and
- generates a multi-gigabyte HLDS dump, which causes e.g. vim to take
forever to open.
Making the generation and use of HLDS dumps practical is worth the cost
of losing some information. (Information you can't afford to generate
or to use is lost anyway.)
compiler/options.m:
doc/user_guide.texi.m:
Add a new option to limit the size of the insts we output
in the inst tables part of HLDS dumps. This option should allow users
to select the tradeoff between the amount of information being preserved
and the cost of generating/using that information.
compiler/hlds_out_module.m:
Pass the value of the new option to hlds_out_inst_table.m.
compiler/hlds_out_inst_table.m:
Specify the size limit when writing out insts as either the keys or
the values in the various kinds of inst tables.
compiler/parse_tree_to_term.m:
To implement those limits, add inst_to_limited_size_term and
inst_name_to_limited_size_term, versions of the old inst_to_term
and inst_name_to_term functions that truncate the given inst or inst name
at the given "size" if necessary. The measure of "size" is just
function symbols in the resulting term in most cases, though
we treat things that in practice never get too big, such as types,
as "one", regardless of the number of function symbols they contain.
To make the parallel between the old non-size-limiting and the new
size-limiting versions of the relevant codes easier to see, transform
the functions in the old code to predicates. (The new versions have
to be predicates to allow the size to be passed along in a state var.)
compiler/hlds_out_goal.m:
When we print out the argument modes of a unification, limit the depth
to which we write out the various insts to three. This should be
more than enough, because any inst that we now replace with "..."
should be available in the mode information of the atomic goal that
generates it, whether that goal is a unification or a call.
357 lines
14 KiB
Mathematica
357 lines
14 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2021 The Mercury team.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module hlds.hlds_out.hlds_out_inst_table.
|
|
:- interface.
|
|
|
|
:- import_module hlds.hlds_inst_mode.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.parse_tree_out_info.
|
|
|
|
:- import_module io.
|
|
|
|
:- pred write_inst_table(io.text_output_stream::in, output_lang::in,
|
|
int::in, int::in, inst_table::in, io::di, io::uo) is det.
|
|
|
|
:- pred write_mode_table(io.text_output_stream::in, mode_table::in,
|
|
io::di, io::uo) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module hlds.hlds_out.hlds_out_util.
|
|
:- import_module hlds.status.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module parse_tree.parse_tree_out_inst.
|
|
:- import_module parse_tree.parse_tree_out_misc.
|
|
:- import_module parse_tree.parse_tree_out_term.
|
|
:- import_module parse_tree.parse_tree_to_term.
|
|
:- import_module parse_tree.prog_data.
|
|
|
|
:- import_module int.
|
|
:- import_module list.
|
|
:- import_module map.
|
|
:- import_module pair.
|
|
:- import_module string.
|
|
:- import_module term.
|
|
:- import_module varset.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
write_inst_table(Stream, Lang, InstNumLimit, InstSizeLimit, InstTable, !IO) :-
|
|
io.write_string(Stream, "%-------- Insts --------\n", !IO),
|
|
|
|
inst_table_get_user_insts(InstTable, UserInstTable),
|
|
inst_table_get_unify_insts(InstTable, UnifyInstTable),
|
|
inst_table_get_merge_insts(InstTable, MergeInstTable),
|
|
inst_table_get_ground_insts(InstTable, GroundInstTable),
|
|
inst_table_get_any_insts(InstTable, AnyInstTable),
|
|
inst_table_get_shared_insts(InstTable, SharedInstTable),
|
|
inst_table_get_mostly_uniq_insts(InstTable, MostlyUniqInstTable),
|
|
|
|
map.to_sorted_assoc_list(UserInstTable, UserInstPairs),
|
|
unify_insts_to_sorted_pairs(UnifyInstTable, UnifyInstPairs),
|
|
merge_insts_to_sorted_pairs(MergeInstTable, MergeInstPairs),
|
|
ground_insts_to_sorted_pairs(GroundInstTable, GroundInstPairs),
|
|
any_insts_to_sorted_pairs(AnyInstTable, AnyInstPairs),
|
|
shared_insts_to_sorted_pairs(SharedInstTable, SharedInstPairs),
|
|
mostly_uniq_insts_to_sorted_pairs(MostlyUniqInstTable,
|
|
MostlyUniqInstPairs),
|
|
|
|
io.write_string(Stream, "%-------- User defined insts --------\n", !IO),
|
|
list.foldl(write_user_inst(Stream), UserInstPairs, !IO),
|
|
|
|
io.write_string(Stream, "%-------- Unify insts --------\n", !IO),
|
|
list.foldl2(
|
|
write_key_maybe_inst_det(Stream, Lang, InstNumLimit, InstSizeLimit,
|
|
write_key_unify_inst),
|
|
UnifyInstPairs, 0, NumUnifyInsts, !IO),
|
|
io.format(Stream,
|
|
"\nTotal number of unify insts: %d\n", [i(NumUnifyInsts)], !IO),
|
|
|
|
io.write_string(Stream, "%-------- Merge insts --------\n", !IO),
|
|
list.foldl2(
|
|
write_key_maybe_inst(Stream, Lang, InstNumLimit, InstSizeLimit,
|
|
write_key_merge_inst),
|
|
MergeInstPairs, 0, NumMergeInsts, !IO),
|
|
io.format(Stream,
|
|
"\nTotal number of merge insts: %d\n", [i(NumMergeInsts)], !IO),
|
|
|
|
io.write_string(Stream, "%-------- Ground insts --------\n", !IO),
|
|
list.foldl2(
|
|
write_key_maybe_inst_det(Stream, Lang, InstNumLimit, InstSizeLimit,
|
|
write_key_ground_inst),
|
|
GroundInstPairs, 0, NumGroundInsts, !IO),
|
|
io.format(Stream, "\nTotal number of ground insts: %d\n",
|
|
[i(NumGroundInsts)], !IO),
|
|
|
|
io.write_string(Stream, "%-------- Any insts --------\n", !IO),
|
|
list.foldl2(
|
|
write_key_maybe_inst_det(Stream, Lang, InstNumLimit, InstSizeLimit,
|
|
write_key_any_inst),
|
|
AnyInstPairs, 0, NumAnyInsts, !IO),
|
|
io.format(Stream,
|
|
"\nTotal number of any insts: %d\n", [i(NumAnyInsts)], !IO),
|
|
|
|
io.write_string(Stream, "%-------- Shared insts --------\n", !IO),
|
|
list.foldl2(
|
|
write_key_maybe_inst(Stream, Lang, InstNumLimit, InstSizeLimit,
|
|
write_inst_name_nl),
|
|
SharedInstPairs, 0, NumSharedInsts, !IO),
|
|
io.format(Stream, "\nTotal number of shared insts: %d\n",
|
|
[i(NumSharedInsts)], !IO),
|
|
|
|
io.write_string(Stream, "%-------- MostlyUniq insts --------\n", !IO),
|
|
list.foldl2(
|
|
write_key_maybe_inst(Stream, Lang, InstNumLimit, InstSizeLimit,
|
|
write_inst_name_nl),
|
|
MostlyUniqInstPairs, 0, NumMostlyUniqInsts, !IO),
|
|
io.format(Stream, "\nTotal number of mostly uniq insts: %d\n",
|
|
[i(NumMostlyUniqInsts)], !IO),
|
|
|
|
io.nl(Stream, !IO).
|
|
|
|
:- pred write_user_inst(io.text_output_stream::in,
|
|
pair(inst_ctor, hlds_inst_defn)::in, io::di, io::uo) is det.
|
|
|
|
write_user_inst(Stream, InstCtor - InstDefn, !IO) :-
|
|
InstCtor = inst_ctor(InstName, _InstArity),
|
|
io.format(Stream, "\n:- inst %s", [s(sym_name_to_string(InstName))], !IO),
|
|
InstDefn = hlds_inst_defn(InstVarSet, InstParams, InstBody,
|
|
_MaybeMatchingTypeCtors, _Context, Status),
|
|
(
|
|
InstParams = []
|
|
;
|
|
InstParams = [HeadInstParam | TailInstParams],
|
|
io.write_string(Stream, "(", !IO),
|
|
write_inst_params(Stream, HeadInstParam, TailInstParams, InstVarSet,
|
|
!IO),
|
|
io.write_string(Stream, ")", !IO)
|
|
),
|
|
InstBody = eqv_inst(EqvInst),
|
|
io.write_string(Stream, ":\n", !IO),
|
|
mercury_output_inst(Stream, output_debug, InstVarSet, EqvInst, !IO),
|
|
io.write_string(Stream, "\n", !IO),
|
|
StatusStr = inst_import_status_to_string(Status),
|
|
io.format(Stream, "%% status %s\n", [s(StatusStr)], !IO).
|
|
|
|
:- pred write_inst_params(io.text_output_stream::in, inst_var::in,
|
|
list(inst_var)::in, inst_varset::in, io::di, io::uo) is det.
|
|
|
|
write_inst_params(Stream, InstVar, InstVars, InstVarSet, !IO) :-
|
|
varset.lookup_name(InstVarSet, InstVar, InstVarName),
|
|
io.write_string(Stream, InstVarName, !IO),
|
|
(
|
|
InstVars = []
|
|
;
|
|
InstVars = [HeadInstVar | TailInstVars],
|
|
io.write_string(Stream, ", ", !IO),
|
|
write_inst_params(Stream, HeadInstVar, TailInstVars, InstVarSet, !IO)
|
|
).
|
|
|
|
:- pred write_key_maybe_inst(io.text_output_stream::in, output_lang::in,
|
|
int::in, int::in,
|
|
pred(io.text_output_stream, output_lang, int, Key, io, io)::
|
|
in(pred(in, in, in, in, di, uo) is det),
|
|
pair(Key, maybe_inst)::in, int::in, int::out, io::di, io::uo) is det.
|
|
|
|
write_key_maybe_inst(Stream, Lang, InstNumLimit, InstSizeLimit,
|
|
WriteKey, Key - MaybeInst, !N, !IO) :-
|
|
!:N = !.N + 1,
|
|
( if !.N =< InstNumLimit then
|
|
io.format(Stream, "\nEntry %d key\n", [i(!.N)], !IO),
|
|
WriteKey(Stream, Lang, InstSizeLimit, Key, !IO),
|
|
(
|
|
MaybeInst = inst_unknown,
|
|
io.format(Stream, "Entry %d value UNKNOWN\n", [i(!.N)], !IO)
|
|
;
|
|
MaybeInst = inst_known(Inst),
|
|
io.format(Stream, "Entry %d value:\n", [i(!.N)], !IO),
|
|
write_inst(Stream, Lang, InstSizeLimit, Inst, !IO),
|
|
io.nl(Stream, !IO)
|
|
)
|
|
else
|
|
true
|
|
).
|
|
|
|
:- pred write_key_maybe_inst_det(io.text_output_stream::in, output_lang::in,
|
|
int::in, int::in,
|
|
pred(io.text_output_stream, output_lang, int, Key, io, io)::
|
|
in(pred(in, in, in, in, di, uo) is det),
|
|
pair(Key, maybe_inst_det)::in, int::in, int::out,
|
|
io::di, io::uo) is det.
|
|
|
|
write_key_maybe_inst_det(Stream, Lang, InstNumLimit, InstSizeLimit,
|
|
WriteKey, Key - MaybeInstDet, !N, !IO) :-
|
|
!:N = !.N + 1,
|
|
( if !.N =< InstNumLimit then
|
|
io.format(Stream, "\nEntry %d key\n", [i(!.N)], !IO),
|
|
WriteKey(Stream, Lang, InstSizeLimit, Key, !IO),
|
|
(
|
|
MaybeInstDet = inst_det_unknown,
|
|
io.format(Stream, "Entry %d value UNKNOWN\n", [i(!.N)], !IO)
|
|
;
|
|
MaybeInstDet = inst_det_known(Inst, Detism),
|
|
DetismStr = determinism_to_string(Detism),
|
|
io.format(Stream, "Entry %d value (%s):\n",
|
|
[i(!.N), s(DetismStr)], !IO),
|
|
write_inst(Stream, Lang, InstSizeLimit, Inst, !IO),
|
|
io.nl(Stream, !IO)
|
|
)
|
|
else
|
|
true
|
|
).
|
|
|
|
:- pred write_key_unify_inst(io.text_output_stream::in, output_lang::in,
|
|
int::in, unify_inst_info::in, io::di, io::uo) is det.
|
|
|
|
write_key_unify_inst(Stream, Lang, InstSizeLimit, UnifyInstInfo, !IO) :-
|
|
UnifyInstInfo = unify_inst_info(Live, Real, InstA, InstB),
|
|
(
|
|
Live = is_live,
|
|
io.write_string(Stream, "live ", !IO)
|
|
;
|
|
Live = is_dead,
|
|
io.write_string(Stream, "dead ", !IO)
|
|
),
|
|
(
|
|
Real = real_unify,
|
|
io.write_string(Stream, "real unify\n", !IO)
|
|
;
|
|
Real = fake_unify,
|
|
io.write_string(Stream, "fake unify\n", !IO)
|
|
),
|
|
io.write_string(Stream, "InstA: ", !IO),
|
|
write_inst(Stream, Lang, InstSizeLimit, InstA, !IO),
|
|
io.nl(Stream, !IO),
|
|
io.write_string(Stream, "InstB: ", !IO),
|
|
write_inst(Stream, Lang, InstSizeLimit, InstB, !IO),
|
|
io.nl(Stream, !IO).
|
|
|
|
:- pred write_key_merge_inst(io.text_output_stream::in, output_lang::in,
|
|
int::in, merge_inst_info::in, io::di, io::uo) is det.
|
|
|
|
write_key_merge_inst(Stream, Lang, InstSizeLimit, MergeInstInfo, !IO) :-
|
|
MergeInstInfo = merge_inst_info(InstA, InstB),
|
|
io.write_string(Stream, "InstA: ", !IO),
|
|
write_inst(Stream, Lang, InstSizeLimit, InstA, !IO),
|
|
io.nl(Stream, !IO),
|
|
io.write_string(Stream, "InstB: ", !IO),
|
|
write_inst(Stream, Lang, InstSizeLimit, InstB, !IO),
|
|
io.nl(Stream, !IO).
|
|
|
|
:- pred write_key_ground_inst(io.text_output_stream::in, output_lang::in,
|
|
int::in, ground_inst_info::in, io::di, io::uo) is det.
|
|
|
|
write_key_ground_inst(Stream, Lang, InstSizeLimit, GroundInstInfo, !IO) :-
|
|
GroundInstInfo = ground_inst_info(InstName, Uniq, Live, Real),
|
|
write_uniq_live_real(Stream, Uniq, Live, Real, !IO),
|
|
write_inst_name_nl(Stream, Lang, InstSizeLimit, InstName, !IO).
|
|
|
|
:- pred write_key_any_inst(io.text_output_stream::in, output_lang::in,
|
|
int::in, any_inst_info::in, io::di, io::uo) is det.
|
|
|
|
write_key_any_inst(Stream, Lang, InstSizeLimit, AnyInstInfo, !IO) :-
|
|
AnyInstInfo = any_inst_info(InstName, Uniq, Live, Real),
|
|
write_uniq_live_real(Stream, Uniq, Live, Real, !IO),
|
|
write_inst_name_nl(Stream, Lang, InstSizeLimit, InstName, !IO).
|
|
|
|
:- pred write_uniq_live_real(io.text_output_stream::in,
|
|
uniqueness::in, is_live::in, unify_is_real::in, io::di, io::uo) is det.
|
|
|
|
write_uniq_live_real(Stream, Uniq, Live, Real, !IO) :-
|
|
(
|
|
Uniq = shared,
|
|
io.write_string(Stream, "shared ", !IO)
|
|
;
|
|
Uniq = unique,
|
|
io.write_string(Stream, "unique ", !IO)
|
|
;
|
|
Uniq = mostly_unique,
|
|
io.write_string(Stream, "mostly_unique ", !IO)
|
|
;
|
|
Uniq = clobbered,
|
|
io.write_string(Stream, "clobbered", !IO)
|
|
;
|
|
Uniq = mostly_clobbered,
|
|
io.write_string(Stream, "mostly_clobbered", !IO)
|
|
),
|
|
(
|
|
Live = is_live,
|
|
io.write_string(Stream, "live ", !IO)
|
|
;
|
|
Live = is_dead,
|
|
io.write_string(Stream, "dead ", !IO)
|
|
),
|
|
(
|
|
Real = real_unify,
|
|
io.write_string(Stream, "real unify\n", !IO)
|
|
;
|
|
Real = fake_unify,
|
|
io.write_string(Stream, "fake unify\n", !IO)
|
|
).
|
|
|
|
:- pred write_inst_name_nl(io.text_output_stream::in, output_lang::in,
|
|
int::in, inst_name::in, io::di, io::uo) is det.
|
|
|
|
write_inst_name_nl(Stream, Lang, InstSizeLimit, InstName, !IO) :-
|
|
InstNameTerm = inst_name_to_limited_size_term(Lang, InstSizeLimit,
|
|
InstName),
|
|
varset.init(VarSet),
|
|
mercury_output_term_vs(VarSet, print_name_only, InstNameTerm, Stream, !IO),
|
|
io.nl(Stream, !IO).
|
|
|
|
:- pred write_inst(io.text_output_stream::in, output_lang::in, int::in,
|
|
mer_inst::in, io::di, io::uo) is det.
|
|
|
|
write_inst(Stream, Lang, InstSizeLimit, Inst, !IO) :-
|
|
InstTerm = inst_to_limited_size_term(Lang, InstSizeLimit, Inst),
|
|
varset.init(VarSet),
|
|
mercury_output_term_vs(VarSet, print_name_only, InstTerm, Stream, !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Write out the mode table.
|
|
%
|
|
|
|
write_mode_table(Stream, ModeTable, !IO) :-
|
|
mode_table_get_mode_defns(ModeTable, ModeDefns),
|
|
io.write_string(Stream, "%-------- Modes --------\n", !IO),
|
|
map.foldl(write_mode_table_entry(Stream), ModeDefns, !IO),
|
|
io.nl(Stream, !IO).
|
|
|
|
:- pred write_mode_table_entry(io.text_output_stream::in,
|
|
mode_ctor::in, hlds_mode_defn::in, io::di, io::uo) is det.
|
|
|
|
write_mode_table_entry(Stream, ModeCtor, ModeDefn, !IO) :-
|
|
ModeCtor = mode_ctor(ModeName, _ModeArity),
|
|
io.format(Stream, "\n:- mode %s", [s(sym_name_to_string(ModeName))], !IO),
|
|
ModeDefn = hlds_mode_defn(InstVarSet, InstParams, ModeBody, _Context,
|
|
Status),
|
|
(
|
|
InstParams = []
|
|
;
|
|
InstParams = [HeadInstParam | TailInstParams],
|
|
io.write_string(Stream, "(", !IO),
|
|
write_inst_params(Stream, HeadInstParam, TailInstParams,
|
|
InstVarSet, !IO),
|
|
io.write_string(Stream, ")", !IO)
|
|
),
|
|
ModeBody = hlds_mode_body(EqvMode),
|
|
io.write_string(Stream, ":\n", !IO),
|
|
mercury_output_mode(Stream, output_debug, InstVarSet, EqvMode, !IO),
|
|
io.write_string(Stream, "\n", !IO),
|
|
StatusStr = mode_import_status_to_string(Status),
|
|
io.format(Stream, "%% status %s\n", [s(StatusStr)], !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module hlds.hlds_out.hlds_out_inst_table.
|
|
%---------------------------------------------------------------------------%
|