[m-rev.] for review: GCC back-end: support nested modules

Fergus Henderson fjh at cs.mu.OZ.AU
Thu May 10 21:40:29 AEST 2001


On 09-May-2001, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> Support nested modules in the GCC back-end.
> (TO DO: Mmake support for nested modules is still not yet implemented.)

The diff that I posted had a bug where it was not correctly handling files
where the file name didn't match the fully-qualified module name.
The relative diff below fixes that.

I'll go ahead and commit this change now.

diff -u mercury_compile.m mercury_compile.m
--- mercury_compile.m
+++ mercury_compile.m
@@ -128,48 +128,7 @@
 	; { Args = [], FileNamesFromStdin = no } ->
 		usage
 	;
-		% Because of limitations in the GCC back-end,
-		% we can only call the GCC back-end once (per process),
-		% to generate a single assembler file, rather than
-		% calling it multiple times to generate individual
-		% assembler files for each module.
-		% So if we're generating code using the GCC back-end,
-		% we need to call run_gcc_backend here at the top level.
-		globals__io_get_globals(Globals),
-		(
-			{ compiling_to_asm(Globals) },
-			{ Args = [FirstArg | _] }
-		->
-			% The name of the assembler file that we generate
-			% is based on the first argument.
-			{ string__remove_suffix(FirstArg, ".m", ArgBase) ->
-				file_name_to_module_name(ArgBase,
-					FirstModuleName)
-			;
-				file_name_to_module_name(FirstArg,
-					FirstModuleName)
-			},
-			% Invoke run_gcc_backend.  It will call us back,
-			% and then we'll continue with the normal work of
-			% the compilation, which will be done by the callback
-			% function (`process_args').
-			maybe_mlds_to_gcc__run_gcc_backend(FirstModuleName,
-				process_args(Args), ModulesToLink),
-			% Invoke the assembler to produce an object file.
-			module_name_to_file_name(FirstModuleName, ".s", no,
-				AsmFile),
-			object_extension(Obj),
-			module_name_to_file_name(FirstModuleName, Obj, yes,
-				O_File),
-			mercury_compile__asm_to_obj(
-				AsmFile, O_File, _AssembleOK)
-		;
-			% If we're NOT using the GCC back-end,
-			% then we can just call process_args directly,
-			% rather than via GCC.
-			process_args(Args, ModulesToLink)
-		),
-
+		process_all_args(Args, ModulesToLink),
 		io__get_exit_status(ExitStatus),
 		( { ExitStatus = 0 } ->
 			( { Link = yes } ->
@@ -199,6 +158,103 @@
 		)
 	).
 
+:- pred process_all_args(list(string), list(string), io__state, io__state).
+:- mode process_all_args(in, out, di, uo) is det.
+
+process_all_args(Args, ModulesToLink) -->
+	% Because of limitations in the GCC back-end,
+	% we can only call the GCC back-end once (per process),
+	% to generate a single assembler file, rather than
+	% calling it multiple times to generate individual
+	% assembler files for each module.
+	% So if we're generating code using the GCC back-end,
+	% we need to call run_gcc_backend here at the top level.
+	globals__io_get_globals(Globals),
+	(
+		{ compiling_to_asm(Globals) },
+		{ Args = [FirstArg | _] }
+	->
+		% The name of the assembler file that we generate
+		% is based on name of the first module named
+		% on the command line.  (Mmake requires this.)
+		%
+		% There's two cases:
+		% (1) If the argument ends in ".m", we assume
+		% that the argument is a file name.
+		% To find the corresponding module name,
+		% we would need to read in the file
+		% (at least up to the first item);
+		% this is needed to handle the case where
+		% the module name does not match the file
+		% name, e.g. file "browse.m" containing
+		% ":- module mdb__browse." as its first item.
+		% Rather than reading in the source file here,
+		% we just pick a name
+		% for the asm file based on the file name argument,
+		% (e.g. "browse.s") and if necessary rename it later
+		% (e.g. to "mdb.browse.s").
+		%
+		% (2) If the argument doesn't end in `.m',
+		% then we assume it is a module name.
+		% (Is it worth checking that the name doesn't
+		% contain directory seperators, and issuing
+		% a warning or error in that case?)
+		%
+		{ string__remove_suffix(FirstArg, ".m", ArgBase) ->
+			file_name_to_module_name(ArgBase,
+				FirstModuleName)
+		;
+			file_name_to_module_name(FirstArg,
+				FirstModuleName)
+		},
+
+		% Invoke run_gcc_backend.  It will call us back,
+		% and then we'll continue with the normal work of
+		% the compilation, which will be done by the callback
+		% function (`process_args').
+		maybe_mlds_to_gcc__run_gcc_backend(FirstModuleName,
+			process_args(Args), ModulesToLink),
+
+		% Now we know what the real module name was, so we
+		% can rename the assembler file if needed (see above).
+		( { ModulesToLink = [Module | _] } ->
+			{ file_name_to_module_name(Module, ModuleName) }
+		;
+			{ error("main_2: no modules") }
+		),
+		globals__io_lookup_bool_option(pic, Pic),
+		{ AsmExt = (Pic = yes -> ".pic_s" ; ".s") },
+		module_name_to_file_name(ModuleName, AsmExt, no, AsmFile),
+		(
+			{ ModuleName \= FirstModuleName }
+		->
+			module_name_to_file_name(FirstModuleName, AsmExt,
+				no, FirstAsmFile),
+			do_rename_file(FirstAsmFile, AsmFile, Result)
+		;
+			{ Result = ok }
+		),
+
+		% Invoke the assembler to produce an object file,
+		% if needed.
+		globals__io_lookup_bool_option(target_code_only, 
+				TargetCodeOnly),
+		( { Result = ok, TargetCodeOnly = no } ->
+			object_extension(Obj),
+			module_name_to_file_name(ModuleName, Obj,
+				yes, O_File),
+			mercury_compile__asm_to_obj(
+				AsmFile, O_File, _AssembleOK)
+		;
+			[]
+		)
+	;
+		% If we're NOT using the GCC back-end,
+		% then we can just call process_args directly,
+		% rather than via GCC.
+		process_args(Args, ModulesToLink)
+	).
+
 :- pred compiling_to_asm(globals::in) is semidet.
 compiling_to_asm(Globals) :-
 	globals__get_target(Globals, asm),
@@ -214,6 +270,69 @@
 		globals__lookup_bool_option(Globals, Opt, Bool)),
 		OptionList),
 	bool__or_list(BoolList) = no.
+
+:- pred do_rename_file(string::in, string::in, io__res::out,
+		io__state::di, io__state::uo) is det.
+
+do_rename_file(OldFileName, NewFileName, Result) -->
+	globals__io_lookup_bool_option(verbose, Verbose),
+	globals__io_lookup_bool_option(very_verbose, VeryVerbose),
+	maybe_write_string(Verbose, "% Renaming `"),
+	maybe_write_string(Verbose, OldFileName),
+	maybe_write_string(Verbose, "' as `"),
+	maybe_write_string(Verbose, NewFileName),
+	maybe_write_string(Verbose, "'..."),
+	maybe_flush_output(Verbose),
+	io__rename_file(OldFileName, NewFileName, Result0),
+	( { Result0 = error(Error0) } ->
+		maybe_write_string(VeryVerbose, " failed.\n"),
+		maybe_flush_output(VeryVerbose),
+		{ io__error_message(Error0, ErrorMsg0) },
+		% On some systems, we need to remove the existing file
+		% first, if any.  So try again that way.
+		maybe_write_string(VeryVerbose, "% Removing `"),
+		maybe_write_string(VeryVerbose, OldFileName),
+		maybe_write_string(VeryVerbose, "'..."),
+		maybe_flush_output(VeryVerbose),
+		io__remove_file(NewFileName, Result1),
+		( { Result1 = error(Error1) } ->
+			maybe_write_string(Verbose, " failed.\n"),
+			maybe_flush_output(Verbose),
+			{ io__error_message(Error1, ErrorMsg1) },
+			{ string__append_list(["can't rename file `",
+				OldFileName, "' as `", NewFileName, "': ",
+				ErrorMsg0, "; and can't remove file `",
+				NewFileName, "': ", ErrorMsg1], Message) },
+			report_error(Message),
+			{ Result = Result1 }
+		;
+			maybe_write_string(VeryVerbose, " done.\n"),
+			maybe_write_string(VeryVerbose, "% Renaming `"),
+			maybe_write_string(VeryVerbose, OldFileName),
+			maybe_write_string(VeryVerbose, "' as `"),
+			maybe_write_string(VeryVerbose, NewFileName),
+			maybe_write_string(VeryVerbose, "' again..."),
+			maybe_flush_output(VeryVerbose),
+			io__rename_file(OldFileName, NewFileName, Result2),
+			( { Result2 = error(Error2) } ->
+				maybe_write_string(Verbose,
+					" failed.\n"),
+				maybe_flush_output(Verbose),
+				{ io__error_message(Error2, ErrorMsg) },
+				{ string__append_list(
+					["can't rename file `", OldFileName,
+					"' as `", NewFileName, "': ",
+					ErrorMsg], Message) },
+				report_error(Message)
+			;
+				maybe_write_string(Verbose, " done.\n")
+			),
+			{ Result = Result2 }
+		)
+	;
+		maybe_write_string(Verbose, " done.\n"),
+		{ Result = Result0 }
+	).
 
 :- pred process_args(list(string), list(string), io__state, io__state).
 :- mode process_args(in, out, di, uo) is det.
diff -u mlds_to_gcc.m mlds_to_gcc.m
--- mlds_to_gcc.m
+++ mlds_to_gcc.m
@@ -207,6 +207,7 @@
 	maybe_write_string(Verbose, "% Invoking GCC back-end as `"),
 	maybe_write_string(Verbose, CommandLine),
 	maybe_write_string(Verbose, "':\n"),
+	maybe_flush_output(Verbose),
 	gcc__run_backend(CommandLine, Result, CallBack, CallBackOutput),
 	( { Result \= 0 } ->
 		report_error("GCC back-end failed!\n")
-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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