Files
mercury/compiler/make.deps_set.m
Zoltan Somogyi ec20b1ed0a Make sparse_bitset.m operate on uints.
NEWS:
    Mention all the user-visible changes below.

library/enum.m:
    Add the typeclass uenum, which is a version of the existing enum typeclass
    that maps items to uints, not ints. It also uses a semidet predicate,
    not a semidet function, to get back to the item from the uint.

library/sparse_bitset.m:
library/fat_sparse_bitset.m:
    Make these modules operate on uints, which means requiring the items
    in the sets to be instances of uenum, not enum.

    If a few places, improve loops by doing previously-repeated conversions
    of [u]ints into <offset, bit-to-set> pairs just once.

library/counter.m:
    Define ucounters, which allocate uints. Improve documentation.

library/digraph.m:
    Change digraph_keys from ints to uints, since we put them into
    sparse_bitsets.

library/int.m:
    Make int an instance of the uenum typeclass. This can help users
    who currently put ints into sparse_bitsets.

library/pprint.m:
    Prettyprint sparse_bitsets as lists of uints.

library/term.m:
    Make vars instances of uenum as well as enum.

library/uint.m:
    Make uint an instance of the uenum typeclass.

    Add the ubits_per_uint function, which allows some casts to be avoided.

compiler/make.deps_set.m:
    Change the indexes we put into sparse_bitsets from ints to uints.

compiler/make.make_info.m:
    Change the source of those indexes from ints to uints.

compiler/make.top_level.m:
compiler/make.util.m:
    Conform to the changes above.

compiler/pre_quantification.m:
    Change zones from ints to uints, since we put them into sparse_bitsets.

tests/hard_coded/int_uenum.{m,exp}:
tests/hard_coded/Mmakefile:
    Enable the new test case.

tests/valid/use_import_only_for_instance.m:
    Update this extract from library/digraph.m the same way as
    library/digraph.m itself.
2022-12-05 09:45:11 +11:00

272 lines
9.5 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 2002-2011 The University of Melbourne.
% Copyright (C) 2020-2022 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: make.deps_set.m.
%
% Dependency computation does a lot of unions so we use a set representation
% suited to that purpose, namely bitsets. We can't store module_names and
% dependency_files in those sets, so we keep two maps
%
% module_name <-> module_index, and
% dependency_file <-> dependency_file_index
%
% in the make_info structure, and work with sets of indices instead.
%
%---------------------------------------------------------------------------%
:- module make.deps_set.
:- interface.
:- import_module make.dependencies.
:- import_module make.make_info.
:- import_module mdbcomp.
:- import_module mdbcomp.sym_name.
:- import_module enum.
:- import_module list.
:- import_module set.
:- import_module sparse_bitset.
%---------------------------------------------------------------------------%
% sparse_bitset is faster than tree_bitset by my tests.
%
:- type deps_set(T) == sparse_bitset(T).
% :- type deps_set(T) == tree_bitset(T).
:- type module_index.
:- instance uenum(module_index).
:- type dependency_file_index.
:- instance uenum(dependency_file_index).
%---------------------------------------------------------------------------%
% Convert a module_name to a module_index.
%
:- pred module_name_to_index(module_name::in, module_index::out,
make_info::in, make_info::out) is det.
% Convert a list of module_names to a module_index set.
%
:- pred module_names_to_index_set(list(module_name)::in,
deps_set(module_index)::out,
make_info::in, make_info::out) is det.
% Convert a module_index to a module_name.
%
:- pred module_index_to_name(make_info::in,
module_index::in, module_name::out) is det.
% Convert a module_index set to a module_name set.
%
:- pred module_index_set_to_plain_set(make_info::in,
deps_set(module_index)::in, set(module_name)::out) is det.
%---------------------------------------------------------------------------%
% Convert a dependency file to a dependency_file_index.
%
:- pred dependency_file_to_index(dependency_file_with_module_index::in,
dependency_file_index::out, make_info::in, make_info::out) is det.
% Convert a list of dependency files to a dependency_file_index set.
%
:- pred dependency_files_to_index_set(list(dependency_file)::in,
deps_set(dependency_file_index)::out, make_info::in, make_info::out)
is det.
% Convert a dependency_file_index set to a dependency_file set.
%
:- pred dependency_file_index_set_to_plain_set(make_info::in,
deps_set(dependency_file_index)::in, set(dependency_file)::out) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module libs.
:- import_module parse_tree.
:- import_module int.
:- import_module maybe.
:- import_module uint.
:- import_module version_array.
:- import_module version_hash_table.
%---------------------------------------------------------------------------%
%
% Bitset indices.
%
:- type module_index
---> module_index(uint).
:- instance uenum(module_index) where [
to_uint(module_index(U)) = U,
from_uint(U, module_index(U))
].
:- type dependency_file_index
---> dependency_file_index(uint).
:- instance uenum(dependency_file_index) where [
to_uint(dependency_file_index(U)) = U,
from_uint(U, dependency_file_index(U))
].
%---------------------------------------------------------------------------%
module_name_to_index(ModuleName, Index, !Info) :-
Map0 = !.Info ^ mki_module_index_map,
Map0 = module_index_map(Forward0, _Reverse0, _Size0),
( if version_hash_table.search(Forward0, ModuleName, Index0) then
Index = Index0
else
Map0 = module_index_map(_Forward0, Reverse0, USize0),
Slot = USize0,
Index = module_index(USize0),
USize = USize0 + 1u,
version_hash_table.det_insert(ModuleName, Index, Forward0, Forward),
TrueSize = version_array.size(Reverse0),
( if cast_to_int(USize) > TrueSize then
NewSize = increase_array_size(TrueSize),
version_array.resize(NewSize, ModuleName, Reverse0, Reverse)
else
version_array.set(cast_to_int(Slot), ModuleName, Reverse0, Reverse)
),
Map = module_index_map(Forward, Reverse, USize),
!Info ^ mki_module_index_map := Map
).
:- func increase_array_size(int) = int.
increase_array_size(N) = (if N = 0 then 1 else N * 2).
%---------------------%
module_names_to_index_set(ModuleNames, IndexSet, !Info) :-
module_names_to_index_set_2(ModuleNames,
sparse_bitset.init, IndexSet, !Info).
:- pred module_names_to_index_set_2(list(module_name)::in,
deps_set(module_index)::in, deps_set(module_index)::out,
make_info::in, make_info::out) is det.
module_names_to_index_set_2([], !IndexSet, !Info).
module_names_to_index_set_2([ModuleName | ModuleNames], !Set, !Info) :-
module_name_to_index(ModuleName, ModuleIndex, !Info),
sparse_bitset.insert(ModuleIndex, !Set),
module_names_to_index_set_2(ModuleNames, !Set, !Info).
%---------------------------------------------------------------------------%
module_index_to_name(Info, Index, ModuleName) :-
Info ^ mki_module_index_map = module_index_map(_Forward, Reverse, _Size),
Index = module_index(I),
ModuleName = version_array.lookup(Reverse, cast_to_int(I)).
%---------------------%
module_index_set_to_plain_set(Info, ModuleIndices, Modules) :-
foldl(module_index_set_to_plain_set_2(Info), ModuleIndices,
set.init, Modules).
:- pred module_index_set_to_plain_set_2(make_info::in, module_index::in,
set(module_name)::in, set(module_name)::out) is det.
module_index_set_to_plain_set_2(Info, ModuleIndex, !Set) :-
module_index_to_name(Info, ModuleIndex, ModuleName),
set.insert(ModuleName, !Set).
%---------------------------------------------------------------------------%
dependency_file_to_index(DepFile, Index, !Info) :-
Map0 = !.Info ^ mki_dep_file_index_map,
ForwardMap0 = Map0 ^ dfim_forward_map,
( if version_hash_table.search(ForwardMap0, DepFile, Index0) then
Index = Index0
else
Map0 = dependency_file_index_map(Forward0, Reverse0, USize0),
Slot = USize0,
Index = dependency_file_index(USize0),
USize = USize0 + 1u,
version_hash_table.det_insert(DepFile, Index, Forward0, Forward),
TrueSize = version_array.size(Reverse0),
( if cast_to_int(USize) > TrueSize then
NewSize = increase_array_size(TrueSize),
version_array.resize(NewSize, DepFile, Reverse0, Reverse)
else
version_array.set(cast_to_int(Slot), DepFile, Reverse0, Reverse)
),
Map = dependency_file_index_map(Forward, Reverse, USize),
!Info ^ mki_dep_file_index_map := Map
).
%---------------------%
dependency_files_to_index_set(DepFiles, DepIndexSet, !Info) :-
list.foldl2(dependency_files_to_index_set_2, DepFiles,
init, DepIndexSet, !Info).
:- pred dependency_files_to_index_set_2(dependency_file::in,
deps_set(dependency_file_index)::in, deps_set(dependency_file_index)::out,
make_info::in, make_info::out) is det.
dependency_files_to_index_set_2(DepFile0, !Set, !Info) :-
(
DepFile0 = dep_target(target_file(ModuleName, TargetType)),
module_name_to_index(ModuleName, ModuleIndex, !Info),
DepFile = dfmi_target(ModuleIndex, TargetType)
;
DepFile0 = dep_file(FileName),
DepFile = dfmi_file(FileName)
),
dependency_file_to_index(DepFile, DepIndex, !Info),
insert(DepIndex, !Set).
%---------------------------------------------------------------------------%
:- pred index_to_dependency_file(make_info::in, dependency_file_index::in,
dependency_file::out) is det.
index_to_dependency_file(Info, Index, DepFile) :-
Info ^ mki_dep_file_index_map =
dependency_file_index_map(_Forward, Reverse, _Size),
Index = dependency_file_index(I),
version_array.lookup(Reverse, cast_to_int(I), DepFile0),
(
DepFile0 = dfmi_target(ModuleIndex, FileType),
module_index_to_name(Info, ModuleIndex, ModuleName),
DepFile = dep_target(target_file(ModuleName, FileType))
;
DepFile0 = dfmi_file(FileName),
DepFile = dep_file(FileName)
).
%---------------------%
dependency_file_index_set_to_plain_set(Info, DepIndices, DepFiles) :-
foldl(dependency_file_index_set_to_plain_set_2(Info), DepIndices,
[], DepFilesList),
DepFiles = set.list_to_set(DepFilesList).
:- pred dependency_file_index_set_to_plain_set_2(make_info::in,
dependency_file_index::in,
list(dependency_file)::in, list(dependency_file)::out) is det.
dependency_file_index_set_to_plain_set_2(Info, DepIndex, List0, List) :-
index_to_dependency_file(Info, DepIndex, DepFile),
List = [DepFile | List0].
%---------------------------------------------------------------------------%
:- end_module make.deps_set.
%---------------------------------------------------------------------------%