mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-18 15:26:31 +00:00
Estimated hours taken: 8 options.m: Rename branch_delay_slot to have_delay_slot. Set optimize_delay_slot in -O2 only if have_delay_slot was set earlier. This is possible now because the default optimization level is now set in mc. mercury_compile: Change verbose output a bit to be more consistent. dead_proc_elim: Export the predicates that will eventually be needed by inlining.m. inlining.m: Use the information about the number of times each procedure is called to inline local nonrecursive procedures that are called exactly once. EXCEPT that this is turned off at the moment, since the inlining of parse_dcg_goal_2 in prog_io, which this change enables, causes the compiler to emit incorrect code. prog_io: Moved the data type definitions to prog_data. (Even though prog_io.m is ten times the size of prog_data.m, the sizes of the .c files are not too dissimilar.)
345 lines
13 KiB
Mathematica
345 lines
13 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.
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Detects undefined `inst's and `mode's and reports appropriate error
|
|
% messages.
|
|
|
|
% Main author: fjh.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module undef_modes.
|
|
|
|
:- interface.
|
|
|
|
:- import_module hlds_module.
|
|
:- import_module bool, io, std_util.
|
|
|
|
:- pred check_undefined_modes(module_info, module_info, bool,
|
|
io__state, io__state).
|
|
:- mode check_undefined_modes(in, out, out, di, uo) is det.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module hlds_pred, hlds_data, prog_data, prog_out, hlds_out.
|
|
:- import_module list, map, std_util, require.
|
|
|
|
% Check for any possible undefined insts/modes.
|
|
% Should we add a definition for undefined insts/modes?
|
|
|
|
check_undefined_modes(Module, Module, FoundError) -->
|
|
io__get_exit_status(ExitStatus0),
|
|
io__set_exit_status(0),
|
|
{ module_info_insts(Module, InstDefns) },
|
|
{ inst_table_get_user_insts(InstDefns, UserInstDefns) },
|
|
{ map__keys(UserInstDefns, InstIds) },
|
|
{ module_info_modes(Module, ModeDefns) },
|
|
find_undef_inst_bodies(InstIds, ModeDefns, UserInstDefns),
|
|
{ map__keys(ModeDefns, ModeIds) },
|
|
find_undef_mode_bodies(ModeIds, ModeDefns, UserInstDefns),
|
|
{ module_info_preds(Module, Preds) },
|
|
{ module_info_predids(Module, PredIds) },
|
|
find_undef_pred_modes(PredIds, Preds, ModeDefns, UserInstDefns),
|
|
io__get_exit_status(ExitStatus1),
|
|
( { ExitStatus1 = 0 } ->
|
|
{ FoundError = no }
|
|
;
|
|
{ FoundError = yes }
|
|
),
|
|
io__set_exit_status(ExitStatus0).
|
|
|
|
% Find any undefined insts/modes used in predicate mode declarations.
|
|
|
|
:- pred find_undef_pred_modes(list(pred_id), pred_table, mode_table,
|
|
user_inst_table, io__state, io__state).
|
|
:- mode find_undef_pred_modes(in, in, in, in, di, uo) is det.
|
|
|
|
find_undef_pred_modes([], _Preds, _ModeDefns, _InstDefns) --> [].
|
|
find_undef_pred_modes([PredId | PredIds], Preds, ModeDefns, InstDefns) -->
|
|
{ map__lookup(Preds, PredId, PredDefn) },
|
|
{ pred_info_procedures(PredDefn, Procs) },
|
|
{ map__keys(Procs, ProcIds) },
|
|
find_undef_proc_modes(ProcIds, PredId, Procs, ModeDefns, InstDefns),
|
|
find_undef_pred_modes(PredIds, Preds, ModeDefns, InstDefns).
|
|
|
|
:- pred find_undef_proc_modes(list(proc_id), pred_id, proc_table, mode_table,
|
|
user_inst_table, io__state, io__state).
|
|
:- mode find_undef_proc_modes(in, in, in, in, in, di, uo) is det.
|
|
|
|
find_undef_proc_modes([], _PredId, _Procs, _ModeDefns, _InstDefns) --> [].
|
|
find_undef_proc_modes([ProcId | ProcIds], PredId, Procs, ModeDefns,
|
|
InstDefns) -->
|
|
{ map__lookup(Procs, ProcId, ProcDefn) },
|
|
{ proc_info_argmodes(ProcDefn, ArgModes) },
|
|
{ proc_info_context(ProcDefn, Context) },
|
|
find_undef_mode_list(ArgModes, pred(PredId) - Context, ModeDefns,
|
|
InstDefns),
|
|
find_undef_proc_modes(ProcIds, PredId, Procs, ModeDefns, InstDefns).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Find any undefined insts/modes used in the bodies of other mode
|
|
% declarations.
|
|
|
|
:- pred find_undef_mode_bodies(list(mode_id), mode_table, user_inst_table,
|
|
io__state, io__state).
|
|
:- mode find_undef_mode_bodies(in, in, in, di, uo) is det.
|
|
|
|
find_undef_mode_bodies([], _, _) --> [].
|
|
find_undef_mode_bodies([ModeId | ModeIds], ModeDefns, InstDefns) -->
|
|
{ map__lookup(ModeDefns, ModeId, HLDS_ModeDefn) },
|
|
% XXX abstract hlds__mode_defn/5
|
|
{ HLDS_ModeDefn = hlds__mode_defn(_, _, Mode, _, Context) },
|
|
find_undef_mode_body(Mode, mode(ModeId) - Context, ModeDefns,
|
|
InstDefns),
|
|
find_undef_mode_bodies(ModeIds, ModeDefns, InstDefns).
|
|
|
|
% Find any undefined insts/modes used in the given mode definition.
|
|
|
|
:- pred find_undef_mode_body(hlds__mode_body, mode_error_context,
|
|
mode_table, user_inst_table, io__state, io__state).
|
|
:- mode find_undef_mode_body(in, in, in, in, di, uo) is det.
|
|
|
|
find_undef_mode_body(eqv_mode(Mode), ErrorContext, ModeDefns, InstDefns) -->
|
|
find_undef_mode(Mode, ErrorContext, ModeDefns, InstDefns).
|
|
|
|
% Find any undefined modes in a list of modes.
|
|
|
|
:- pred find_undef_mode_list(list(mode), mode_error_context,
|
|
mode_table, user_inst_table, io__state, io__state).
|
|
:- mode find_undef_mode_list(in, in, in, in, di, uo) is det.
|
|
|
|
find_undef_mode_list([], _, _, _) --> [].
|
|
find_undef_mode_list([Mode|Modes], ErrorContext, ModeDefns, InstDefns) -->
|
|
find_undef_mode(Mode, ErrorContext, ModeDefns, InstDefns),
|
|
find_undef_mode_list(Modes, ErrorContext, ModeDefns, InstDefns).
|
|
|
|
% Find any undefined modes/insts used in a mode.
|
|
% The mode itself may be undefined, and also
|
|
% any inst arguments may also be undefined.
|
|
% (eg. the mode `undef1(undef2, undef3)' should generate 3 errors.)
|
|
|
|
:- pred find_undef_mode(mode, mode_error_context, mode_table, user_inst_table,
|
|
io__state, io__state).
|
|
:- mode find_undef_mode(in, in, in, in, di, uo) is det.
|
|
|
|
find_undef_mode((InstA -> InstB), ErrorContext, ModeDefns, InstDefns) -->
|
|
find_undef_inst(InstA, ErrorContext, ModeDefns, InstDefns),
|
|
find_undef_inst(InstB, ErrorContext, ModeDefns, InstDefns).
|
|
find_undef_mode(user_defined_mode(Name, Args), ErrorContext, ModeDefns,
|
|
InstDefns) -->
|
|
%%% no builtin modes as yet
|
|
{ list__length(Args, Arity) },
|
|
{ ModeId = Name - Arity },
|
|
(
|
|
{ map__contains(ModeDefns, ModeId) }
|
|
->
|
|
[]
|
|
;
|
|
report_undef_mode(ModeId, ErrorContext)
|
|
),
|
|
find_undef_inst_list(Args, ErrorContext, ModeDefns, InstDefns).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Find any undefined insts used in the bodies of other inst
|
|
% declarations.
|
|
|
|
:- pred find_undef_inst_bodies(list(inst_id), mode_table, user_inst_table,
|
|
io__state, io__state).
|
|
:- mode find_undef_inst_bodies(in, in, in, di, uo) is det.
|
|
|
|
find_undef_inst_bodies([], _, _) --> [].
|
|
find_undef_inst_bodies([InstId | InstIds], ModeDefns, InstDefns) -->
|
|
{ map__lookup(InstDefns, InstId, HLDS_InstDefn) },
|
|
% XXX abstract hlds__inst_defn/5
|
|
{ HLDS_InstDefn = hlds__inst_defn(_, _, Inst, _, Context) },
|
|
find_undef_inst_body(Inst, inst(InstId) - Context,
|
|
ModeDefns, InstDefns),
|
|
find_undef_inst_bodies(InstIds, ModeDefns, InstDefns).
|
|
|
|
% Find any undefined insts used in the given inst definition.
|
|
|
|
:- pred find_undef_inst_body(hlds__inst_body, mode_error_context,
|
|
mode_table, user_inst_table,
|
|
io__state, io__state).
|
|
:- mode find_undef_inst_body(in, in, in, in, di, uo) is det.
|
|
|
|
find_undef_inst_body(eqv_inst(Inst), ErrorContext, ModeDefns, InstDefns) -->
|
|
find_undef_inst(Inst, ErrorContext, ModeDefns, InstDefns).
|
|
find_undef_inst_body(abstract_inst, _, _, _) --> [].
|
|
|
|
% Find any undefined insts in a list of insts.
|
|
|
|
:- pred find_undef_inst_list(list(inst), mode_error_context,
|
|
mode_table, user_inst_table,
|
|
io__state, io__state).
|
|
:- mode find_undef_inst_list(in, in, in, in, di, uo) is det.
|
|
|
|
find_undef_inst_list([], _ErrorContext, _ModeDefns, _InstDefns) --> [].
|
|
find_undef_inst_list([Inst|Insts], ErrorContext, ModeDefns, InstDefns) -->
|
|
find_undef_inst(Inst, ErrorContext, ModeDefns, InstDefns),
|
|
find_undef_inst_list(Insts, ErrorContext, ModeDefns, InstDefns).
|
|
|
|
% Find any undefined insts used in an inst.
|
|
% The inst itself may be undefined, and also
|
|
% any inst arguments may also be undefined.
|
|
% (eg. the inst `undef1(undef2, undef3)' should generate 3 errors.)
|
|
|
|
:- pred find_undef_inst(inst, mode_error_context, mode_table, user_inst_table,
|
|
io__state, io__state).
|
|
:- mode find_undef_inst(in, in, in, in, di, uo) is det.
|
|
|
|
find_undef_inst(any(_), _, _, _) --> [].
|
|
find_undef_inst(free, _, _, _) --> [].
|
|
find_undef_inst(ground(_, MaybePredInfo), ErrorContext, ModeDefns, InstDefns)
|
|
-->
|
|
( { MaybePredInfo = yes(pred_inst_info(Modes, _Det)) } ->
|
|
find_undef_mode_list(Modes, ErrorContext, ModeDefns, InstDefns)
|
|
;
|
|
[]
|
|
).
|
|
find_undef_inst(inst_var(_), _, _, _) --> [].
|
|
find_undef_inst(bound(_Uniq, BoundInsts), ErrorContext, ModeDefns, InstDefns)
|
|
-->
|
|
find_undef_bound_insts(BoundInsts, ErrorContext, ModeDefns, InstDefns).
|
|
find_undef_inst(defined_inst(InstName), ErrorContext, ModeDefns, InstDefns) -->
|
|
find_undef_inst_name(InstName, ErrorContext, ModeDefns, InstDefns).
|
|
find_undef_inst(abstract_inst(Name, Args), ErrorContext, ModeDefns, InstDefns)
|
|
-->
|
|
find_undef_inst_name(user_inst(Name, Args), ErrorContext, ModeDefns,
|
|
InstDefns).
|
|
find_undef_inst(not_reached, _, _, _) --> [].
|
|
find_undef_inst(free(_), _, _, _) -->
|
|
{ error("compiler generated inst unexpected") }.
|
|
|
|
:- pred find_undef_inst_name(inst_name, mode_error_context,
|
|
mode_table, user_inst_table,
|
|
io__state, io__state).
|
|
:- mode find_undef_inst_name(in, in, in, in, di, uo) is det.
|
|
|
|
find_undef_inst_name(user_inst(Name, Args), ErrorContext, ModeDefns, InstDefns)
|
|
-->
|
|
{ list__length(Args, Arity) },
|
|
{ InstId = Name - Arity },
|
|
(
|
|
{ map__contains(InstDefns, InstId) }
|
|
->
|
|
[]
|
|
;
|
|
report_undef_inst(InstId, ErrorContext)
|
|
),
|
|
find_undef_inst_list(Args, ErrorContext, ModeDefns, InstDefns).
|
|
find_undef_inst_name(unify_inst(_, _, _, _), _, _, _) -->
|
|
{ error("compiler generated inst unexpected") }.
|
|
find_undef_inst_name(merge_inst(_, _), _, _, _) -->
|
|
{ error("compiler generated inst unexpected") }.
|
|
find_undef_inst_name(ground_inst(_, _, _, _), _, _, _) -->
|
|
{ error("compiler generated inst unexpected") }.
|
|
find_undef_inst_name(typed_ground(_, _), _, _, _) -->
|
|
{ error("compiler generated inst unexpected") }.
|
|
find_undef_inst_name(shared_inst(_), _, _, _) -->
|
|
{ error("compiler generated inst unexpected") }.
|
|
find_undef_inst_name(mostly_uniq_inst(_), _, _, _) -->
|
|
{ error("compiler generated inst unexpected") }.
|
|
find_undef_inst_name(typed_inst(_,_), _, _, _) -->
|
|
{ error("compiler generated inst unexpected") }.
|
|
|
|
:- pred find_undef_bound_insts(list(bound_inst), mode_error_context,
|
|
mode_table, user_inst_table,
|
|
io__state, io__state).
|
|
:- mode find_undef_bound_insts(in, in, in, in, di, uo) is det.
|
|
|
|
find_undef_bound_insts([], _, _, _) --> [].
|
|
find_undef_bound_insts([functor(_Name, Args) | BoundInsts], ErrorContext,
|
|
ModeDefns, InstDefns) -->
|
|
find_undef_inst_list(Args, ErrorContext, ModeDefns, InstDefns),
|
|
find_undef_bound_insts(BoundInsts, ErrorContext, ModeDefns, InstDefns).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- type mode_error_context == pair(mode_error_context_2, term__context).
|
|
:- type mode_error_context_2 ---> inst(inst_id)
|
|
; mode(mode_id)
|
|
; pred(pred_id).
|
|
|
|
% Output an error message about an undefined mode
|
|
% in the specified context.
|
|
|
|
:- pred report_undef_mode(mode_id, mode_error_context, io__state, io__state).
|
|
:- mode report_undef_mode(in, in, di, uo) is det.
|
|
report_undef_mode(ModeId, ErrorContext - Context) -->
|
|
io__set_exit_status(1),
|
|
prog_out__write_context(Context),
|
|
io__write_string("In "),
|
|
write_mode_error_context(ErrorContext),
|
|
io__write_string(":\n"),
|
|
prog_out__write_context(Context),
|
|
io__write_string(" error: undefined mode "),
|
|
write_mode_id(ModeId),
|
|
io__write_string(".\n").
|
|
|
|
% Output an error message about an undefined inst
|
|
% in the specified context.
|
|
|
|
:- pred report_undef_inst(inst_id, mode_error_context, io__state, io__state).
|
|
:- mode report_undef_inst(in, in, di, uo) is det.
|
|
|
|
report_undef_inst(InstId, ErrorContext - Context) -->
|
|
io__set_exit_status(1),
|
|
prog_out__write_context(Context),
|
|
io__write_string("In "),
|
|
write_mode_error_context(ErrorContext),
|
|
io__write_string(":\n"),
|
|
prog_out__write_context(Context),
|
|
io__write_string(" error: undefined inst "),
|
|
write_inst_id(InstId),
|
|
io__write_string(".\n").
|
|
|
|
% Output a description of the context where an undefined mode was
|
|
% used.
|
|
|
|
:- pred write_mode_error_context(mode_error_context_2, io__state, io__state).
|
|
:- mode write_mode_error_context(in, di, uo) is det.
|
|
|
|
write_mode_error_context(pred(_PredId)) -->
|
|
io__write_string("mode declaration for predicate").
|
|
% XXX hlds_out__write_pred_id(PredId).
|
|
write_mode_error_context(mode(ModeId)) -->
|
|
io__write_string("definition of mode "),
|
|
write_mode_id(ModeId).
|
|
write_mode_error_context(inst(InstId)) -->
|
|
io__write_string("definition of inst "),
|
|
write_inst_id(InstId).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Predicates to output inst_ids and mode_ids.
|
|
% XXX inst_ids and mode_ids should include the module.
|
|
|
|
:- pred write_mode_id(mode_id, io__state, io__state).
|
|
:- mode write_mode_id(in, di, uo) is det.
|
|
|
|
write_mode_id(F - N) -->
|
|
prog_out__write_sym_name(F),
|
|
io__write_string("/"),
|
|
io__write_int(N).
|
|
|
|
% XXX inst_ids should include the module.
|
|
|
|
:- pred write_inst_id(inst_id, io__state, io__state).
|
|
:- mode write_inst_id(in, di, uo) is det.
|
|
|
|
write_inst_id(F - N) -->
|
|
prog_out__write_sym_name(F),
|
|
io__write_string("/"),
|
|
io__write_int(N).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|