Files
mercury/deep_profiler/message.m
Zoltan Somogyi 9095985aa8 Fix more warnings from --warn-inconsistent-pred-order-clauses.
deep_profiler/*.m:
    Fix inconsistencies between (a) the order in which functions and predicates
    are declared, and (b) the order in which they are defined.

    In most modules, either the order of the declarations or the order
    of the definitions made sense, and I changed the other to match.
    In some modules, neither made sense, so I changed *both* to an order
    that *does* make sense (i.e. it has related predicates together).

    In query.m, put the various commands in the same sensible order
    as the code processing them.

    In html_format.m, merge two exported functions together, since
    they can't be used separately.

    In some places, put dividers between groups of related
    functions/predicates, to make the groups themselves more visible.

    In some places, fix comments or programming style.

deep_profiler/DEEP_FLAGS.in:
    Since all the modules in this directory are now free from any warnings
    generated by --warn-inconsistent-pred-order-clauses, specify that option
    by default in this directory to keep it that way.
2017-04-30 15:48:13 +10:00

429 lines
16 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 2009-2011 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.
%---------------------------------------------------------------------------%
%
% File: message.m.
% Author: pbone.
%
% This module contains types and predicates for building messages used by the
% mdprof_create_feedback tool. These messages can represent information such as
% warnings and errors. Code is also included here to print them out.
%
%---------------------------------------------------------------------------%
:- module message.
:- interface.
:- import_module mdbcomp.
:- import_module mdbcomp.goal_path.
:- import_module mdbcomp.program_representation.
:- import_module profile.
:- import_module cord.
:- import_module io.
%---------------------------------------------------------------------------%
% A message to be displayed to the user.
%
:- type message
---> message(
message_location :: program_location,
message_type :: message_type
).
% The 'importance' of a message. Debug messages are not covered here since
% they should be implemented via trace goals. Neither are critical messages
% since we use exceptions in that case.
%
:- type message_level
---> message_info
; message_notice
; message_warning
; message_error.
:- type program_location
---> pl_proc(string_proc_label)
; pl_goal(string_proc_label, reverse_goal_path)
; pl_clique(clique_ptr)
; pl_csd(call_site_dynamic_ptr).
%---------------------------------------------------------------------------%
:- func message_get_level(message) = message_level.
:- func message_level_to_int(message_level) = int.
:- pred message_to_string(message::in, string::out) is det.
% location_to_string(IndentLevel, Location, String).
%
% Pretty-print a location to a cord of strings.
%
:- pred location_to_string(int::in, program_location::in, cord(string)::out)
is det.
:- pred append_message(program_location::in, message_type::in,
cord(message)::in, cord(message)::out) is det.
%---------------------------------------------------------------------------%
:- type message_type
---> info_found_candidate_conjunction
% A candidate parallel conjunction has been found.
; info_found_conjs_above_callsite_threshold(int)
% There are a number of conjuncts containing calls above the
% configured call site threshold, we are considering them for
% parallelisation against one another.
; info_found_pushed_conjs_above_callsite_threshold
% There are two of conjuncts containing calls above the
% configured call site threshold that can be pushed together,
% we are considering them for parallelisation against one another.
; info_split_conjunction_into_partitions(int)
% The conjunction being considered for parallelisation had to be
% split into several 'partitions' because it contains some
% nonatomic goals; this can limit the amount of parallelism
% available.
; info_found_n_conjunctions_with_positive_speedup(int)
% There are N conjunctions whose speedup due to parallelisation
% is positive.
; notice_duplicate_instantiation(
% This occurs when a variable is instantiated twice in a
% procedure body (different instantiation states are used).
% We don't bother parallelising such procedures.
%
% The number of conjunctions that could have been
% parallelised.
int
)
; notice_callpair_has_more_than_one_dependant_var
% A pair of calls that could be parallelised have many
% dependent variables. We don't yet calculate the speedup in
% these situations.
; notice_partition_does_not_have_costly_calls(int, int)
% A partition does not enough enough costly calls (>1) and
% could not be parallelised, we could have parallelised them
% if we could parallelise over non-atomic code.
%
% The parameters are the partition number and the number of
% costly calls found.
; notice_candidate_conjunction_not_det(detism_rep)
% The candidate conjunction has goals that are not
% deterministic or cc_multi amongst the costly calls.
; warning_cannot_lookup_proc_defn
% Couldn't find the proc defn in the progrep data, maybe the
% procedure is built-in.
; warning_cannot_compute_procrep_coverage_fallback(string)
% Couldn't compute the coverage annotation for a procedure
% representation. A fallback method will be used but without
% this information it may be less accurate.
; warning_cannot_compute_cost_of_recursive_calls(string)
% Couldn't compute the cost of recursive calls.
%
% The parameter contains extra information about this error.
; warning_cannot_compute_first_use_time(string)
% Couldn't compute the time at which a variable is produced
% or consumed.
%
% The parameter contains extra information about this error.
; error_extra_proc_dynamics_in_clique_proc
% We don't yet handle clique_proc_reports with multiple proc
% dynamics.
; error_cannot_lookup_coverage_points
% An error in the generation of a coverage_procrep report.
; error_exception_thrown(string).
%---------------------------------------------------------------------------%
% Create an indentation of the appropriate amount. Indentation is two
% spaces per indentation level.
%
:- func indent(int) = cord(string).
% Create a new line proceeded by an indentation.
%
:- func nl_indent(int) = cord(string).
% A newline symbol.
:- func nl = cord(string).
% The size of an indentation level. 2 x the input.
%
:- func indent_size(int) = int.
%---------------------------------------------------------------------------%
% Write out messages.
%
:- pred write_out_messages(io.output_stream::in, cord(message)::in,
io::di, io::uo) is det.
% Set the verbosity level to use above. Higher levels print out more
% information. Levels are in the inclusive range 0..4.
%
:- pred set_verbosity_level(int::in, io::di, io::uo) is det.
% The default verbosity level if set_verbosity_level is never called.
%
:- func default_verbosity_level = int.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module program_representation_utils.
:- import_module int.
:- import_module list.
:- import_module require.
:- import_module string.
%---------------------------------------------------------------------------%
message_get_level(message(_, Type)) =
message_type_to_level(Type).
%---------------------------------------------------------------------------%
message_level_to_int(message_info) = 4.
message_level_to_int(message_notice) = 3.
message_level_to_int(message_warning) = 2.
message_level_to_int(message_error) = 1.
%---------------------------------------------------------------------------%
message_to_string(message(Location, MessageType), String) :-
location_to_string(1, Location, LocationString),
Level = message_type_to_level(MessageType),
LevelString = message_level_to_string(Level),
MessageStr = message_type_to_string(MessageType),
Cord = LevelString ++ singleton(":\n") ++ LocationString ++
indent(1) ++ MessageStr ++ singleton("\n"),
append_list(cord.list(Cord), String).
location_to_string(Level, Location, String) :-
(
Location = pl_proc(ProcLabel),
print_proc_label_to_string(ProcLabel, ProcLabelString),
String = indent(Level) ++ singleton("Proc: ") ++
singleton(ProcLabelString) ++ singleton("\n")
;
Location = pl_goal(ProcLabel, RevGoalPath),
location_to_string(Level, pl_proc(ProcLabel), FirstLine),
(
RevGoalPath = rgp_nil,
GoalPathString = singleton("Root goal")
;
RevGoalPath = rgp_cons(_, _),
GoalPathString = singleton("Goal: ") ++
singleton(rev_goal_path_to_string(RevGoalPath))
),
SecondLine = indent(Level) ++ GoalPathString ++ singleton("\n"),
String = FirstLine ++ SecondLine
;
Location = pl_clique(clique_ptr(Id)),
format("clique %d", [i(Id)], String0),
String = indent(Level) ++ singleton(String0)
;
Location = pl_csd(CSDPtr),
CSDPtr = call_site_dynamic_ptr(CSDNum),
format("call site dynamic %d", [i(CSDNum)], String0),
String = indent(Level) ++ singleton(String0)
).
%---------------------------------------------------------------------------%
append_message(Location, MessageType, !Messages) :-
Message = message(Location, MessageType),
!:Messages = cord.snoc(!.Messages, Message).
%---------------------------------------------------------------------------%
:- func message_level_to_string(message_level) = cord(string).
message_level_to_string(message_info) = singleton("Info").
message_level_to_string(message_notice) = singleton("Notice").
message_level_to_string(message_warning) = singleton("Warning").
message_level_to_string(message_error) = singleton("Error").
%---------------------------------------------------------------------------%
:- func message_type_to_level(message_type) = message_level.
message_type_to_level(MsgType) = MsgLevel :-
(
( MsgType = info_found_candidate_conjunction
; MsgType = info_found_conjs_above_callsite_threshold(_)
; MsgType = info_found_pushed_conjs_above_callsite_threshold
; MsgType = info_found_n_conjunctions_with_positive_speedup(_)
; MsgType = info_split_conjunction_into_partitions(_)
),
MsgLevel = message_info
;
( MsgType = notice_duplicate_instantiation(_)
; MsgType = notice_callpair_has_more_than_one_dependant_var
; MsgType = notice_partition_does_not_have_costly_calls(_, _)
; MsgType = notice_candidate_conjunction_not_det(_)
),
MsgLevel = message_notice
;
( MsgType = warning_cannot_lookup_proc_defn
; MsgType = warning_cannot_compute_procrep_coverage_fallback(_)
; MsgType = warning_cannot_compute_cost_of_recursive_calls(_)
; MsgType = warning_cannot_compute_first_use_time(_)
),
MsgLevel = message_warning
;
( MsgType = error_extra_proc_dynamics_in_clique_proc
; MsgType = error_exception_thrown(_)
; MsgType = error_cannot_lookup_coverage_points
),
MsgLevel = message_error
).
%---------------------------------------------------------------------------%
:- func message_type_to_string(message_type) = cord(string).
message_type_to_string(MessageType) = Cord :-
(
MessageType = info_found_candidate_conjunction,
String = "Found candidate conjunction"
;
MessageType = error_cannot_lookup_coverage_points,
String = "Cannot lookup coverage points"
;
(
MessageType = info_found_conjs_above_callsite_threshold(Num),
MessageStr = "Found %d conjuncts above callsite threshold"
;
MessageType = info_found_n_conjunctions_with_positive_speedup(Num),
MessageStr = "Found %d conjunctions with a positive speedup due"
++ " to parallelisation"
;
MessageType = info_split_conjunction_into_partitions(Num),
MessageStr = "Split conjunction into %d partitions, "
++ "this may reduce parallelism"
),
string.format(MessageStr, [i(Num)], String)
;
MessageType = info_found_pushed_conjs_above_callsite_threshold,
String = "Found pushed conjuncts above callsite threshold"
;
MessageType = notice_duplicate_instantiation(CandidateConjuncts),
string.format(
"%d conjunctions not parallelised: Seen duplicate instantiations",
[i(CandidateConjuncts)], String)
;
MessageType = notice_callpair_has_more_than_one_dependant_var,
String = "Parallelising call pairs that have more than one "
++ "dependent variable is not yet supported."
;
MessageType = notice_partition_does_not_have_costly_calls(PartNum,
NumCalls),
string.format("Partition %d has only %d costly calls and cannot be"
++ " parallelised",
[i(PartNum), i(NumCalls)], String)
;
MessageType = notice_candidate_conjunction_not_det(Detism),
string.format("There are %s goals amongst goals"
++ " above the parallelisation overhead.",
[s(string(Detism))], String)
;
MessageType = warning_cannot_lookup_proc_defn,
String = "Could not look up proc defn, perhaps this procedure is"
++ " built-in"
;
MessageType = warning_cannot_compute_procrep_coverage_fallback(Error),
String = "Cannot compute procrep coverage annotation: " ++ Error
++ "\n falling back to some other method"
;
MessageType = error_extra_proc_dynamics_in_clique_proc,
String = "extra proc dynamics for a clique proc are not currently"
++ " handled."
;
(
MessageType = error_exception_thrown(ErrorStr),
Template = "Exception thrown: %s"
;
MessageType =
warning_cannot_compute_cost_of_recursive_calls(ErrorStr),
Template = "Cannot compute cost of recursive calls: %s"
;
MessageType =
warning_cannot_compute_first_use_time(ErrorStr),
Template = "Cannot compute the production or consumption time "
++ "of a variable: %s"
),
string.format(Template, [s(ErrorStr)], String)
),
Cord = singleton(String).
%---------------------------------------------------------------------------%
indent(N) = Indent :-
( if N < 0 then
error("automatic_parallelism: Negative indent")
else if N = 0 then
Indent = empty
else
Indent = snoc(indent(N - 1), " ")
).
nl_indent(N) = nl ++ indent(N).
nl = singleton("\n").
indent_size(N) = 2 * N.
%---------------------------------------------------------------------------%
:- mutable(verbosity_level_mut, int, default_verbosity_level, ground,
[attach_to_io_state, untrailed]).
write_out_messages(Stream, Messages, !IO) :-
cord.foldl_pred(write_out_message(Stream), Messages, !IO).
:- pred write_out_message(output_stream::in, message::in, io::di, io::uo)
is det.
write_out_message(Stream, Message, !IO) :-
Level = message_get_level(Message),
get_verbosity_level_mut(VerbosityLevel, !IO),
( if message_level_to_int(Level) =< VerbosityLevel then
message_to_string(Message, MessageStr),
io.write_string(Stream, MessageStr, !IO),
io.nl(Stream, !IO)
else
true
).
set_verbosity_level(VerbosityLevel, !IO) :-
set_verbosity_level_mut(VerbosityLevel, !IO).
default_verbosity_level = 2.
%---------------------------------------------------------------------------%
:- end_module message.
%---------------------------------------------------------------------------%