diff: fixed transitive intermodule optimization

Christopher Rodd SPEIRS crs at students.cs.mu.oz.au
Wed Jan 7 10:50:55 AEDT 1998


Hi,
	Here is a fixed diff of the changes to support transitive
intermodule optimization.  It is already committed.

Chris


Fix the processing of .trans_opt files so that circular dependencies
cannot occur.  This also guarantees correctness of the information in
the .trans_opt file.

compiler/handle_options.m:
	Add the fact that --transitive-intermodule-optimization implies
	--intermodule-optimization, and that
	--make-transitive-optimization-interface implies
	--transitive-intermodule-optimization.

compiler/mercury_compile.m:
	Add code to read the .d file before new .d files are written.
	The .d file is only read if transitive intermodule optimization
	is enabled.  Also changed the pre-hlds pass so that .d files
	were not written when `error-check only' or `type-check only'
	options were selected.

compiler/modules.m:
	Modified so that the trans_opt dependencies were correctly
	created, and so they were written out to the .d files.  Also
	added new code to read the .d files in.  Removed the
	transitive_dependencies set of predicates as they were no longer
	used.

compiler/options.m:
	Added new option 'warn-missing-trans-opt-deps', to control
	whether warnings are emitted when the dependency information in
	the .d file is lost.  Also uncommented the help messages
	describing transitive-intermodule-optimization.

compiler/trans_opt.m:
	Small changes to trans_opt__grab_optfiles. Also modified the
	comment at the beginning of the file to reflect the current set
	of changes.

doc/user_guide.texi:
	Uncommented the documentation on transitive intermodule
	optimization.


Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.37
diff -u -r1.37 handle_options.m
--- 1.37	1997/12/10 07:15:40
+++ handle_options.m	1998/01/06 23:37:31
@@ -1,5 +1,5 @@
 %-----------------------------------------------------------------------------%
-% Copyright (C) 1994-1997 The University of Melbourne.
+% Copyright (C) 1994-1998 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.
 %-----------------------------------------------------------------------------%
@@ -247,17 +247,17 @@
 
 	globals__io_set_option(num_tag_bits, int(NumTagBits)),
 
-	% --verbose-check-termination implies --check-termination
 	option_implies(verbose_check_termination, check_termination,bool(yes)),
-	% --check-termination implies --enable-termination
 	option_implies(check_termination, termination, bool(yes)),
+	option_implies(make_transitive_opt_interface, transitive_optimization,
+		bool(yes)),
+	option_implies(transitive_optimization, intermodule_optimization,
+		bool(yes)),
+	option_implies(very_verbose, verbose, bool(yes)),
 
 	% --split-c-files implies --procs-per-c-function 1
 	option_implies(split_c_files, procs_per_c_function, int(1)),
 
-	% --very-verbose implies --verbose
-	option_implies(very_verbose, verbose, bool(yes)),
-
 	% -D all is really -D "abcdefghijklmnopqrstuvwxyz"
 	globals__io_lookup_string_option(verbose_dump_hlds, VerboseDump),
 	( { VerboseDump = "all" } ->
@@ -652,7 +652,7 @@
  	io__write_strings(StdErr,
 			["Mercury Compiler, version ", Version, "\n"]),
  	io__write_string(StdErr,
-			"Copyright (C) 1993-1997 The University of Melbourne\n"),
+			"Copyright (C) 1993-1998 The University of Melbourne\n"),
 	io__write_string(StdErr, "Usage: "),
 	io__write_string(StdErr, ProgName),
 	io__write_string(StdErr, " [<options>] <module(s)>\n"),
@@ -664,7 +664,7 @@
 	io__progname_base("mercury_compile", ProgName),
 	{ library__version(Version) },
  	io__write_strings(["Mercury Compiler, version ", Version, "\n"]),
- 	io__write_string("Copyright (C) 1993-1997 The University of Melbourne\n"),
+ 	io__write_string("Copyright (C) 1993-1998 The University of Melbourne\n"),
 	io__write_string("Usage: "),
 	io__write_string(ProgName),
 	io__write_string(" [<options>] <module(s)>\n"),
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.69
diff -u -r1.69 mercury_compile.m
--- 1.69	1998/01/02 00:10:41
+++ mercury_compile.m	1998/01/05 12:09:03
@@ -200,18 +200,20 @@
 :- mode mercury_compile(in, in, di, uo) is det.
 
 mercury_compile(Module, FactDeps) -->
-	{ Module = module_imports(ModuleName, _, _, _, _) },
-	mercury_compile__pre_hlds_pass(Module, FactDeps, HLDS1, UndefTypes,
-						UndefModes, Errors1), !,
+	globals__io_lookup_bool_option(typecheck_only, TypeCheckOnly),
+	globals__io_lookup_bool_option(errorcheck_only, ErrorCheckOnly),
+	{ bool__or(TypeCheckOnly, ErrorCheckOnly, DontWriteDFile) },
+	% If we are only typechecking or error checking, then we should not
+	% modify any files, this includes writing to .d files.
+	mercury_compile__pre_hlds_pass(Module, FactDeps, DontWriteDFile,
+		HLDS1, UndefTypes, UndefModes, Errors1), !,
 	mercury_compile__frontend_pass(HLDS1, HLDS20, UndefTypes,
-						UndefModes, Errors2), !,
+		UndefModes, Errors2), !,
 	( { Errors1 = no }, { Errors2 = no } ->
 	    globals__io_lookup_bool_option(verbose, Verbose),
 	    globals__io_lookup_bool_option(statistics, Stats),
 	    mercury_compile__maybe_write_dependency_graph(HLDS20,
 		Verbose, Stats, HLDS21),
-	    globals__io_lookup_bool_option(typecheck_only, TypeCheckOnly),
-	    globals__io_lookup_bool_option(errorcheck_only, ErrorCheckOnly),
 	    globals__io_lookup_bool_option(make_optimization_interface,
 		MakeOptInt),
 	    globals__io_lookup_bool_option(make_transitive_opt_interface,
@@ -229,6 +231,7 @@
 	    ; { MakeTransOptInt = yes } ->
 	    	mercury_compile__output_trans_opt_file(HLDS21)
 	    ;
+		{ Module = module_imports(ModuleName, _, _, _, _) },
 		mercury_compile__maybe_output_prof_call_graph(HLDS21,
 			Verbose, Stats, HLDS25),
 		mercury_compile__middle_pass(ModuleName, HLDS25, HLDS50), !,
@@ -258,21 +261,33 @@
 %-----------------------------------------------------------------------------%
 
 :- pred mercury_compile__pre_hlds_pass(module_imports, list(string),
-		module_info, bool, bool, bool, io__state, io__state).
-:- mode mercury_compile__pre_hlds_pass(in, in, out, out, out, out,
+		bool, module_info, bool, bool, bool, io__state, io__state).
+:- mode mercury_compile__pre_hlds_pass(in, in, in, out, out, out, out,
 		di, uo) is det.
 
-mercury_compile__pre_hlds_pass(ModuleImports0, FactDeps, HLDS1, UndefTypes,
-		UndefModes, FoundError) -->
+mercury_compile__pre_hlds_pass(ModuleImports0, FactDeps, DontWriteDFile,
+		HLDS1, UndefTypes, UndefModes, FoundError) -->
 	globals__io_lookup_bool_option(statistics, Stats),
 	globals__io_lookup_bool_option(verbose, Verbose),
 
 	{ ModuleImports0 = module_imports(Module, LongDeps, ShortDeps, _, _) },
-	write_dependency_file(Module, LongDeps, ShortDeps, FactDeps), !,
+	
+
+	( { DontWriteDFile = yes } ->
+		% The only time the TransOptDeps are required is when
+		% creating the .trans_opt file.  If DontWriteDFile is yes,
+		% then error check only or type-check only is enabled, so
+		% we cant be creating the .trans_opt file.
+		{ MaybeTransOptDeps = no }
+	;
+		maybe_read_dependency_file(Module, MaybeTransOptDeps), !,
+		write_dependency_file(Module, LongDeps, ShortDeps, FactDeps, 
+			MaybeTransOptDeps), !
+	),
 
 	% Errors in .opt and .trans_opt files result in software errors.
 	mercury_compile__maybe_grab_optfiles(ModuleImports0, Verbose,
-				 ModuleImports1, IntermodError), !,
+		MaybeTransOptDeps, ModuleImports1, IntermodError), !,
 
 	{ ModuleImports1 = module_imports(_, _, _, Items1, _) },
 	mercury_compile__module_qualify_items(Items1, Items2, Module, Verbose,
@@ -321,14 +336,18 @@
 	maybe_report_stats(Stats).
 
 :- pred mercury_compile__maybe_grab_optfiles(module_imports, bool,
-	 module_imports, bool, io__state, io__state).
-:- mode mercury_compile__maybe_grab_optfiles(in, in, out, out, di, uo) is det.
+	 maybe(list(string)), module_imports, bool, io__state, io__state).
+:- mode mercury_compile__maybe_grab_optfiles(in, in, in, out, out, 
+	di, uo) is det.
 
-mercury_compile__maybe_grab_optfiles(Imports0, Verbose, Imports, Error) -->
+mercury_compile__maybe_grab_optfiles(Imports0, Verbose, MaybeTransOptDeps, 
+		Imports, Error) -->
 	globals__io_lookup_bool_option(intermodule_optimization, UseOptInt),
 	globals__io_lookup_bool_option(make_optimization_interface,
 						MakeOptInt),
 	globals__io_lookup_bool_option(transitive_optimization, TransOpt),
+	globals__io_lookup_bool_option(make_transitive_opt_interface,
+		MakeTransOptInt),
 	( { UseOptInt = yes, MakeOptInt = no } ->
 		maybe_write_string(Verbose, "% Reading .opt files...\n"),
 		maybe_flush_output(Verbose),
@@ -338,15 +357,45 @@
 		{ Imports1 = Imports0 },
 		{ Error1 = no }
 	),
-	( { TransOpt = yes } ->
-		maybe_write_string(Verbose, "% Reading .trans_opt files..\n"),
-		maybe_flush_output(Verbose),
-		trans_opt__grab_optfiles(Imports1, Imports, Error2),
-		maybe_write_string(Verbose, "% Done.\n")
+	( { MakeTransOptInt = yes } ->
+		( { MaybeTransOptDeps = yes(TransOptDeps) } ->
+			% When creating the trans_opt file, only import the
+			% trans_opt files which are lower in the ordering.
+			trans_opt__grab_optfiles(Imports1, TransOptDeps, 
+				Imports, Error2)
+		;
+			{ Imports = Imports1 },
+			{ Error2 = no },
+			{ Imports = module_imports(ModuleName, _, _, _, _) },
+			globals__io_lookup_bool_option(
+				warn_missing_trans_opt_deps,
+				WarnNoTransOptDeps),
+			( { WarnNoTransOptDeps = yes } ->
+				io__write_strings([
+				    "Warning: Cannot read dependencies for `",
+				    ModuleName, ".trans_opt'.\n",
+				    "  run `mmake main_module.depend' ",
+				    "to remake the dependencies\n"])
+			;
+				[]
+			)
+		)
 	;
-		{ Imports = Imports1 },
-		{ Error2 = no }
+		( { TransOpt = yes } ->
+			% If transitive optimization is enabled, but we are
+			% not creating the trans opt file, then import the
+			% trans_opt files for all the modules that are
+			% imported (or used).
+			{ Imports0 = module_imports(_Module, DirectImports, 
+				_IndirectImports, _Items, _) },
+			trans_opt__grab_optfiles(Imports1, DirectImports,
+				Imports, Error2)
+		;
+			{ Imports = Imports1 },
+			{ Error2 = no }
+		)
 	),
+
 	{ bool__or(Error1, Error2, Error) }.
 
 :- pred mercury_compile__expand_equiv_types(item_list, bool, bool, item_list,
Index: compiler/modules.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.46
diff -u -r1.46 modules.m
--- 1.46	1998/01/05 09:53:15
+++ modules.m	1998/01/06 23:23:51
@@ -87,15 +87,28 @@
 			module_error, io__state, io__state).
 :- mode grab_imported_modules(in, in, out, out, out, di, uo) is det.
 
-	% write_dependency_file(ModuleName, LongDeps, ShortDeps, FactDeps):
+	% write_dependency_file(ModuleName, LongDeps, ShortDeps, FactDeps
+	% 		MaybeTransOptDeps):
 	%	Write out the per-module makefile dependencies (`.d') file
 	%	for a module `ModuleName' which depends directly on the
 	% 	modules `LongDeps' and indirectly on the modules `ShortDeps'.
 	%	FactDeps is the list of filenames of fact tables in the module.
+	%	MaybeTransOptDeps is a list of filenames which the
+	%	.trans_opt file may depend on.  This is set to no if the
+	%	dependency list is not available.
 	%
 :- pred write_dependency_file(string, list(string), list(string), list(string),
-				io__state, io__state).
-:- mode write_dependency_file(in, in, in, in, di, uo) is det.
+				maybe(list(string)), io__state, io__state).
+:- mode write_dependency_file(in, in, in, in, in, di, uo) is det.
+
+	%	maybe_read_dependency_file(ModuleName, MaybeTransOptDeps).
+	%	If transitive intermodule optimization has been enabled,
+	%	then read <ModuleName>.d to find the modules which
+	%	<ModuleName>.trans_opt may depend on.  Otherwise return
+	%	`no'.
+:- pred maybe_read_dependency_file(string, maybe(list(string)), io__state,
+	io__state).
+:- mode maybe_read_dependency_file(in, out, di, uo) is det.
 
 	% generate_dependencies(ModuleName):
 	%	Generate the per-program makefile dependencies (`.dep') file
@@ -147,7 +160,7 @@
 :- import_module passes_aux, prog_out, mercury_to_mercury.
 :- import_module prog_io_util, globals, options, intermod, module_qual.
 :- import_module bool, string, set, map, term, varset, dir, std_util, library.
-:- import_module assoc_list, relation.
+:- import_module assoc_list, relation, char, require.
 
 	% Read in the .int3 files that the current module depends on,
 	% and use these to qualify all items in the interface as much as
@@ -453,7 +466,8 @@
 
 %-----------------------------------------------------------------------------%
 
-write_dependency_file(ModuleName, LongDeps0, ShortDeps0, FactDeps0) -->
+write_dependency_file(ModuleName, LongDeps0, ShortDeps0, FactDeps0,
+		MaybeTransOptDeps) -->
 	globals__io_lookup_bool_option(verbose, Verbose),
 	{ string__append(ModuleName, ".d", DependencyFileName) },
 	maybe_write_string(Verbose, "% Writing auto-dependency file `"),
@@ -462,16 +476,32 @@
 	maybe_flush_output(Verbose),
 	io__open_output(DependencyFileName, Result),
 	( { Result = ok(DepStream) } ->
-		{ list__sort_and_remove_dups(LongDeps0, LongDeps1) },
-		{ list__delete_all(LongDeps1, ModuleName, LongDeps) },
-		{ list__sort_and_remove_dups(ShortDeps0, ShortDeps1) },
-		{ list__delete_elems(ShortDeps1, LongDeps, ShortDeps2) },
-		{ list__delete_all(ShortDeps2, ModuleName, ShortDeps) },
+		{ set__list_to_set(LongDeps0, LongDepsSet0) },
+		{ set__delete(LongDepsSet0, ModuleName, LongDepsSet) },
+		{ set__list_to_set(ShortDeps0, ShortDepsSet0) },
+		{ set__difference(ShortDepsSet0, LongDepsSet, ShortDepsSet1) },
+		{ set__delete(ShortDepsSet1, ModuleName, ShortDepsSet) },
+		{ set__to_sorted_list(LongDepsSet, LongDeps) },
+		{ set__to_sorted_list(ShortDepsSet, ShortDeps) },
 		{ list__sort_and_remove_dups(FactDeps0, FactDeps) },
 
+		( { MaybeTransOptDeps = yes(TransOptDeps0) } ->
+			{ set__list_to_set(TransOptDeps0, TransOptDepsSet0) },
+			{ set__intersect(TransOptDepsSet0, LongDepsSet,
+				TransOptDepsSet) },
+			{ set__to_sorted_list(TransOptDepsSet, 
+				TransOptDateDeps) },
+			io__write_strings(DepStream,
+				[ModuleName, ".trans_optdate : "]),
+			write_dependencies_list(TransOptDateDeps, ".trans_opt", 
+				DepStream)
+		;
+			[]
+		),
+
 		( { FactDeps \= [] } ->
 			io__write_strings(DepStream, 
-				[ModuleName, ".fact_tables = "]),
+				["\n\n", ModuleName, ".fact_tables = "]),
 			write_dependencies_list(FactDeps, "", DepStream),
 			io__nl(DepStream),
 			globals__io_lookup_bool_option(assume_gmake,
@@ -502,7 +532,8 @@
 		),
 
 
-		io__write_strings(DepStream, [
+		io__write_strings(DepStream, ["\n\n",
+			ModuleName, ".trans_optdate ",
 			ModuleName, ".optdate ",
 			ModuleName, ".c ",
 			ModuleName, ".err ",
@@ -526,11 +557,14 @@
 		),
 
 		globals__io_lookup_bool_option(intermodule_optimization,
-							Intermod),
+			Intermod),
 		( { Intermod = yes } ->
 			io__write_strings(DepStream, [
-				"\n\n", ModuleName, ".c ",
-				ModuleName, ".err ", ModuleName, ".o :"
+				"\n\n", 
+				ModuleName, ".c ",
+				ModuleName, ".trans_optdate ",
+				ModuleName, ".err ", 
+				ModuleName, ".o :"
 			]),
 			% The .c file only depends on the .opt files from 
 			% the current directory, so that inter-module
@@ -543,9 +577,27 @@
 			% modules.
 			globals__io_lookup_accumulating_option(
 				intermod_directories, IntermodDirs),
-			get_opt_deps(LongDeps, IntermodDirs, [], OptDeps),
-			write_dependencies_list([ModuleName | OptDeps],
-				".opt", DepStream)
+			globals__io_lookup_bool_option(transitive_optimization,
+				TransOpt),
+			( { TransOpt = yes } ->
+				get_both_opt_deps(LongDeps, IntermodDirs, 
+					OptDeps, TransOptDeps),
+				write_dependencies_list([ModuleName | OptDeps],
+					".opt", DepStream),
+				io__write_strings(DepStream, [
+					"\n\n", 
+					ModuleName, ".c ",
+					ModuleName, ".err ", 
+					ModuleName, ".o :"
+				]),
+				write_dependencies_list(TransOptDeps,
+					".trans_opt", DepStream)
+			;
+				get_opt_deps(LongDeps, IntermodDirs, ".opt", 
+					OptDeps),
+				write_dependencies_list([ModuleName | OptDeps],
+					".opt", DepStream)
+			)
 		;
 			[]
 		),
@@ -574,100 +626,263 @@
 		report_error(Message)
 	).
 
-	% For each dependency, search intermod_directories for a .opt
-	% file or a .m file, filtering out those for which the search fails.
-:- pred get_opt_deps(list(string)::in, list(string)::in, list(string)::in, 
-		list(string)::out, io__state::di, io__state::uo) is det.
+maybe_read_dependency_file(ModuleName, MaybeTransOptDeps) -->
+	globals__io_lookup_bool_option(transitive_optimization, TransOpt),
+	( { TransOpt = yes } ->
+		globals__io_lookup_bool_option(verbose, Verbose),
+		{ string__append(ModuleName, ".d", DependencyFileName) },
+		maybe_write_string(Verbose, "% Reading auto-dependency file `"),
+		maybe_write_string(Verbose, DependencyFileName),
+		maybe_write_string(Verbose, "'..."),
+		maybe_flush_output(Verbose),
+		io__open_input(DependencyFileName, OpenResult),
+		( { OpenResult = ok(Stream) } ->
+			io__set_input_stream(Stream, OldStream),
+			{ string__append(ModuleName, ".trans_optdate", 
+				TransOptFileName0) },
+			{ string__to_char_list(TransOptFileName0, 
+				TransOptFileName) },
+			read_dependency_file_find_start(TransOptFileName, 
+				FindResult),
+			( { FindResult = yes } ->
+				read_dependency_file_get_modules(TransOptDeps),
+				{ MaybeTransOptDeps = yes(TransOptDeps) }
+			;
+				% error reading .d file
+				{ MaybeTransOptDeps = no }
+			),
+			io__set_input_stream(OldStream, _),	
+			io__close_input(Stream)
+		;
+			{ string__append_list(["can't open file `", 
+				DependencyFileName,
+				"' for input."], Message) },
+			{ MaybeTransOptDeps = no },
+			report_error(Message)
+		),
+		maybe_write_string(Verbose, " done.\n")
+	;
+			{ MaybeTransOptDeps = no }
+	).
+			
+	% Read lines from the dependency file (module.d) until one is found
+	% which begins with TransOptFileName.
+:- pred read_dependency_file_find_start(list(char)::in, bool::out, 
+	io__state::di, io__state::uo) is det.
+read_dependency_file_find_start(TransOptFileName, Success) -->
+	io__read_line(Result),
+	( { Result = ok(CharList) } ->
+		( { list__append(TransOptFileName, _, CharList) } ->
+			% Have found the start
+			{ Success = yes }
+		;
+			read_dependency_file_find_start(TransOptFileName, 
+				Success)
+		)
+	; 
+		{ Success = no }
+	).
+		
+	% Read lines until one is found which does not contain whitespace
+	% followed by a word which ends in .trans_opt.  Remove the
+	% .trans_opt ending from all the words which are read in and return
+	% the resulting list of modules..
+:- pred read_dependency_file_get_modules(list(string)::out, io__state::di,
+	io__state::uo) is det.
+read_dependency_file_get_modules(TransOptDeps) -->
+	io__read_line(Result),
+	( 
+		{ Result = ok(CharList0) },
+		% Remove any whitespace from the beginning of the line,
+		% then take all characters until another whitespace occurs.
+		{ list__takewhile(char__is_whitespace, CharList0, _, 
+			CharList1) },
+		{ NotIsWhitespace = lambda([Char::in] is semidet, (
+			\+ char__is_whitespace(Char)
+		)) },
+		{ list__takewhile(NotIsWhitespace, CharList1, CharList, _) },
+		% Remove the ".trans_opt" suffix from the word which was
+		% read in.
+		{ list__remove_suffix(CharList, 
+			['.','t','r','a','n','s','_','o','p','t'], 
+			ModuleCharList) }
+	->
+		{ string__from_char_list(ModuleCharList, Module) },
+		read_dependency_file_get_modules(TransOptDeps0),
+		{ TransOptDeps = [ Module | TransOptDeps0 ] }
+	;
+		{ TransOptDeps = [] }
+	).
 
-get_opt_deps([], _, OptDeps, OptDeps) --> [].
-get_opt_deps([Dep | Deps], IntermodDirs, OptDeps0, OptDeps) -->
+	% get_both_opt_deps(Deps, Directories, OptDeps, TransOptDeps).
+	% For each dependency, search intermod_directories for a .m file.
+	% If it exists, add it to both output lists. Otherwise, if a .opt
+	% file exists, add it to the OptDeps list, and if a .trans_opt
+	% file exists, add it to the TransOptDeps list.
+:- pred get_both_opt_deps(list(string)::in, list(string)::in, 
+	list(string)::out, list(string)::out, 
+	io__state::di, io__state::uo) is det.
+get_both_opt_deps([], _, [], []) --> [].
+get_both_opt_deps([Dep | Deps], IntermodDirs, OptDeps, TransOptDeps) -->
 	{ string__append(Dep, ".m", DepName) },
 	search_for_file(IntermodDirs, DepName, Result1),
+	get_both_opt_deps(Deps, IntermodDirs, OptDeps0, TransOptDeps0),
 	( { Result1 = yes } ->
-		{ OptDeps1 = [Dep | OptDeps0] },
+		{ OptDeps = [Dep | OptDeps0] },
+		{ TransOptDeps = [Dep | TransOptDeps0] },
 		io__seen
 	;
 		{ string__append(Dep, ".opt", OptName) },
 		search_for_file(IntermodDirs, OptName, Result2),
 		( { Result2 = yes } ->
-			{ OptDeps1 = [Dep | OptDeps0] },
+			{ OptDeps = [Dep | OptDeps0] },
+			io__seen
+		;
+			{ OptDeps = OptDeps0 }
+		),
+		{ string__append(Dep, ".trans_opt", TransOptName) },
+		search_for_file(IntermodDirs, TransOptName, Result3),
+		( { Result3 = yes } ->
+			{ TransOptDeps = [Dep | TransOptDeps0] },
 			io__seen
 		;
-			{ OptDeps1 = OptDeps0 }
+			{ TransOptDeps = TransOptDeps0 }
 		)
-	),
-	get_opt_deps(Deps, IntermodDirs, OptDeps1, OptDeps).
+	).
+
+	% For each dependency, search intermod_directories for a .Suffix
+	% file or a .m file, filtering out those for which the search fails.
+:- pred get_opt_deps(list(string)::in, list(string)::in, string::in,
+	list(string)::out, io__state::di, io__state::uo) is det.
+get_opt_deps([], _, _, []) --> [].
+get_opt_deps([Dep | Deps], IntermodDirs, Suffix, OptDeps) -->
+	{ string__append(Dep, ".m", DepName) },
+	search_for_file(IntermodDirs, DepName, Result1),
+	get_opt_deps(Deps, IntermodDirs, Suffix, OptDeps0),
+	( { Result1 = yes } ->
+		{ OptDeps = [Dep | OptDeps0] },
+		io__seen
+	;
+		{ string__append(Dep, Suffix, OptName) },
+		search_for_file(IntermodDirs, OptName, Result2),
+		( { Result2 = yes } ->
+			{ OptDeps = [Dep | OptDeps0] },
+			io__seen
+		;
+			{ OptDeps = OptDeps0 }
+		)
+	).
 
 %-----------------------------------------------------------------------------%
 
 generate_dependencies(Module) -->
-	%
-	% first, build up a map of the dependencies (writing `.d' files as
-	% we go)
-	%
+	% first, build up a map of the dependencies.
 	{ map__init(DepsMap0) },
 	generate_deps_map([Module], DepsMap0, DepsMap),
 	%
-	% check whether we couldn't read the main `.m' file
+	% check whether we could read the main `.m' file
 	%
 	{ map__lookup(DepsMap, Module, deps(_, Error, _, _, _)) },
-	globals__io_lookup_bool_option(verbose, Verbose),
 	( { Error = fatal } ->
-	    { string__append_list(["fatal error reading module `",
-				Module, "'."], Message) },
-	    report_error(Message)
-	;
-	    %
-	    % now, write the `.dep' file
-	    %
-	    { string__append(Module, ".dep", DepFileName) },
-	    maybe_write_string(Verbose, "% Creating auto-dependency file `"),
-	    maybe_write_string(Verbose, DepFileName),
-	    maybe_write_string(Verbose, "'...\n"),
-	    io__open_output(DepFileName, DepResult),
-	    ( { DepResult = ok(DepStream) } ->
-		generate_dep_file(Module, DepsMap, DepStream),
-		io__close_output(DepStream),
-		maybe_write_string(Verbose, "% done\n")
-	    ;
-		{ string__append_list(["can't open file `", DepFileName,
-				"' for output."], DepMessage) },
-		report_error(DepMessage)
-	    ),
-	    globals__io_lookup_bool_option(generate_module_order, Order),
-	    ( { Order = yes } ->
-	  	{ string__append(Module, ".order", OrdFileName) },
+		{ string__append_list(["fatal error reading module `",
+			Module, "'."], Message) },
+		report_error(Message)
+	;
+		globals__io_lookup_accumulating_option(intermod_directories, 
+			IntermodDirs),
+		generate_dependencies_write_dep_file(Module, DepsMap),
+		{ relation__init(DepsRel0) },
+		{ map__to_assoc_list(DepsMap, DepsList) },
+		{ deps_map_to_deps_rel(DepsList, DepsMap, 
+			DepsRel0, DepsRel) },
+		{ relation__atsort(DepsRel, DepsOrdering0) },
+		maybe_output_module_order(Module, DepsOrdering0),
+		{ list__map(set__to_sorted_list, DepsOrdering0, 
+			DepsOrdering) },
+		{ list__condense(DepsOrdering, TransOptDepsOrdering0) },
+		get_opt_deps(TransOptDepsOrdering0, IntermodDirs, ".trans_opt",
+			TransOptDepsOrdering),
+		generate_dependencies_write_d_files(DepsOrdering,
+			TransOptDepsOrdering, DepsMap)
+	).
+
+:- pred maybe_output_module_order(string::in, list(set(string))::in,
+	io__state::di, io__state::uo) is det.
+maybe_output_module_order(Module, DepsOrdering) -->
+	globals__io_lookup_bool_option(generate_module_order, Order),
+	globals__io_lookup_bool_option(verbose, Verbose),
+	( { Order = yes } ->
+		{ string__append(Module, ".order", OrdFileName) },
 		maybe_write_string(Verbose, "% Creating module order file `"),
 		maybe_write_string(Verbose, OrdFileName),
 		maybe_write_string(Verbose, "'...\n"),
 		io__open_output(OrdFileName, OrdResult),
 		( { OrdResult = ok(OrdStream) } ->
-		    { relation__init(DepsRel0) },
-		    { map__to_assoc_list(DepsMap, DepsList) },
-		    { deps_map_to_deps_rel(DepsList, DepsMap, 
-				DepsRel0, DepsRel) },
-		    { relation__atsort(DepsRel, DepsOrdering) },
-		    io__write_list(OrdStream, DepsOrdering, "\n\n", 
-		    		write_module_scc(OrdStream)),
-		    io__close_output(OrdStream),
-		    maybe_write_string(Verbose, "% done\n")
-		;
-		    { string__append_list(["can't open file `", 
-				OrdFileName, "' for output."], OrdMessage) },
-		    report_error(OrdMessage)
+			io__write_list(OrdStream, DepsOrdering, "\n\n", 
+					write_module_scc(OrdStream)),
+			io__close_output(OrdStream),
+			maybe_write_string(Verbose, "% done\n")
+		;
+			{ string__append_list(["can't open file `", 
+	    			OrdFileName, "' for output."], OrdMessage) },
+			report_error(OrdMessage)
 		)
-	    ;
+	;
 		[]
-	    )
 	).
 
 :- pred write_module_scc(io__output_stream::in, set(module_name)::in,
 		io__state::di, io__state::uo) is det.
-
 write_module_scc(Stream, SCC0) -->
 	{ set__to_sorted_list(SCC0, SCC) },
 	io__write_list(Stream, SCC, "\n", io__write_string).
 
+% generate_dependencies_write_d_files(Sccs, TransOptOrder, DepsMap, IO0, IO).
+%		This predicate writes out the .d files for all the modules
+%		in the Sccs list.  
+%		Sccs is a list of lists of modules.  Each list of
+%		modules represents a set of strongly connected components
+%		of the module call graph.  
+%		TransOptOrder gives the ordering that is used to determine
+%		which other modules the .trans_opt files may depend on.
+:- pred generate_dependencies_write_d_files(list(list(string))::in, 
+	list(string)::in, deps_map::in, io__state::di, io__state::uo) is det.
+generate_dependencies_write_d_files([], _, _) --> [].
+generate_dependencies_write_d_files([Scc | Sccs], TransOptOrder, DepsMap) --> 
+	{ list__condense([Scc | Sccs], TransDeps) },
+	generate_dependencies_write_d_files_2(Scc, TransDeps, TransOptOrder,
+		DepsMap),
+	generate_dependencies_write_d_files(Sccs, TransOptOrder, DepsMap).
+
+:- pred generate_dependencies_write_d_files_2(list(string)::in, 
+	list(string)::in, list(string)::in, deps_map::in, 
+	io__state::di, io__state::uo) is det.
+generate_dependencies_write_d_files_2([], _, _TransOptOrder, _DepsMap) --> [].
+generate_dependencies_write_d_files_2([ModuleName | ModuleNames], TransDeps,
+		TransOptOrder, DepsMap) --> 
+	{ map__lookup(DepsMap, ModuleName, 
+		deps(_, Error, _IntDeps, ImplDeps, FactDeps)) },
+	
+	{ FindModule = lambda([Module::in] is semidet, ( 
+		ModuleName \= Module )) },
+	{ list__takewhile(FindModule, TransOptOrder, _, TransOptDeps0) },
+	( { TransOptDeps0 = [ _ | TransOptDeps1 ] } ->
+		% The module was found in the list
+		{ TransOptDeps = TransOptDeps1 }
+	;
+		{ TransOptDeps = [] }
+	),
+	% Note that even if a fatal error occured for one of the files that
+	% the current Module depends on, a .d file is still produced, even
+	% though it probably contains incorrect information.
+	( { Error \= fatal } ->
+		write_dependency_file(ModuleName, ImplDeps, TransDeps,
+			FactDeps, yes(TransOptDeps))
+	;
+		[]
+	),
+	generate_dependencies_write_d_files_2(ModuleNames, TransDeps,
+		TransOptOrder, DepsMap).
 
 % This is the data structure we use to record the dependencies.
 % We keep a map from module name to information about the module.
@@ -685,8 +900,6 @@
 	% (Module1 deps_rel Module2) means Module1 is imported by Module2.
 :- type deps_rel == relation(string).
 
-% This is the predicate which creates the above data structure.
-
 :- pred generate_deps_map(list(string), deps_map, deps_map,
 			io__state, io__state).
 :- mode generate_deps_map(in, in, out, di, uo) is det.
@@ -697,31 +910,20 @@
 		% it has been processed yet.
 	lookup_dependencies(Module, DepsMap0, no, Done, Error, IntDeps, 
 				ImplDeps, FactDeps, DepsMap1),
-		% If the module hadn't been processed yet, compute its
-		% transitive dependencies (we already know its primary ones),
-		% (1) output this module's dependencies to its `.d' file
-		% (if the `.m' file exists), (2) add its imports to the list of
-		% dependencies we need to generate, and (3) mark it as having
-		% been processed.
+		% If the module hadn't been processed yet, then add its
+		% imports to the list of dependencies we need to generate
+		% and mark it as having been processed.
 	( { Done = no } ->
 		{ map__set(DepsMap1, Module,
 			deps(yes, Error, IntDeps, ImplDeps, FactDeps), 
-			DepsMap2) },
-		transitive_dependencies(ImplDeps, DepsMap2, no, SecondaryDeps,
-			DepsMap3),
-		( { Error \= fatal } ->
-			write_dependency_file(Module, ImplDeps, SecondaryDeps,
-			FactDeps)
-		;
-			[]
-		),
-		{ list__append(ImplDeps, Modules, Modules2) }
+				DepsMap2) },
+		{ list__append(ImplDeps, Modules, Modules1) }
 	;
-		{ DepsMap3 = DepsMap1 },
-		{ Modules2 = Modules }
+		{ DepsMap2 = DepsMap1 },
+		{ Modules1 = Modules }
 	),
 		% Recursively process the remaining modules
-	generate_deps_map(Modules2, DepsMap3, DepsMap).
+	generate_deps_map(Modules1, DepsMap2, DepsMap).
 
 
 	% Construct a dependency relation of all the modules in the program.
@@ -738,8 +940,8 @@
 		    lambda([Dep::in, Relation0::in, Relation::out] is det, (
 			relation__add_element(Relation0, Dep,
 				DepRelKey, Relation1),
-			relation__add(Relation1, DepRelKey,
-				ModuleRelKey, Relation)
+			relation__add(Relation1, ModuleRelKey,
+				DepRelKey, Relation)
 		    )),
 		list__foldl(AddDeps, IntDeps, Rel1, Rel2),
 		list__foldl(AddDeps, ImplDeps, Rel2, Rel3)
@@ -748,8 +950,28 @@
 	),
 	deps_map_to_deps_rel(DepsList, DepsMap, Rel3, Rel).
 
-% Write out the `.dep' file, using the information collected in the
-% deps_map data structure.
+%-----------------------------------------------------------------------------%
+	% Write out the `.dep' file, using the information collected in the
+	% deps_map data structure.
+:- pred generate_dependencies_write_dep_file(string::in, deps_map::in, 
+	io__state::di, io__state::uo) is det.
+generate_dependencies_write_dep_file(Module, DepsMap) -->
+	globals__io_lookup_bool_option(verbose, Verbose),
+	{ string__append(Module, ".dep", DepFileName) },
+	maybe_write_string(Verbose, "% Creating auto-dependency file `"),
+	maybe_write_string(Verbose, DepFileName),
+	maybe_write_string(Verbose, "'...\n"),
+	io__open_output(DepFileName, DepResult),
+	( { DepResult = ok(DepStream) } ->
+		generate_dep_file(Module, DepsMap, DepStream),
+		io__close_output(DepStream),
+		maybe_write_string(Verbose, "% done\n")
+	;
+		{ string__append_list(["can't open file `", DepFileName,
+			"' for output."], DepMessage) },
+		report_error(DepMessage)
+	).
+
 
 :- pred generate_dep_file(string, deps_map, io__output_stream,
 			io__state, io__state).
@@ -1120,81 +1342,6 @@
 
 %-----------------------------------------------------------------------------%
 
-	% Given a list of modules, return a list of those modules
-	% and all their transitive interface dependencies.
-
-:- pred transitive_dependencies(list(string), deps_map, bool, list(string), 
-				deps_map, io__state, io__state).
-:- mode transitive_dependencies(in, in, in, out, out, di, uo) is det.
-
-transitive_dependencies(Modules, DepsMap0, Search, Dependencies, DepsMap) -->
-	{ set__init(Dependencies0) },
-	transitive_dependencies_2(Modules, Dependencies0, DepsMap0, Search,
-		Dependencies1, DepsMap),
-	{ set__to_sorted_list(Dependencies1, Dependencies) }.
-
-:- pred transitive_dependencies_2(list(string), set(string), deps_map, bool,
-				set(string), deps_map,
-				io__state, io__state).
-:- mode transitive_dependencies_2(in, in, in, in, out, out, di, uo) is det.
-
-transitive_dependencies_2([], Deps, DepsMap, _Search, Deps, DepsMap) --> [].
-transitive_dependencies_2([Module | Modules0], Deps0, DepsMap0, Search, Deps, 
-		DepsMap)
-		-->
-	( { set__member(Module, Deps0) } ->
-		{ Deps1 = Deps0 },
-		{ DepsMap1 = DepsMap0 },
-		{ Modules1 = Modules0 }
-	;
-		{ set__insert(Deps0, Module, Deps1) },
-		lookup_dependencies(Module, DepsMap0, Search, _, _, 
-			IntDeps, _ImplDeps, _FactDeps, DepsMap1),
-		{ list__append(IntDeps, Modules0, Modules1) }
-	),
-	transitive_dependencies_2(Modules1, Deps1, DepsMap1, Search, Deps, 
-		DepsMap).
-
-%-----------------------------------------------------------------------------%
-
-        % Given a list of modules, return a list of those modules
-        % and all their transitive implementation dependencies.
-
-:- pred trans_impl_dependencies(list(string), deps_map, bool,
-                        list(string), deps_map, io__state, io__state).
-:- mode trans_impl_dependencies(in, in, in, out, out, di, uo) is det.
-
-trans_impl_dependencies(Modules, DepsMap0, Search, Dependencies, DepsMap) -->
-        { set__init(Dependencies0) },
-        trans_impl_dependencies_2(Modules, Dependencies0, DepsMap0, Search,
-                Dependencies1, DepsMap),
-        { set__to_sorted_list(Dependencies1, Dependencies) }.
-
-:- pred trans_impl_dependencies_2(list(string), set(string), deps_map, bool,
-                                set(string), deps_map,
-                                io__state, io__state).
-:- mode trans_impl_dependencies_2(in, in, in, in, out, out, di, uo) is det.
-
-trans_impl_dependencies_2([], Deps, DepsMap, _Search, Deps, DepsMap) --> [].
-trans_impl_dependencies_2([Module | Modules0], Deps0, DepsMap0, Search, Deps,
-                DepsMap)
-                -->
-        ( { set__member(Module, Deps0) } ->
-                { Deps1 = Deps0 },
-                { DepsMap1 = DepsMap0 },
-                { Modules2 = Modules0 }
-        ;
-                { set__insert(Deps0, Module, Deps1) },
-                lookup_dependencies(Module, DepsMap0, Search, _, _, IntDeps, 
-                	ImplDeps, _FactDeps, DepsMap1),
-                { list__append(IntDeps, Modules0, Modules1) },
-                { list__append(ImplDeps, Modules1, Modules2) }
-        ),
-        trans_impl_dependencies_2(Modules2, Deps1, DepsMap1, Search, Deps,
-                DepsMap).
-
-%-----------------------------------------------------------------------------%
-
 	% Look up a module in the dependency map
 	% If we don't know its dependencies, read the
 	% module and save the dependencies in the dependency map.
@@ -1206,8 +1353,7 @@
 		di, uo) is det.
 
 lookup_dependencies(Module, DepsMap0, Search, Done, Error, IntDeps, 
-		ImplDeps, FactDeps, DepsMap)
-		-->
+		ImplDeps, FactDeps, DepsMap) -->
 	(
 		{ map__search(DepsMap0, Module,
 			deps(Done0, Error0, IntDeps0, ImplDeps0, FactDeps0)) }
@@ -1220,7 +1366,7 @@
 		{ DepsMap = DepsMap0 }
 	;
 		read_dependencies(Module, Search, IntDeps, ImplDeps, FactDeps, 
-				Error),
+			Error),
 		{ map__det_insert(DepsMap0, Module, 
 		    deps(no, Error, IntDeps, ImplDeps, FactDeps), DepsMap) },
 		{ Done = no }
Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.217
diff -u -r1.217 options.m
--- 1.217	1998/01/05 08:40:28
+++ options.m	1998/01/06 22:52:39
@@ -55,6 +55,7 @@
 		;	warn_unused_args
 		;	warn_interface_imports
 		;	warn_missing_opt_files
+		;	warn_missing_trans_opt_deps
 		;	warn_non_stratification
 		;	warn_simple_code
 		;	warn_duplicate_calls
@@ -303,6 +304,7 @@
 	warn_interface_imports	-	bool(yes),
 	warn_non_stratification -	bool(no),
 	warn_missing_opt_files  -	bool(yes),
+	warn_missing_trans_opt_deps  -	bool(yes),
 	warn_simple_code	-	bool(yes),
 	warn_duplicate_calls	-	bool(no),
 	warn_missing_module_name -	bool(yes),
@@ -593,6 +595,7 @@
 long_option("warn-interface-imports",	warn_interface_imports).
 long_option("warn-non-stratification",	warn_non_stratification).
 long_option("warn-missing-opt-files",	warn_missing_opt_files).
+long_option("warn-missing-trans-opt-deps",	warn_missing_trans_opt_deps).
 long_option("warn-simple-code",		warn_simple_code).
 long_option("warn-duplicate-calls",	warn_duplicate_calls).
 long_option("warn-missing-module-name",	warn_missing_module_name).
@@ -918,6 +921,7 @@
 			warn_nothing_exported	-	bool(Enable),
 			warn_interface_imports	-	bool(Enable),
 			warn_missing_opt_files	-	bool(Enable),
+			warn_missing_trans_opt_deps -	bool(Enable),
 			warn_simple_code	-	bool(Enable),
 			warn_missing_module_name -	bool(Enable),
 			warn_wrong_module_name	-	bool(Enable)
@@ -1153,8 +1157,14 @@
 	io__write_string("\t--warn-interface-imports\n"),
 	io__write_string("\t\tWarn about modules imported in the interface, but\n"),
 	io__write_string("\t\twhich are not used in the interface.\n"),
-	io__write_string("\t--warn-missing-opt-files\n"),
-	io__write_string("\t\tWarn about `.opt' files which cannot be opened.\n"),
+	io__write_string("\t--no-warn-missing-opt-files\n"),
+	io__write_string("\t\tDisable warnings about `.opt' files which cannot be opened.\n"),
+	io__write_string("\t--no-warn-missing-trans-opt-deps\n"),
+	io__write_string("\t\tDisable warnings produced when the information required\n"),
+	io__write_string("\t\tto allow `.trans_opt' files to be read when creating other\n"),
+	io__write_string("\t\t`.trans_opt' files has been lost.  The information can be\n"),
+	io__write_string("\t\trecreated by running `mmake <mainmodule>.depend'\n"),
+
 	io__write_string("\t--warn-non-stratification\n"),
 	io__write_string("\t\tWarn about possible non-stratification in the module.\n"),
 	io__write_string("\t\tNon-stratification occurs when a predicate/function can call\n"),
@@ -1216,7 +1226,6 @@
 	io__write_string("\t\tOutput the strongly connected components of the module\n"),
 	io__write_string("\t\tdependency graph in top-down order to `<module>.order'.\n"),
 	io__write_string("\t\tImplies --generate-dependencies.\n"),
-
 	io__write_string("\t-i, --make-int, --make-interface\n"),
 	io__write_string("\t\tWrite the module interface to `<module>.int',\n"),
 	io__write_string("\t\tand write the short interface to `<module>.int2'\n"),
@@ -1228,10 +1237,10 @@
 	io__write_string("\t\tWrite inter-module optimization information to\n"),
 	io__write_string("\t\t`<module>.opt'.\n"),
 	io__write_string("\t\tThis option should only be used by mmake.\n"),
-%	io__write_string("\t--make-transitive-optimization-interface\n"),
-%	io__write_string("\t--make-trans-opt\n"),
-%	io__write_string("\t\tOutput transitive optimization information\n"),
-%	io__write_string("\t\tinto the <module>.trans_opt file.\n"),
+	io__write_string("\t--make-trans-opt\n"),
+	io__write_string("\t--make-transitive-optimization-interface\n"),
+	io__write_string("\t\tOutput transitive optimization information\n"),
+	io__write_string("\t\tinto the `<module>.trans_opt' file.\n"),
 	io__write_string("\t-G, --convert-to-goedel\n"),
 	io__write_string("\t\tConvert to Goedel. Output to file `<module>.loc'.\n"),
 	io__write_string("\t\tNote that some Mercury language constructs cannot\n"),
@@ -1545,10 +1554,10 @@
 	io__write_string("\t\tPerform inlining and higher-order specialization of\n"),
 	io__write_string("\t\tthe code for predicates imported from other modules.\n"),
 	io__write_string("\t\tThis option must be set throughout the compilation process.\n"),
-%	io__write_string("\t--trans-intermod-opt\n"),
-%	io__write_string("\t--transitive-intermodule-optimization\n"),
-%	io__write_string("\t\tImport the transitive intermodule optimization data.\n"),
-%	io__write_string("\t\tThis data is imported from <module>.trans_opt files.\n"),
+	io__write_string("\t--trans-intermod-opt\n"),
+	io__write_string("\t--transitive-intermodule-optimization\n"),
+	io__write_string("\t\tImport the transitive intermodule optimization data.\n"),
+	io__write_string("\t\tThis data is imported from `<module>.trans_opt' files.\n"),
 	io__write_string("\t--enable-term, --enable-termination\n"),
 	io__write_string("\t\tAnalyse each predicate to discover if it terminates.\n"),
 	io__write_string("\t--chk-term, --check-term, --check-termination\n"),
Index: compiler/trans_opt.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/trans_opt.m,v
retrieving revision 1.3
diff -u -r1.3 trans_opt.m
--- 1.3	1997/12/22 09:56:37
+++ trans_opt.m	1998/01/06 23:34:55
@@ -1,5 +1,5 @@
 %-----------------------------------------------------------------------------%
-% Copyright (C) 1997 The University of Melbourne.
+% Copyright (C) 1997-1998 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.
 %-----------------------------------------------------------------------------%
@@ -15,30 +15,19 @@
 % other .trans_opt files introduces the possibility of circular
 % dependencies occuring. These circular dependencies would occur if the
 % data in A.trans_opt depended on the data in B.trans_opt being correct,
-% and vice-versa.  Before .trans_opt files can be used safely, a system
-% will need to be implemented to ensure that circular dependencies cannot
-% occur.  The best way to do this has not yet been decided upon, but here
-% are some possibilities:
-% 1 - Have mmc <module>.depend output a .order file.  This file would
-%     contain a list of all the modules in the current program, sorted
-%     topologically.  As a result, any module may import a .trans_opt file
-%     from another module if and only if that other module appears after
-%     the current module in the .order file.  This solution has the
-%     advantage that it is quite simple to implement (in fact Simon Taylor
-%     has already implemented it).  Unfortunatly, it has some problems.
-%     Firstly, when module dependencies change, the .order file is not
-%     modified until mmc <module>.depend is run again.  Secondly, some
-%     modules are only imported for types.  It would be better if these
-%     dependencies were not considered, but this would make it quite
-%     difficult to create the .order file. Thirdly, it is not clear how to
-%     handle the situation where one module is used by two different
-%     programs, and if the dependencies of that module changes between when
-%     mmc <module>.depend is run on each program.
-%
-% 2 - Have a system where the dependencies can be modified each time 
-%     compiler is run.  This causes all sorts of problems when considering
-%     the effect of parallel makes.
+% and vice-versa.  
 %
+% The following system is used to ensure that circular dependencies cannot
+% occur:
+% 	When mmake <module>.depend is run, mmc calculates a suitable
+% 	ordering.  This ordering is then used to create each of the .d
+% 	files.  This allows make to ensure that all necessary trans_opt
+% 	files are up to date before creating any other trans_opt files.
+% 	This same information is used by mmc to decide which trans_opt
+% 	files may be imported when creating another .trans_opt file.  By
+% 	observing the ordering decided upon when mmake module.depend was
+% 	run, any circularities which may have been created are avoided.
+%
 % This module writes out the interface for transitive intermodule optimization.
 % The .trans_opt file includes:
 %	- pragma termination_info declarations for all exported preds
@@ -72,11 +61,13 @@
 :- pred trans_opt__write_optfile(module_info, io__state, io__state).
 :- mode trans_opt__write_optfile(in, di, uo) is det.
 
-	% Add the items from the .trans_opt files of imported modules to
-	% the items for this module.
-:- pred trans_opt__grab_optfiles(module_imports, module_imports, bool,
-				io__state, io__state).
-:- mode trans_opt__grab_optfiles(in, out, out, di, uo) is det.
+	% trans_opt__grab_optfiles(ModuleImports0, ModuleList, ModuleImports, 
+	% 	Error, IO0, IO).
+	% Add the items from each of the modules in ModuleList.trans_opt to
+	% the items in ModuleImports.
+:- pred trans_opt__grab_optfiles(module_imports, list(string), 
+	module_imports, bool, io__state, io__state).
+:- mode trans_opt__grab_optfiles(in, in, out, out, di, uo) is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -183,17 +174,20 @@
 %-----------------------------------------------------------------------------%
 	% Read in and process the transitive optimization interfaces.
 
-trans_opt__grab_optfiles(Module0, Module, FoundError) -->
+trans_opt__grab_optfiles(Module0, TransOptDeps, Module, FoundError) -->
+	globals__io_lookup_bool_option(verbose, Verbose),
+	maybe_write_string(Verbose, "% Reading .trans_opt files..\n"),
+	maybe_flush_output(Verbose),
 	{ Module0 = module_imports(ModuleName, DirectImports0,
 		IndirectImports0, Items0, _) },
-	{ list__sort_and_remove_dups(DirectImports0, Imports) },
-	read_trans_opt_files(Imports, [], OptItems, no, FoundError),
+	read_trans_opt_files(TransOptDeps, [], OptItems, no, FoundError),
 	{ term__context_init(Context) },
 	{ varset__init(Varset) },
 	{ OptDefn = module_defn(Varset, opt_imported) - Context },
 	{ list__append(Items0, [ OptDefn | OptItems ], Items) },
 	{ Module = module_imports(ModuleName, DirectImports0, 
-		IndirectImports0, Items, no) }.
+		IndirectImports0, Items, no) },
+	maybe_write_string(Verbose, "% Done.\n").
 
 :- pred read_trans_opt_files(list(module_name), item_list,
 	item_list, bool, bool, io__state, io__state).
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.112
diff -u -r1.112 user_guide.texi
--- 1.112	1998/01/05 08:40:38
+++ user_guide.texi	1998/01/06 22:53:47
@@ -136,9 +136,9 @@
 interface files used in inter-module optimization,
 and are created using the @samp{--make-optimization-interface}
 (or @samp{--make-opt-int}) option.
- at c Files ending in @file{.trans_opt} are interface files used in
- at c transitive inter-module optimization, and are created using the
- at c @samp{--make-transitive-optimization-interface} option.
+Files ending in @file{.trans_opt} are interface files used in
+transitive inter-module optimization, and are created using the
+ at samp{--make-transitive-optimization-interface} option.
 
 Since the interface of a module changes less often than its implementation,
 the @file{.int}, @file{.int2}, @file{.int3}, and @file{.opt}
@@ -219,13 +219,13 @@
 mmc --make-opt-int @var{module1}.m @var{module2}.m ...
 @end example
 
- at c If you are going to compile with @samp{--transitive-intermodule-optimization}
- at c enabled, then you also need to create the transitive optimization files.
+If you are going to compile with @samp{--transitive-intermodule-optimization}
+enabled, then you also need to create the transitive optimization files.
 
- at c @example
- at c mmc -make-trans-opt @var{module1}.m @var{module2}.m ...
- at c @end example
- at c
+ at example
+mmc --make-trans-opt @var{module1}.m @var{module2}.m ...
+ at end example
+
 Given that you have made all the interface files,
 one way to create an executable for a multi-module program
 is to compile all the modules at the same time
@@ -808,7 +808,7 @@
 In addition to the files removed by @var{main-module}.clean, this
 removes the @samp{.date}, @samp{.int}, @samp{.int2}, @samp{.int3},
 @samp{.opt}, @samp{.optdate}, @samp{.date3},
- at c @samp{.trans_opt}, @samp{.trans_optdate},
+ at samp{.trans_opt}, @samp{.trans_optdate},
 @samp{.d}, and @samp{.dep} belonging to one of the modules of the program,
 and also the various possible executables for the program ---
 @samp{@var{main-module}},
@@ -1572,17 +1572,17 @@
 Write information used for inter-module optimization to
 @file{@var{module}.opt}.
 
- at c @sp 1
- at c @item --make-transitive-optimization-interface
- at c @itemx --make-trans-opt
- at c Write the @file{@var{module}.trans_opt} file.  This file is used to store
- at c information used for inter-module optimization. The information is read
- at c in when the compiler is invoked with the @samp{--transitive-optimization}
- at c option.  The file is called ``transitive'' because a
- at c @file{@var{module}.trans_opt} file may depend on other
- at c @file{@var{module}.trans_opt} files.
- at c
 @sp 1
+ at item --make-trans-opt
+ at itemx --make-transitive-optimization-interface
+Write the @file{@var{module}.trans_opt} file.  This file is used to store
+information used for inter-module optimization. The information is read
+in when the compiler is invoked with the @samp{--transitive-optimization}
+option.  The file is called ``transitive'' because a
+ at file{@var{module}.trans_opt} file may depend on other
+ at file{@var{module}.trans_opt} files.
+
+ at sp 1
 @item -G
 @itemx --convert-to-goedel
 Convert the Mercury code to Goedel. Output to file @file{@var{module}.loc}.
@@ -2118,19 +2118,19 @@
 Perform inlining and higher-order specialization of the code for
 predicates or functions imported from other modules.
 
- at c @sp 1
- at c @item --transitive-intermodule-optimization
- at c @item --trans-intermod-opt
- at c Use the information stored in other @file{@var{module}.trans_opt} files
- at c to make intermodule optimizations.  The @file{@var{module}.trans_opt} is
- at c different to the @file{@var{module}.opt} as @file{@var{module}.trans_opt}
- at c files may depend on other @file{@var{module}.trans_opt} files.
- at c @file{@var{module}.opt} files may only depend on the
- at c @file{@var{module}.m} file.
- at c
+ at sp 1
+ at item --trans-intermod-opt
+ at itemx --transitive-intermodule-optimization
+Use the information stored in other @file{@var{module}.trans_opt} files
+to make intermodule optimizations.  The @file{@var{module}.trans_opt} is
+different to the @file{@var{module}.opt} as @file{@var{module}.trans_opt}
+files may depend on other @file{@var{module}.trans_opt} files.
+ at file{@var{module}.opt} files may only depend on the
+ at file{@var{module}.m} file.
+
 @sp 1
- at itemx --enable-term
- at item --enable-termination
+ at item --enable-term
+ at itemx --enable-termination
 Enable termination analysis.  Termination analysis analyses each mode of
 each predicate to see whether it terminates.  @samp{pragma terminates},
 @samp{pragma does_not_terminate} and @samp{pragma check_termination}



More information about the developers mailing list