mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-17 23:05:21 +00:00
Sometimes, one wants to keep some predicates around even if they are not
currently being used. Adding this pragma for such a predicate will shut up
dead procedure/predicate warnings both for the named predicate and for the
other predicates it calls, both directly and indirectly.
With two of these pragmas added to compiler/stratify.m, the number of
predicates being reported as dead goes from 25 to 0.
compiler/prog_item.m:
Define the new pragma.
compiler/prog_io_pragma.m:
Parse the new pragma.
compiler/parse_tree_out_pragma.m:
Write out the new pragma, if needed.
compiler/add_pragma.m:
Add the new pragma to the HLDS in the form of a marker on the named
predicate.
compiler/hlds_pred.m:
Define that marker.
compiler/dead_proc_elim.m:
If a predicate has that marker, consider all its procedures to be live.
compiler/comp_unit_interface.m:
compiler/equiv_type.m:
compiler/get_dependencies.m:
compiler/hlds_out_pred.m:
compiler/intermod.m:
compiler/item_util.m:
compiler/make_hlds_separate_items.m:
compiler/module_qual.qual_errors.m:
compiler/module_qual.qualify_items.m:
compiler/prog_item_stats.m:
compiler/recompilation.version.m:
compiler/table_gen.m:
compiler/write_module_interface_files.m:
Conform to the changes above.
tests/invalid/bad_consider_used.{m,err_exp}:
New test case to test the handling of invalid consider_used pragmas.
tests/invalid/Mmakefile:
Add the new test case.
294 lines
11 KiB
Mathematica
294 lines
11 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2014 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.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% File: item_util.m.
|
|
%
|
|
% This module contains utility predicates for dealing with items.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module parse_tree.item_util.
|
|
:- interface.
|
|
|
|
:- import_module libs.globals.
|
|
:- import_module parse_tree.prog_item.
|
|
|
|
:- import_module bool.
|
|
:- import_module list.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% This is effectively a subtype of int_file_kind, which is defined in
|
|
% prog_item.m.
|
|
:- type short_int_file_kind
|
|
---> sifk_int2 % the qualified short interface, for the .int2 file
|
|
; sifk_int3. % the unqualified short interface, for the .int3 file
|
|
|
|
% XXX make_abstract_defn should be merged with make_abstract_unify_compare
|
|
% and made det, returning the unchanged item if it does not need to be made
|
|
% abstract (so we can use det switches instead semidet tests in the code).
|
|
%
|
|
:- pred maybe_make_abstract_type_defn(short_int_file_kind::in,
|
|
item_type_defn_info::in, item_type_defn_info::out) is det.
|
|
|
|
:- pred make_abstract_typeclass(item_typeclass_info::in,
|
|
item_typeclass_info::out) is det.
|
|
|
|
:- pred maybe_make_abstract_instance(short_int_file_kind::in,
|
|
item_instance_info::in, item_instance_info::out) is det.
|
|
|
|
% All instance declarations must be written to `.int' files as
|
|
% abstract instance declarations, because the method names have not yet
|
|
% been module qualified. This could cause the wrong predicate to be
|
|
% used if calls to the method are specialized.
|
|
%
|
|
:- func make_instance_abstract(item_instance_info) = item_instance_info.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Could this item use items from imported modules.
|
|
%
|
|
:- func item_needs_imports(item) = bool.
|
|
|
|
:- func item_needs_foreign_imports(item) = list(foreign_language).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.prog_foreign.
|
|
:- import_module parse_tree.prog_type.
|
|
|
|
:- import_module maybe.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
maybe_make_abstract_type_defn(ShortIntFileKind,
|
|
ItemTypeDefn, MaybeAbstractItemTypeDefn) :-
|
|
TypeDefn = ItemTypeDefn ^ td_ctor_defn,
|
|
(
|
|
TypeDefn = parse_tree_du_type(Ctors, MaybeUserEqComp,
|
|
MaybeDirectArgCtors),
|
|
% For the `.int2' files, we need the full definitions of
|
|
% discriminated union types. Even if the functors for a type
|
|
% are not used within a module, we may need to know them for
|
|
% comparing insts, e.g. for comparing `ground' and `bound(...)'.
|
|
(
|
|
ShortIntFileKind = sifk_int2,
|
|
(
|
|
MaybeUserEqComp = no,
|
|
MaybeAbstractItemTypeDefn = ItemTypeDefn
|
|
;
|
|
MaybeUserEqComp = yes(_UserEqComp),
|
|
AbstractTypeDefn = parse_tree_du_type(Ctors,
|
|
yes(abstract_noncanonical_type(non_solver_type)),
|
|
MaybeDirectArgCtors),
|
|
MaybeAbstractItemTypeDefn = ItemTypeDefn ^ td_ctor_defn :=
|
|
AbstractTypeDefn
|
|
)
|
|
;
|
|
ShortIntFileKind = sifk_int3,
|
|
( if du_type_is_enum(Ctors, NumBits) then
|
|
AbstractDetails = abstract_enum_type(NumBits)
|
|
else
|
|
AbstractDetails = abstract_type_general
|
|
),
|
|
MaybeAbstractItemTypeDefn = ItemTypeDefn ^ td_ctor_defn
|
|
:= parse_tree_abstract_type(AbstractDetails)
|
|
)
|
|
;
|
|
TypeDefn = parse_tree_abstract_type(AbstractDetails),
|
|
MaybeAbstractItemTypeDefn = ItemTypeDefn ^ td_ctor_defn
|
|
:= parse_tree_abstract_type(AbstractDetails)
|
|
;
|
|
TypeDefn = parse_tree_solver_type(_, _),
|
|
% rafe: XXX we need to also export the details of the
|
|
% forwarding type for the representation and the forwarding
|
|
% pred for initialization.
|
|
AbstractDetails = abstract_solver_type,
|
|
MaybeAbstractItemTypeDefn = ItemTypeDefn ^ td_ctor_defn
|
|
:= parse_tree_abstract_type(AbstractDetails)
|
|
;
|
|
TypeDefn = parse_tree_eqv_type(_),
|
|
% For the `.int2' files, we need the full definitions of
|
|
% equivalence types. They are needed to ensure that
|
|
% non-abstract equivalence types always get fully expanded
|
|
% before code generation, even in modules that only indirectly
|
|
% import the definition of the equivalence type.
|
|
% But the full definitions are not needed for the `.int3'
|
|
% files. So we convert equivalence types into abstract types
|
|
% only for the `.int3' files.
|
|
(
|
|
ShortIntFileKind = sifk_int2,
|
|
MaybeAbstractItemTypeDefn = ItemTypeDefn
|
|
;
|
|
ShortIntFileKind = sifk_int3,
|
|
% XXX is this right for solver types?
|
|
AbstractDetails = abstract_type_general,
|
|
MaybeAbstractItemTypeDefn = ItemTypeDefn ^ td_ctor_defn
|
|
:= parse_tree_abstract_type(AbstractDetails)
|
|
)
|
|
;
|
|
TypeDefn = parse_tree_foreign_type(ForeignType, MaybeUserEqComp,
|
|
Assertions),
|
|
% We always need the definitions of foreign types
|
|
% to handle inter-language interfacing correctly.
|
|
% However, we want to abstract away any unify and compare predicates.
|
|
(
|
|
MaybeUserEqComp = no,
|
|
MaybeAbstractItemTypeDefn = ItemTypeDefn
|
|
;
|
|
MaybeUserEqComp = yes(_UserEqComp),
|
|
AbstractTypeDefn = parse_tree_foreign_type(ForeignType,
|
|
yes(abstract_noncanonical_type(non_solver_type)), Assertions),
|
|
MaybeAbstractItemTypeDefn = ItemTypeDefn ^ td_ctor_defn :=
|
|
AbstractTypeDefn
|
|
)
|
|
).
|
|
|
|
make_abstract_typeclass(ItemTypeClass, AbstractItemTypeClass) :-
|
|
AbstractItemTypeClass = ItemTypeClass ^ tc_class_methods
|
|
:= class_interface_abstract.
|
|
|
|
maybe_make_abstract_instance(ShortIntFileKind,
|
|
ItemInstance, MaybeAbstractItemInstance) :-
|
|
(
|
|
ShortIntFileKind = sifk_int2,
|
|
MaybeAbstractItemInstance = make_instance_abstract(ItemInstance)
|
|
;
|
|
ShortIntFileKind = sifk_int3,
|
|
MaybeAbstractItemInstance = ItemInstance
|
|
).
|
|
|
|
make_instance_abstract(ItemInstance0) = ItemInstance :-
|
|
ItemInstance = ItemInstance0 ^ ci_method_instances
|
|
:= instance_body_abstract.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
item_needs_imports(Item) = NeedsImports :-
|
|
(
|
|
Item = item_type_defn(ItemTypeDefn),
|
|
( if ItemTypeDefn ^ td_ctor_defn = parse_tree_abstract_type(_) then
|
|
NeedsImports = no
|
|
else
|
|
NeedsImports = yes
|
|
)
|
|
;
|
|
( Item = item_clause(_)
|
|
; Item = item_inst_defn(_)
|
|
; Item = item_mode_defn(_)
|
|
; Item = item_pragma(_)
|
|
; Item = item_pred_decl(_)
|
|
; Item = item_mode_decl(_)
|
|
; Item = item_typeclass(_)
|
|
; Item = item_instance(_)
|
|
; Item = item_promise(_)
|
|
; Item = item_initialise(_)
|
|
; Item = item_finalise(_)
|
|
; Item = item_mutable(_)
|
|
),
|
|
NeedsImports = yes
|
|
;
|
|
Item = item_nothing(_),
|
|
NeedsImports = no
|
|
).
|
|
|
|
item_needs_foreign_imports(Item) = Langs :-
|
|
(
|
|
Item = item_mutable(_ItemMutable),
|
|
% We can use all foreign languages.
|
|
Langs = all_foreign_languages
|
|
;
|
|
Item = item_type_defn(ItemTypeDefn),
|
|
( if
|
|
ItemTypeDefn ^ td_ctor_defn =
|
|
parse_tree_foreign_type(ForeignType, _, _)
|
|
then
|
|
Langs = [foreign_type_language(ForeignType)]
|
|
else
|
|
Langs = []
|
|
)
|
|
;
|
|
Item = item_pragma(ItemPragma),
|
|
ItemPragma = item_pragma_info(Pragma, _, _, _),
|
|
(
|
|
(
|
|
Pragma = pragma_foreign_decl(FDInfo),
|
|
FDInfo = pragma_info_foreign_decl(Lang, _, _)
|
|
;
|
|
Pragma = pragma_foreign_code(FCInfo),
|
|
FCInfo = pragma_info_foreign_code(Lang, _)
|
|
;
|
|
Pragma = pragma_foreign_enum(FEInfo),
|
|
FEInfo = pragma_info_foreign_enum(Lang, _, _)
|
|
;
|
|
Pragma = pragma_foreign_proc_export(FPEInfo),
|
|
FPEInfo = pragma_info_foreign_proc_export(Lang, _, _)
|
|
),
|
|
Langs = [Lang]
|
|
;
|
|
Pragma = pragma_foreign_proc(FPInfo),
|
|
FPInfo = pragma_info_foreign_proc(Attrs, _, _, _, _, _, _),
|
|
Langs = [get_foreign_language(Attrs)]
|
|
;
|
|
( Pragma = pragma_foreign_import_module(_)
|
|
; Pragma = pragma_foreign_export_enum(_)
|
|
; Pragma = pragma_external_proc(_)
|
|
; Pragma = pragma_type_spec(_)
|
|
; Pragma = pragma_inline(_)
|
|
; Pragma = pragma_no_inline(_)
|
|
; Pragma = pragma_consider_used(_)
|
|
; Pragma = pragma_unused_args(_)
|
|
; Pragma = pragma_exceptions(_)
|
|
; Pragma = pragma_trailing_info(_)
|
|
; Pragma = pragma_mm_tabling_info(_)
|
|
; Pragma = pragma_obsolete(_)
|
|
; Pragma = pragma_no_detism_warning(_)
|
|
; Pragma = pragma_require_tail_recursion(_)
|
|
; Pragma = pragma_oisu(_)
|
|
; Pragma = pragma_tabled(_)
|
|
; Pragma = pragma_fact_table(_)
|
|
; Pragma = pragma_reserve_tag(_)
|
|
; Pragma = pragma_promise_eqv_clauses(_)
|
|
; Pragma = pragma_promise_pure(_)
|
|
; Pragma = pragma_promise_semipure(_)
|
|
; Pragma = pragma_termination_info(_)
|
|
; Pragma = pragma_termination2_info(_)
|
|
; Pragma = pragma_terminates(_)
|
|
; Pragma = pragma_does_not_terminate(_)
|
|
; Pragma = pragma_check_termination(_)
|
|
; Pragma = pragma_mode_check_clauses(_)
|
|
; Pragma = pragma_structure_sharing(_)
|
|
; Pragma = pragma_structure_reuse(_)
|
|
; Pragma = pragma_require_feature_set(_)
|
|
),
|
|
Langs = []
|
|
)
|
|
;
|
|
( Item = item_clause(_)
|
|
; Item = item_inst_defn(_)
|
|
; Item = item_mode_defn(_)
|
|
; Item = item_pred_decl(_)
|
|
; Item = item_mode_decl(_)
|
|
; Item = item_typeclass(_)
|
|
; Item = item_instance(_)
|
|
; Item = item_promise(_)
|
|
; Item = item_initialise(_)
|
|
; Item = item_finalise(_)
|
|
; Item = item_nothing(_)
|
|
),
|
|
Langs = []
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module parse_tree.item_util.
|
|
%-----------------------------------------------------------------------------%
|