[m-rev.] for review: analysis framework and libraries
Peter Wang
wangp at students.cs.mu.OZ.AU
Fri Feb 10 15:23:26 AEDT 2006
Estimated hours taken: 25
Branches: main
This patch mainly improves the handling of libraries with the intermodule
analysis framework. `.analysis' files can now be installed into library
directories and used when analysing local modules.
analysis/analysis.m:
analysis/analysis.file.m:
compiler/mmc_analysis.m:
Separate the `module_id_to_file_name' method of the `compiler'
typeclass into `module_id_to_read_file_name' and
`module_id_to_write_file_name'. Add `module_is_local' method.
Change the calls to `module_id_to_file_name' appropriately for the
context. This allows us to find the `.analysis' files of library
modules.
Only write results, IMDG and request files for local modules.
Force `.analysis' files of the currently-analysed module to be written
out, even if it would be empty. This avoids us trying to reanalyse the
module later.
compiler/options.m:
Add internal compiler option `--local-module-id'.
compiler/make.dependencies.m:
Add `make_local_module_id_options' to build a list of
`--local-module-id' options.
compiler/make.module_target.m:
Add predicate `make_module_target_extra_options' so we can pass the
`--local-module-id' options.
compiler/make.program_target.m:
Analyse modules in bottom up order, according to the module dependency
graph. The current analyses don't support non-default call patterns,
so this should reduce the number of analysis passes to get (close to)
to a fixpoint.
Pass `--local-module-id' options when building analysis files, so the
analysis framework knows which modules are local.
Install `.analysis' files when installing libraries.
compiler/modules.m:
Make `.analysis', `.analysis_date', `.imdg' and `.request' files
architecture- or grade-specified so they go into grade directories
when `--use-grade-subdirs' is used.
Search for `.analysis' files in the same directories as `.opt' and
`.trans_opt' files.
Export predicate `add_module_relations' to help build module dependency
graphs.
compiler/mercury_compile.m:
Fix a bug where the unused argument optimisation pass was always being
run if `--intermodule-analysis' was enabled.
Index: analysis/analysis.file.m
===================================================================
RCS file: /home/mercury1/repository/mercury/analysis/analysis.file.m,v
retrieving revision 1.4
diff -u -r1.4 analysis.file.m
--- analysis/analysis.file.m 6 Feb 2006 05:39:40 -0000 1.4
+++ analysis/analysis.file.m 10 Feb 2006 02:57:54 -0000
@@ -87,8 +87,20 @@
%-----------------------------------------------------------------------------%
read_module_overall_status(Compiler, ModuleId, MaybeModuleStatus, !IO) :-
- module_id_to_file_name(Compiler, ModuleId, analysis_registry_suffix,
- AnalysisFileName, !IO),
+ module_id_to_read_file_name(Compiler, ModuleId, analysis_registry_suffix,
+ MaybeAnalysisFileName, !IO),
+ (
+ MaybeAnalysisFileName = ok(AnalysisFileName),
+ read_module_overall_status_2(AnalysisFileName, MaybeModuleStatus, !IO)
+ ;
+ MaybeAnalysisFileName = error(_),
+ MaybeModuleStatus = no
+ ).
+
+:- pred read_module_overall_status_2(string::in, maybe(analysis_status)::out,
+ io::di, io::uo) is det.
+
+read_module_overall_status_2(AnalysisFileName, MaybeModuleStatus, !IO) :-
io__open_input(AnalysisFileName, OpenResult, !IO),
(
OpenResult = ok(Stream),
@@ -331,11 +343,18 @@
read_analysis_file(Compiler, ModuleId, Suffix,
ReadHeader, DefaultHeader, Header,
ParseEntry, ModuleResults0, ModuleResults, !IO) :-
- module_id_to_file_name(Compiler, ModuleId,
- Suffix, AnalysisFileName, !IO),
- read_analysis_file(AnalysisFileName,
- ReadHeader, DefaultHeader, Header,
- ParseEntry, ModuleResults0, ModuleResults, !IO).
+ module_id_to_read_file_name(Compiler, ModuleId,
+ Suffix, MaybeAnalysisFileName, !IO),
+ (
+ MaybeAnalysisFileName = ok(AnalysisFileName),
+ read_analysis_file(AnalysisFileName,
+ ReadHeader, DefaultHeader, Header,
+ ParseEntry, ModuleResults0, ModuleResults, !IO)
+ ;
+ MaybeAnalysisFileName = error(_),
+ Header = DefaultHeader,
+ ModuleResults = ModuleResults0
+ ).
:- pred read_analysis_file(string::in,
read_analysis_header(Header)::in(read_analysis_header),
@@ -443,7 +462,8 @@
analysis_status_to_string(Status, String).
write_module_analysis_requests(Info, ModuleId, ModuleRequests, !IO) :-
- module_id_to_file_name(Info ^ compiler, ModuleId, request_suffix,
+ Compiler = Info ^ compiler,
+ module_id_to_write_file_name(Compiler, ModuleId, request_suffix,
AnalysisFileName, !IO),
debug_msg((pred(!.IO::di, !:IO::uo) is det :-
io.print("Writing module analysis requests to ", !IO),
@@ -469,7 +489,7 @@
io__set_output_stream(AppendStream,
OldOutputStream, !IO),
write_analysis_entries(
- write_request_entry(Info ^ compiler),
+ write_request_entry(Compiler),
ModuleRequests, !IO),
io__set_output_stream(OldOutputStream, _, !IO),
io__close_output(AppendStream, !IO),
@@ -484,9 +504,8 @@
Appended = no
),
( Appended = no ->
- write_analysis_file(Info ^ compiler, ModuleId, request_suffix,
- nop,
- write_request_entry(Info ^ compiler),
+ write_analysis_file(AnalysisFileName,
+ nop, write_request_entry(Compiler),
ModuleRequests, !IO)
;
true
@@ -576,10 +595,19 @@
write_entry(T)::in(write_entry), module_analysis_map(T)::in,
io__state::di, io__state::uo) is det <= compiler(Compiler).
-write_analysis_file(Compiler, ModuleId, Suffix, WriteHeader,
- WriteEntry, ModuleResults, !IO) :-
- module_id_to_file_name(Compiler, ModuleId,
- Suffix, AnalysisFileName, !IO),
+write_analysis_file(Compiler, ModuleId, Suffix, WriteHeader, WriteEntry,
+ ModuleResults, !IO) :-
+ module_id_to_write_file_name(Compiler, ModuleId, Suffix,
+ AnalysisFileName, !IO),
+ write_analysis_file(AnalysisFileName, WriteHeader, WriteEntry,
+ ModuleResults, !IO).
+
+:- pred write_analysis_file(string::in, write_header::in(write_header),
+ write_entry(T)::in(write_entry), module_analysis_map(T)::in,
+ io__state::di, io__state::uo) is det.
+
+write_analysis_file(AnalysisFileName, WriteHeader, WriteEntry,
+ ModuleResults, !IO) :-
io__open_output(AnalysisFileName, OpenResult, !IO),
(
OpenResult = ok(Stream),
@@ -615,7 +643,7 @@
), ModuleResults, !IO).
empty_request_file(Info, ModuleId, !IO) :-
- module_id_to_file_name(Info ^ compiler, ModuleId, request_suffix,
+ module_id_to_write_file_name(Info ^ compiler, ModuleId, request_suffix,
RequestFileName, !IO),
debug_msg((pred(!.IO::di, !:IO::uo) is det :-
io.print("Removing request file ", !IO),
Index: analysis/analysis.m
===================================================================
RCS file: /home/mercury1/repository/mercury/analysis/analysis.m,v
retrieving revision 1.4
diff -u -r1.4 analysis.m
--- analysis/analysis.m 6 Feb 2006 05:39:40 -0000 1.4
+++ analysis/analysis.m 10 Feb 2006 03:15:02 -0000
@@ -36,9 +36,22 @@
% Describe the analyses which can be performed by a compiler.
func analyses(Compiler, analysis_name) = analysis_type is semidet,
- % module_id_to_file_name(Compiler, ModuleId, Ext, FileName)
- pred module_id_to_file_name(Compiler::in, module_id::in,
- string::in, string::out, io__state::di, io__state::uo) is det
+ % module_id_to_read_file_name(Compiler, ModuleId, Ext, FileName)
+ pred module_id_to_read_file_name(Compiler::in, module_id::in,
+ string::in, maybe_error(string)::out, io::di, io::uo) is det,
+
+ % module_id_to_write_file_name(Compiler, ModuleId, Ext, FileName)
+ pred module_id_to_write_file_name(Compiler::in, module_id::in,
+ string::in, string::out, io::di, io::uo) is det,
+
+ % module_is_local(Compiler, ModuleId, IsLocal, !IO)
+ %
+ % IsLocal is `yes' if the module is not a "library" module, i.e. we are
+ % able to reanalyse the module, not just use results that already
+ % exist.
+ %
+ pred module_is_local(Compiler::in, module_id::in, bool::out,
+ io::di, io::uo) is det
].
:- type module_id == string.
@@ -911,7 +924,10 @@
(if NewResults = !.Info ^ new_analysis_results ^ elem(ModuleId) then
ModuleStatus = lub_result_statuses(NewResults)
else
- ModuleStatus = optimal
+ ModuleStatus = optimal,
+ % Force an `.analysis' file to be written out for this module,
+ % even though there are no results recorded for it.
+ !:Info = !.Info ^ new_analysis_results ^ elem(ModuleId) := map.init
),
update_analysis_registry(!Info, !IO),
@@ -931,11 +947,11 @@
% Write the results for all the modules we know of. For the
% module being compiled, the analysis results may have changed.
% For other modules, their overall statuses may have changed.
- map.foldl(write_analysis_files_2(!.Info),
+ write_local_modules(!.Info, write_module_analysis_results,
!.Info ^ old_analysis_results, !IO),
% Write the requests for the imported modules.
- map.foldl(write_module_analysis_requests(!.Info),
+ write_local_modules(!.Info, write_module_analysis_requests,
!.Info ^ analysis_requests, !IO),
% Remove the requests for the current module since we (should have)
@@ -943,11 +959,12 @@
empty_request_file(!.Info, ModuleId, !IO),
% Write the intermodule dependency graphs.
- map.foldl(write_module_imdg(!.Info), !.Info ^ old_imdg, !IO),
+ write_local_modules(!.Info, write_module_imdg,
+ !.Info ^ old_imdg, !IO),
% Touch a timestamp file to indicate the last time that this module was
% analysed.
- module_id_to_file_name(Compiler, ModuleId, ".analysis_date",
+ module_id_to_write_file_name(Compiler, ModuleId, ".analysis_date",
TimestampFileName, !IO),
io.open_output(TimestampFileName, Result, !IO),
(
@@ -959,10 +976,38 @@
error(io.error_message(IOError))
).
-:- pred write_analysis_files_2(analysis_info::in, module_id::in,
+:- type write_module_analysis_map(T) ==
+ (pred(analysis_info, module_id, module_analysis_map(T), io, io)).
+:- mode write_module_analysis_map == in(pred(in, in, in, di, uo) is det).
+
+:- pred write_local_modules(analysis_info::in,
+ write_module_analysis_map(T)::write_module_analysis_map,
+ analysis_map(T)::in, io::di, io::uo) is det.
+:- pred write_local_modules_2(analysis_info::in,
+ write_module_analysis_map(T)::write_module_analysis_map,
+ module_id::in, module_analysis_map(T)::in, io::di, io::uo) is det.
+
+write_local_modules(Info, Write, AnalysisMap, !IO) :-
+ map.foldl(write_local_modules_2(Info, Write), AnalysisMap, !IO).
+
+write_local_modules_2(Info, Write, ModuleId, ModuleResults, !IO) :-
+ module_is_local(Info ^ compiler, ModuleId, IsLocal, !IO),
+ (
+ IsLocal = yes,
+ Write(Info, ModuleId, ModuleResults, !IO)
+ ;
+ IsLocal = no,
+ debug_msg((pred(!.IO::di, !:IO::uo) is det :-
+ io.write_string("Not writing file for non-local module ", !IO),
+ io.write_string(ModuleId, !IO),
+ io.nl(!IO)
+ ), !IO)
+ ).
+
+:- pred write_module_analysis_results(analysis_info::in, module_id::in,
module_analysis_map(analysis_result)::in, io::di, io::uo) is det.
-write_analysis_files_2(Info, ModuleId, ModuleResults, !IO) :-
+write_module_analysis_results(Info, ModuleId, ModuleResults, !IO) :-
ModuleStatus = Info ^ module_statuses ^ det_elem(ModuleId),
write_module_analysis_results(Info, ModuleId,
ModuleStatus, ModuleResults, !IO).
Index: compiler/make.dependencies.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make.dependencies.m,v
retrieving revision 1.24
diff -u -r1.24 make.dependencies.m
--- compiler/make.dependencies.m 6 Feb 2006 05:39:41 -0000 1.24
+++ compiler/make.dependencies.m 10 Feb 2006 00:03:59 -0000
@@ -63,6 +63,16 @@
%-----------------------------------------------------------------------------%
+ % Find all modules in the current directory which are
+ % reachable (by import) from the given module.
+ % Return a list of `--local-module-id' options suitable for the
+ % command line.
+ %
+:- pred make_local_module_id_options(module_name::in, bool::out,
+ list(string)::out, make_info::in, make_info::out, io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+
:- pred dependency_status(dependency_file::in, dependency_status::out,
make_info::in, make_info::out, io::di, io::uo) is det.
@@ -106,6 +116,9 @@
:- implementation.
+:- import_module transform_hlds.
+:- import_module transform_hlds__mmc_analysis.
+
%-----------------------------------------------------------------------------%
:- type deps_result(T) == pair(bool, set(T)).
@@ -887,6 +900,19 @@
%-----------------------------------------------------------------------------%
+make_local_module_id_options(ModuleName, Success, Options, !Info, !IO) :-
+ find_reachable_local_modules(ModuleName, Success, LocalModules,
+ !Info, !IO),
+ set.fold(make_local_module_id_option, LocalModules, [], Options).
+
+:- pred make_local_module_id_option(module_name::in, list(string)::in,
+ list(string)::out) is det.
+
+make_local_module_id_option(ModuleName, Opts,
+ ["--local-module-id", module_name_to_module_id(ModuleName) | Opts]).
+
+%-----------------------------------------------------------------------------%
+
:- pred check_dependencies_debug_unbuilt(file_name::in,
assoc_list(dependency_file, dependency_status)::in,
io::di, io::uo) is det.
Index: compiler/make.module_target.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make.module_target.m,v
retrieving revision 1.36
diff -u -r1.36 make.module_target.m
--- compiler/make.module_target.m 6 Feb 2006 05:39:42 -0000 1.36
+++ compiler/make.module_target.m 10 Feb 2006 00:24:54 -0000
@@ -26,6 +26,15 @@
:- pred make_module_target(dependency_file::in, bool::out,
make_info::in, make_info::out, io::di, io::uo) is det.
+ % make_module_target_extra_options(ExtraOpts, Target, Success, Info0, Info)
+ %
+ % Make a target corresponding to a single module, with extra command line
+ % options.
+ %
+:- pred make_module_target_extra_options(list(string)::in,
+ dependency_file::in, bool::out,
+ make_info::in, make_info::out, io::di, io::uo) is det.
+
% record_made_target(Target, Task, MakeSucceeded)
%
% Record whether building a target succeeded or not.
@@ -75,10 +84,15 @@
!Info, !IO) :-
make_module_target(TargetFile, Succeeded2, !Info, !IO).
-make_module_target(file(_, _) @ Dep, Succeeded, !Info, !IO) :-
+make_module_target(DepFile, Succeeded, !Info, !IO) :-
+ make_module_target_extra_options([], DepFile, Succeeded, !Info, !IO).
+
+make_module_target_extra_options(_ExtraOptions, file(_, _) @ Dep,
+ Succeeded, !Info, !IO) :-
dependency_status(Dep, Status, !Info, !IO),
Succeeded = ( Status = error -> no ; yes ).
-make_module_target(target(TargetFile) @ Dep, Succeeded, !Info, !IO) :-
+make_module_target_extra_options(ExtraOptions, target(TargetFile) @ Dep,
+ Succeeded, !Info, !IO) :-
dependency_status(Dep, Status, !Info, !IO),
(
Status = not_considered,
@@ -100,7 +114,7 @@
CompilationTask = process_module(_) - _,
Imports ^ source_file_module_name \= ModuleName
->
- make_module_target(
+ make_module_target_extra_options(ExtraOptions,
target(Imports ^ source_file_module_name - FileType),
Succeeded, !Info, !IO)
;
@@ -167,8 +181,8 @@
set__delete(!.Info ^ command_line_targets,
ModuleName - module_target(FileType)),
build_target(CompilationTask, TargetFile, Imports,
- TouchedTargetFiles, TouchedFiles, Succeeded,
- !Info, !IO)
+ TouchedTargetFiles, TouchedFiles, ExtraOptions,
+ Succeeded, !Info, !IO)
;
DepsResult = up_to_date,
maybe_warn_up_to_date_target(
@@ -286,11 +300,11 @@
:- pred build_target(compilation_task_result::in, target_file::in,
module_imports::in, list(target_file)::in, list(file_name)::in,
- bool::out, make_info::in, make_info::out,
+ list(string)::in, bool::out, make_info::in, make_info::out,
io::di, io::uo) is det.
build_target(CompilationTask, TargetFile, Imports, TouchedTargetFiles,
- TouchedFiles, Succeeded, !Info, !IO) :-
+ TouchedFiles, ExtraOptions, Succeeded, !Info, !IO) :-
maybe_make_target_message(TargetFile, !IO),
TargetFile = ModuleName - _FileType,
CompilationTask = Task - TaskOptions,
@@ -322,8 +336,8 @@
),
build_with_check_for_interrupt(
build_with_module_options_and_output_redirect(ModuleName,
- TaskOptions,
- build_target_2(ModuleName, Task, MaybeArgFileName, Imports)),
+ ExtraOptions ++ TaskOptions,
+ build_target_2(ModuleName, Task, MaybeArgFileName, Imports)),
Cleanup, Succeeded, !Info, !IO),
record_made_target_2(Succeeded, TargetFile, TouchedTargetFiles,
TouchedFiles, !Info, !IO).
Index: compiler/make.program_target.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make.program_target.m,v
retrieving revision 1.40
diff -u -r1.40 make.program_target.m
--- compiler/make.program_target.m 7 Feb 2006 00:06:20 -0000 1.40
+++ compiler/make.program_target.m 10 Feb 2006 04:17:19 -0000
@@ -46,6 +46,9 @@
:- import_module transform_hlds.
:- import_module transform_hlds.mmc_analysis.
+:- import_module relation.
+:- import_module svrelation.
+
%-----------------------------------------------------------------------------%
make_linked_target(MainModuleName - FileType, Succeeded, !Info, !IO) :-
@@ -598,43 +601,93 @@
build_analysis_files(MainModuleName, AllModules, Succeeded0, Succeeded,
!Info, !IO) :-
- get_target_modules(analysis_registry, AllModules, TargetModules,
+ get_target_modules(analysis_registry, AllModules, TargetModules0,
!Info, !IO),
globals__io_lookup_bool_option(keep_going, KeepGoing, !IO),
( Succeeded0 = no, KeepGoing = no ->
Succeeded = no
;
- foldl2_maybe_stop_at_error(KeepGoing,
- make_module_target,
- make_dependency_list(TargetModules, analysis_registry),
- Succeeded1, !Info, !IO),
-
- % Find which module analysis files are suboptimal or invalid.
- % If there are any invalid files then we repeat the analysis pass.
- % If there are only suboptimal files then we repeat the analysis up
- % to the number of times given by the user.
- ReanalysisPasses = !.Info ^ reanalysis_passes,
- ReanalyseSuboptimal = (if ReanalysisPasses > 1 then yes else no),
- modules_needing_reanalysis(ReanalyseSuboptimal, TargetModules,
- InvalidModules, SuboptimalModules, !IO),
- ( list__is_not_empty(InvalidModules) ->
- maybe_reanalyse_modules_message(!IO),
- list__foldl(reset_analysis_registry_dependency_status,
- InvalidModules, !Info),
- build_analysis_files(MainModuleName, AllModules,
- Succeeded0, Succeeded, !Info, !IO)
- ; list__is_not_empty(SuboptimalModules) ->
- list__foldl(reset_analysis_registry_dependency_status,
- SuboptimalModules, !Info),
- !:Info = !.Info ^ reanalysis_passes := ReanalysisPasses - 1,
- maybe_reanalyse_modules_message(!IO),
- build_analysis_files(MainModuleName, AllModules,
- Succeeded0, Succeeded, !Info, !IO)
+ reverse_ordered_modules(!.Info ^ module_dependencies,
+ TargetModules0, TargetModules),
+ make_local_module_id_options(MainModuleName, Succeeded1,
+ LocalModulesOpts, !Info, !IO),
+ (
+ Succeeded1 = yes,
+ build_analysis_files_2(MainModuleName, TargetModules,
+ LocalModulesOpts, Succeeded0, Succeeded, !Info, !IO)
;
- Succeeded = Succeeded0 `and` Succeeded1
+ Succeeded1 = no,
+ Succeeded = no
)
).
+:- pred build_analysis_files_2(module_name::in, list(module_name)::in,
+ list(string)::in, bool::in, bool::out, make_info::in, make_info::out,
+ io::di, io::uo) is det.
+
+build_analysis_files_2(MainModuleName, TargetModules, LocalModulesOpts,
+ Succeeded0, Succeeded, !Info, !IO) :-
+ globals__io_lookup_bool_option(keep_going, KeepGoing, !IO),
+ foldl2_maybe_stop_at_error(KeepGoing,
+ make_module_target_extra_options(LocalModulesOpts),
+ make_dependency_list(TargetModules, analysis_registry),
+ Succeeded1, !Info, !IO),
+ % Maybe we should have an option to reanalyse cliques before moving
+ % upwards in the dependency graph?
+
+ % Find which module analysis files are suboptimal or invalid.
+ % If there are any invalid files then we repeat the analysis pass.
+ % If there are only suboptimal files then we repeat the analysis up
+ % to the number of times given by the user.
+ ReanalysisPasses = !.Info ^ reanalysis_passes,
+ ReanalyseSuboptimal = (if ReanalysisPasses > 1 then yes else no),
+ modules_needing_reanalysis(ReanalyseSuboptimal, TargetModules,
+ InvalidModules, SuboptimalModules, !IO),
+ ( list__is_not_empty(InvalidModules) ->
+ maybe_reanalyse_modules_message(!IO),
+ list__foldl(reset_analysis_registry_dependency_status,
+ InvalidModules, !Info),
+ build_analysis_files_2(MainModuleName, TargetModules, LocalModulesOpts,
+ Succeeded0, Succeeded, !Info, !IO)
+ ; list__is_not_empty(SuboptimalModules) ->
+ list__foldl(reset_analysis_registry_dependency_status,
+ SuboptimalModules, !Info),
+ !:Info = !.Info ^ reanalysis_passes := ReanalysisPasses - 1,
+ maybe_reanalyse_modules_message(!IO),
+ build_analysis_files_2(MainModuleName, TargetModules, LocalModulesOpts,
+ Succeeded0, Succeeded, !Info, !IO)
+ ;
+ Succeeded = Succeeded0 `and` Succeeded1
+ ).
+
+ % Return a list of modules in reverse order of their dependencies, i.e.
+ % the list is the module dependency graph from bottom-up. Mutually
+ % dependent modules (modules which form a clique in the dependency graph)
+ % are returned adjacent in the list in arbitrary order.
+ %
+:- pred reverse_ordered_modules(map(module_name, maybe(module_imports))::in,
+ list(module_name)::in, list(module_name)::out) is det.
+
+reverse_ordered_modules(ModuleDeps, Modules0, Modules) :-
+ list__foldl2(add_module_relations(lookup_module_imports(ModuleDeps)),
+ Modules0, relation__init, _IntRel, relation__init, ImplRel),
+ relation__atsort(ImplRel, Order0),
+ list__reverse(Order0, Order1),
+ list__map(set__to_sorted_list, Order1, Order2),
+ list__condense(Order2, Modules).
+
+:- func lookup_module_imports(map(module_name, maybe(module_imports)),
+ module_name) = module_imports.
+
+lookup_module_imports(ModuleDeps, ModuleName) = ModuleImports :-
+ map__lookup(ModuleDeps, ModuleName, MaybeModuleImports),
+ (
+ MaybeModuleImports = yes(ModuleImports)
+ ;
+ MaybeModuleImports = no,
+ unexpected(this_file, "lookup_module_imports")
+ ).
+
:- pred modules_needing_reanalysis(bool::in, list(module_name)::in,
list(module_name)::out, list(module_name)::out, io::di, io::uo) is det.
@@ -939,7 +992,7 @@
Succeeded = no
).
- % Install the `.opt' and `.mih' files for the current grade.
+ % Install the `.opt', `.analysis' and `.mih' files for the current grade.
%
:- pred install_grade_ints_and_headers(bool::in, string::in, module_name::in,
bool::out, make_info::in, make_info::out, io::di, io::uo) is det.
@@ -978,18 +1031,31 @@
HeaderSucceeded = yes
),
+ GradeIntDir = LibDir/"ints"/GradeDir,
globals__io_lookup_bool_option(intermodule_optimization, Intermod,
!IO),
(
Intermod = yes,
- GradeIntDir = LibDir/"ints"/GradeDir,
install_subdir_file(LinkSucceeded, GradeIntDir, ModuleName, "opt",
OptSucceeded, !IO)
;
Intermod = no,
OptSucceeded = yes
),
- Succeeded = HeaderSucceeded `and` OptSucceeded
+
+ globals__io_lookup_bool_option(intermodule_analysis, IntermodAnalysis,
+ !IO),
+ (
+ IntermodAnalysis = yes,
+ install_subdir_file(LinkSucceeded, GradeIntDir,
+ ModuleName, "analysis", IntermodAnalysisSucceeded, !IO)
+ ;
+ IntermodAnalysis = no,
+ IntermodAnalysisSucceeded = yes
+ ),
+
+ Succeeded = HeaderSucceeded `and` OptSucceeded `and`
+ IntermodAnalysisSucceeded
;
MaybeImports = no,
Succeeded = no
@@ -1092,7 +1158,7 @@
make_install_symlink(GradeIncSubdir, "mih", LinkResult0, !IO),
list__map_foldl(make_install_symlink(GradeIntsSubdir),
- ["opt", "trans_opt"], LinkResults, !IO),
+ ["opt", "trans_opt", "analysis"], LinkResults, !IO),
LinkResult = bool__and_list([LinkResult0 | LinkResults]),
(
LinkResult = yes,
@@ -1102,7 +1168,8 @@
make_directory(GradeIncSubdir/"mihs", Result4, !IO),
make_directory(GradeIntsSubdir/"opts", Result5, !IO),
make_directory(GradeIntsSubdir/"trans_opts", Result6, !IO),
- Results = [Result4, Result5, Result6 | Results0]
+ make_directory(GradeIntsSubdir/"analysiss", Result7, !IO),
+ Results = [Result4, Result5, Result6, Result7 | Results0]
),
print_mkdir_errors(Results, Result, !IO).
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.375
diff -u -r1.375 mercury_compile.m
--- compiler/mercury_compile.m 6 Feb 2006 05:39:42 -0000 1.375
+++ compiler/mercury_compile.m 9 Feb 2006 00:13:42 -0000
@@ -3678,13 +3678,10 @@
globals__lookup_bool_option(Globals, intermod_unused_args, Intermod),
globals__lookup_bool_option(Globals, optimize_unused_args, Optimize),
globals__lookup_bool_option(Globals, warn_unused_args, Warn),
- globals__lookup_bool_option(Globals, intermodule_analysis,
- IntermodAnalysis),
(
( Optimize = yes
; Warn = yes
; Intermod = yes
- ; IntermodAnalysis = yes
)
->
maybe_write_string(Verbose, "% Finding unused arguments ...\n", !IO),
Index: compiler/mmc_analysis.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mmc_analysis.m,v
retrieving revision 1.11
diff -u -r1.11 mmc_analysis.m
--- compiler/mmc_analysis.m 1 Feb 2006 04:02:46 -0000 1.11
+++ compiler/mmc_analysis.m 10 Feb 2006 02:49:12 -0000
@@ -43,7 +43,10 @@
:- implementation.
+:- import_module libs.globals.
+:- import_module libs.options.
:- import_module parse_tree.modules.
+:- import_module parse_tree.prog_io.
:- import_module parse_tree.prog_out.
:- import_module parse_tree.prog_util.
:- import_module transform_hlds.exception_analysis.
@@ -51,8 +54,10 @@
:- import_module transform_hlds.unused_args.
:- import_module bool.
+:- import_module list.
:- import_module std_util.
:- import_module string.
+:- import_module io.
%-----------------------------------------------------------------------------%
@@ -74,11 +79,39 @@
unit1 : unit(unused_args_call),
unit1 : unit(unused_args_answer)),
- module_id_to_file_name(mmc, ModuleId, Ext, FileName) -->
- module_name_to_file_name(module_id_to_module_name(ModuleId),
- Ext, yes, FileName)
+ module_id_to_read_file_name(mmc, ModuleId, Ext, FileName, !IO) :-
+ mmc_module_id_to_read_file_name(ModuleId, Ext, FileName, !IO),
+
+ module_id_to_write_file_name(mmc, ModuleId, Ext, FileName, !IO) :-
+ mmc_module_id_to_write_file_name(ModuleId, Ext, FileName, !IO),
+
+ module_is_local(mmc, ModuleId, IsLocal, !IO) :-
+ mmc_module_is_local(ModuleId, IsLocal, !IO)
].
+:- pred mmc_module_id_to_read_file_name(module_id::in, string::in,
+ maybe_error(string)::out, io::di, io::uo) is det.
+
+mmc_module_id_to_read_file_name(ModuleId, Ext, MaybeFileName, !IO) :-
+ ModuleName = module_id_to_module_name(ModuleId),
+ modules.module_name_to_search_file_name(ModuleName, Ext, FileName0, !IO),
+ globals.io_lookup_accumulating_option(intermod_directories, Dirs, !IO),
+ search_for_file(Dirs, FileName0, MaybeFileName, !IO).
+
+:- pred mmc_module_id_to_write_file_name(module_id::in, string::in, string::out,
+ io::di, io::uo) is det.
+
+mmc_module_id_to_write_file_name(ModuleId, Ext, FileName, !IO) :-
+ ModuleName = module_id_to_module_name(ModuleId),
+ module_name_to_file_name(ModuleName, Ext, yes, FileName, !IO).
+
+:- pred mmc_module_is_local(module_id::in, bool::out, io::di, io::uo) is det.
+
+mmc_module_is_local(ModuleId, IsLocal, !IO) :-
+ globals__io_lookup_accumulating_option(local_module_id, LocalModuleIds,
+ !IO),
+ IsLocal = (if ModuleId `list.member` LocalModuleIds then yes else no).
+
module_name_to_module_id(ModuleName) = ModuleId :-
sym_name_to_string(ModuleName, ModuleId).
Index: compiler/modules.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.371
diff -u -r1.371 modules.m
--- compiler/modules.m 7 Feb 2006 00:06:20 -0000 1.371
+++ compiler/modules.m 10 Feb 2006 04:12:40 -0000
@@ -52,6 +52,7 @@
:- import_module io.
:- import_module list.
:- import_module map.
+:- import_module relation.
:- import_module set.
:- import_module std_util.
@@ -633,6 +634,20 @@
%
:- pred generate_file_dependency_file(file_name::in, io::di, io::uo) is det.
+ % add_module_relations(LookupModuleImports, ModuleName,
+ % !IntDepsRel, !ImplDepsRel)
+ %
+ % Add a module's interface and implementation dependencies to IntDepsRel
+ % and ImplDepsRel respectively. Dependencies are found using the
+ % LookupModuleImports function.
+ %
+:- pred add_module_relations(lookup_module_imports::lookup_module_imports,
+ module_name::in, relation(module_name)::in, relation(module_name)::out,
+ relation(module_name)::in, relation(module_name)::out) is det.
+
+:- type lookup_module_imports == (func(module_name) = module_imports).
+:- mode lookup_module_imports == in(func(in) = out is det).
+
% get_dependencies(Items, ImportDeps, UseDeps):
%
% Get the list of modules that a list of items (explicitly) depends on.
@@ -803,7 +818,6 @@
:- import_module getopt_io.
:- import_module library.
:- import_module multi_map.
-:- import_module relation.
:- import_module sparse_bitset.
:- import_module string.
:- import_module svmap.
@@ -1152,6 +1166,7 @@
Search = yes,
( Ext = ".opt"
; Ext = ".trans_opt"
+ ; Ext = ".analysis"
)
)
->
@@ -1213,6 +1228,10 @@
file_is_arch_or_grade_dependent_2(".optdate").
file_is_arch_or_grade_dependent_2(".trans_opt").
file_is_arch_or_grade_dependent_2(".trans_opt_date").
+file_is_arch_or_grade_dependent_2(".analysis").
+file_is_arch_or_grade_dependent_2(".analysis_date").
+file_is_arch_or_grade_dependent_2(".imdg").
+file_is_arch_or_grade_dependent_2(".request").
file_is_arch_or_grade_dependent_2(".mih").
file_is_arch_or_grade_dependent_2(".c").
file_is_arch_or_grade_dependent_2(".c_date").
@@ -4321,47 +4340,68 @@
Deps = deps(_, ModuleImports),
ModuleError = ModuleImports ^ error,
( ModuleError \= fatal_module_errors ->
- %
- % Add interface dependencies to the interface deps relation.
- %
- % Note that we need to do this both for the interface imports
- % of this module and for the *implementation* imports of
- % its ancestors. This is because if this module is defined
- % in the implementation section of its parent, then the
- % interface of this module may depend on things
- % imported only by its parent's implementation.
- %
- % If this module was actually defined in the interface
- % section of one of its ancestors, then it should only
- % depend on the interface imports of that ancestor,
- % so the dependencies added here are in fact more
- % conservative than they need to be in that case.
- % However, that should not be a major problem.
- %
- ModuleName = ModuleImports ^ module_name,
- ParentDeps = ModuleImports ^ parent_deps,
- svrelation__add_element(ModuleName, IntModuleKey, !IntRel),
- add_int_deps(IntModuleKey, ModuleImports, !IntRel),
- add_parent_impl_deps_list(DepsMap, IntModuleKey, ParentDeps, !IntRel),
-
- %
- % Add implementation dependencies to the impl. deps relation.
- % (The implementation dependencies are a superset of the
- % interface dependencies.)
- %
- % Note that we need to do this both for the imports
- % of this module and for the imports of its parents,
- % because this module may depend on things imported
- % only by its parents.
- %
- svrelation__add_element(ModuleName, ImplModuleKey, !ImplRel),
- add_impl_deps(ImplModuleKey, ModuleImports, !ImplRel),
- add_parent_impl_deps_list(DepsMap, ImplModuleKey, ParentDeps, !ImplRel)
+ module_imports_to_deps_rel(ModuleImports,
+ lookup_module_imports(DepsMap), !IntRel, !ImplRel)
;
true
),
deps_list_to_deps_rel(DepsList, DepsMap, !IntRel, !ImplRel).
+:- func lookup_module_imports(deps_map, module_name) = module_imports.
+
+lookup_module_imports(DepsMap, ModuleName) = ModuleImports :-
+ map__lookup(DepsMap, ModuleName, deps(_, ModuleImports)).
+
+add_module_relations(LookupModuleImports, ModuleName, !IntRel, !ImplRel) :-
+ ModuleImports = LookupModuleImports(ModuleName),
+ module_imports_to_deps_rel(ModuleImports, LookupModuleImports,
+ !IntRel, !ImplRel).
+
+:- pred module_imports_to_deps_rel(module_imports::in,
+ lookup_module_imports::lookup_module_imports,
+ deps_rel::in, deps_rel::out, deps_rel::in, deps_rel::out) is det.
+
+module_imports_to_deps_rel(ModuleImports, LookupModuleImports,
+ !IntRel, !ImplRel) :-
+ %
+ % Add interface dependencies to the interface deps relation.
+ %
+ % Note that we need to do this both for the interface imports
+ % of this module and for the *implementation* imports of
+ % its ancestors. This is because if this module is defined
+ % in the implementation section of its parent, then the
+ % interface of this module may depend on things
+ % imported only by its parent's implementation.
+ %
+ % If this module was actually defined in the interface
+ % section of one of its ancestors, then it should only
+ % depend on the interface imports of that ancestor,
+ % so the dependencies added here are in fact more
+ % conservative than they need to be in that case.
+ % However, that should not be a major problem.
+ %
+ ModuleName = ModuleImports ^ module_name,
+ ParentDeps = ModuleImports ^ parent_deps,
+ svrelation__add_element(ModuleName, IntModuleKey, !IntRel),
+ add_int_deps(IntModuleKey, ModuleImports, !IntRel),
+ add_parent_impl_deps_list(LookupModuleImports, IntModuleKey, ParentDeps,
+ !IntRel),
+
+ %
+ % Add implementation dependencies to the impl. deps relation.
+ % (The implementation dependencies are a superset of the
+ % interface dependencies.)
+ %
+ % Note that we need to do this both for the imports
+ % of this module and for the imports of its parents,
+ % because this module may depend on things imported
+ % only by its parents.
+ %
+ svrelation__add_element(ModuleName, ImplModuleKey, !ImplRel),
+ add_impl_deps(ImplModuleKey, ModuleImports, !ImplRel),
+ add_parent_impl_deps_list(LookupModuleImports, ImplModuleKey, ParentDeps,
+ !ImplRel).
+
% Add interface dependencies to the interface deps relation.
%
:- pred add_int_deps(relation_key::in, module_imports::in,
@@ -4389,18 +4429,20 @@
% Add parent implementation dependencies for the given Parent module
% to the impl. deps relation values for the given ModuleKey.
%
-:- pred add_parent_impl_deps(deps_map::in, relation_key::in, module_name::in,
- deps_rel::in, deps_rel::out) is det.
+:- pred add_parent_impl_deps(lookup_module_imports::lookup_module_imports,
+ relation_key::in, module_name::in, deps_rel::in, deps_rel::out) is det.
-add_parent_impl_deps(DepsMap, ModuleKey, Parent, !Rel) :-
- map__lookup(DepsMap, Parent, deps(_, ParentModuleImports)),
+add_parent_impl_deps(LookupModuleImports, ModuleKey, Parent, !Rel) :-
+ ParentModuleImports = LookupModuleImports(Parent),
add_impl_deps(ModuleKey, ParentModuleImports, !Rel).
-:- pred add_parent_impl_deps_list(deps_map::in, relation_key::in,
- list(module_name)::in, deps_rel::in, deps_rel::out) is det.
+:- pred add_parent_impl_deps_list(lookup_module_imports::lookup_module_imports,
+ relation_key::in, list(module_name)::in, deps_rel::in, deps_rel::out)
+ is det.
-add_parent_impl_deps_list(DepsMap, ModuleKey, Parents, !Rel) :-
- list__foldl(add_parent_impl_deps(DepsMap, ModuleKey), Parents, !Rel).
+add_parent_impl_deps_list(LookupModuleImports, ModuleKey, Parents, !Rel) :-
+ list__foldl(add_parent_impl_deps(LookupModuleImports, ModuleKey), Parents,
+ !Rel).
% Add a single dependency to a relation.
%
Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.494
diff -u -r1.494 options.m
--- compiler/options.m 6 Feb 2006 05:39:43 -0000 1.494
+++ compiler/options.m 8 Feb 2006 06:28:32 -0000
@@ -758,6 +758,7 @@
; help
; version
; fullarch
+ ; local_module_id
; compiler_sufficiently_recent
% This option is used to test that the compiler is sufficiently
% recent when no other test can easily be constructed in
@@ -1491,6 +1492,7 @@
help - bool(no),
version - bool(no),
fullarch - string(""),
+ local_module_id - accumulating([]),
compiler_sufficiently_recent - bool(no),
experiment - string("")
]).
@@ -2238,6 +2240,7 @@
long_option("filenames-from-stdin", filenames_from_stdin).
long_option("aditi-user", aditi_user).
long_option("fullarch", fullarch).
+long_option("local-module-id", local_module_id).
long_option("bug-intermod-2002-06-13", compiler_sufficiently_recent).
long_option("bug-foreign_import-2002-08-06", compiler_sufficiently_recent).
long_option("install-opt-files-2002-08-30", compiler_sufficiently_recent).
@@ -4591,6 +4594,8 @@
% The `--fullarch' option is reserved for
% use by the `Mercury.config' file.
+
+ % The `--local-module-id' option is used by `mmc --make'.
]).
:- pred write_tabbed_lines(list(string)::in, io::di, io::uo) is det.
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list