[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