[m-rev.] for review: fix library intialisers / finalisers
Julien Fischer
juliensf at cs.mu.OZ.AU
Tue May 16 16:51:43 AEST 2006
For review by Zoltan.
Estimated hours taken: 7
Branches: main, release
Fix the bug with initialisers/finalisers in libraries not being called (and as
a consequence also fixes the bugs with mutables not being given their correct
initial values. The problem was that the directives necessary to call them
were not being included in the libraries' .init file.
The fix is to add a new mode of operation to mkinit that given a list of .c
files that make up some Mercury library, constructs the .init file for that
library. In particular, it now constructs the .init file so that it contains
any REQUIRED_{INIT,FINAL} directives needed by the library. The new mode of
operation is invoked when mkinit is given the `-k' option.
Modify the build systems (i.e. mmake and mmc --make) to conform to the above
change.
util/mkinit.c:
Add a new mode of operation, `-k'. When invoked with this
option mkinit will read a list of .c files and emit a sequence of
INIT, REQUIRED_INIT and REQUIRED_FINAL directives to stdout,
corresponding to INIT, REQUIRED_INIT and REQUIRED_FINAL comments
in the .c files.
compiler/modules.m:
Change the rule mmake uses to build .init files so that it calls
mkinit -k on all the .c files generated for the library.
scripts/Mmake.vars.in:
Add a new mmake variable MKLIBINIT. This is the program used to
create .init files. (It will nearly always be mkinit.)
compiler/compile_target_code.m:
Change how .init files are built. We now have to call mkinit -k to
scan all of the .c files to write out the correct set of INIT,
REQUIRED_INIT and REQUIRED_FINAL directives. The code here is
that used by mmc --make for creating the .init files.
compiler/make.program_target.m:
Build the .init file after building the .c files, since building
it before will no longer work.
Julien.
Index: compiler/compile_target_code.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/compile_target_code.m,v
retrieving revision 1.86
diff -u -r1.86 compile_target_code.m
--- compiler/compile_target_code.m 12 May 2006 04:32:03 -0000 1.86
+++ compiler/compile_target_code.m 16 May 2006 03:51:35 -0000
@@ -866,18 +866,39 @@
io.open_output(TmpInitFileName, InitFileRes, !IO),
(
InitFileRes = ok(InitFileStream),
- list.foldl(make_init_file(InitFileStream), AllModules, !IO),
- globals.io_lookup_maybe_string_option(extra_init_command,
- MaybeInitFileCommand, !IO),
- (
- MaybeInitFileCommand = yes(InitFileCommand),
- make_all_module_command(InitFileCommand, MainModuleName,
- AllModules, CommandString, !IO),
- invoke_system_command(InitFileStream, verbose_commands,
- CommandString, Succeeded0, !IO)
+ ModuleNameToCFileName =
+ (pred(ThisModule::in, CFileName::out, !.IO::di, !:IO::uo) is det :-
+ module_name_to_file_name(ThisModule, ".c", no, CFileName, !IO)
+ ),
+ list.map_foldl(ModuleNameToCFileName, AllModules, AllCFilesList, !IO),
+ join_quoted_string_list(AllCFilesList, "", "", " ", CFileNames),
+
+ globals.io_lookup_string_option(mkinit_command, MkInit, !IO),
+ MkInitCmd = string.append_list(
+ [ MkInit,
+ " -k ",
+ " ", CFileNames
+ ]),
+ invoke_system_command(InitFileStream, verbose, MkInitCmd, MkInitOK,
+ !IO),
+
+ (
+ MkInitOK = yes,
+ globals.io_lookup_maybe_string_option(extra_init_command,
+ MaybeInitFileCommand, !IO),
+ (
+ MaybeInitFileCommand = yes(InitFileCommand),
+ make_all_module_command(InitFileCommand, MainModuleName,
+ AllModules, CommandString, !IO),
+ invoke_system_command(InitFileStream, verbose_commands,
+ CommandString, Succeeded0, !IO)
+ ;
+ MaybeInitFileCommand = no,
+ Succeeded0 = yes
+ )
;
- MaybeInitFileCommand = no,
- Succeeded0 = yes
+ MkInitOK = no,
+ Succeeded0 = no
),
io.close_output(InitFileStream, !IO),
@@ -898,16 +919,6 @@
Succeeded = no
).
-:- pred make_init_file(io.output_stream::in, module_name::in,
- io::di, io::uo) is det.
-
-make_init_file(InitFileStream, ModuleName, !IO) :-
- InitFuncName0 = make_init_name(ModuleName),
- InitFuncName = InitFuncName0 ++ "init",
- io.write_string(InitFileStream, "INIT ", !IO),
- io.write_string(InitFileStream, InitFuncName, !IO),
- io.nl(InitFileStream, !IO).
-
%-----------------------------------------------------------------------------%
link_module_list(Modules, FactTableObjFiles, Succeeded, !IO) :-
Index: compiler/make.program_target.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make.program_target.m,v
retrieving revision 1.47
diff -u -r1.47 make.program_target.m
--- compiler/make.program_target.m 17 Mar 2006 01:40:25 -0000 1.47
+++ compiler/make.program_target.m 16 May 2006 03:39:18 -0000
@@ -5,12 +5,13 @@
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%
-
+%
% File: make.program_target.m.
% Main author: stayl.
-
+%
% Build targets which relate to whole programs or libraries.
-
+%
+%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- module make.program_target.
@@ -560,32 +561,33 @@
IntSucceeded, !Info, !IO),
(
IntSucceeded = yes,
- % Errors while making the `.init' file should be very rare.
- io.output_stream(ErrorStream, !IO),
- compile_target_code.make_init_file(ErrorStream, MainModuleName,
- AllModules, InitSucceeded, !IO),
+ make_linked_target(MainModuleName - static_library,
+ StaticSucceeded, !Info, !IO),
+ shared_libraries_supported(SharedLibsSupported, !IO),
(
- InitSucceeded = yes,
- make_linked_target(MainModuleName - static_library,
- StaticSucceeded, !Info, !IO),
- compile_target_code.shared_libraries_supported(
- SharedLibsSupported, !IO),
+ StaticSucceeded = yes,
+ (
+ SharedLibsSupported = yes,
+ make_linked_target(MainModuleName - shared_library,
+ SharedLibsSucceeded, !Info, !IO)
+ ;
+ SharedLibsSupported = no,
+ SharedLibsSucceeded = yes
+ ),
+ % We can only build the .init file if we have succesfully
+ % built the .c files.
(
- StaticSucceeded = yes,
- (
- SharedLibsSupported = yes,
- make_linked_target(MainModuleName - shared_library,
- Succeeded, !Info, !IO)
- ;
- SharedLibsSupported = no,
- Succeeded = yes
- )
+ SharedLibsSucceeded = yes,
+ % Errors while making the .init file should be very rare.
+ io.output_stream(ErrorStream, !IO),
+ make_init_file(ErrorStream, MainModuleName,
+ AllModules, Succeeded, !IO)
;
- StaticSucceeded = no,
- Succeeded = no
+ SharedLibsSucceeded = no,
+ Succeeded = no
)
;
- InitSucceeded = no,
+ StaticSucceeded = no,
Succeeded = no
)
;
Index: compiler/modules.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.390
diff -u -r1.390 modules.m
--- compiler/modules.m 2 May 2006 05:57:07 -0000 1.390
+++ compiler/modules.m 16 May 2006 06:40:22 -0000
@@ -5048,9 +5048,6 @@
io.write_string(DepStream, Version, !IO),
io.write_string(DepStream, ".\n\n", !IO),
- map.keys(DepsMap, Modules0),
- select_ok_modules(Modules0, DepsMap, Modules),
-
module_name_to_make_var_name(ModuleName, MakeVarName),
module_name_to_file_name(ModuleName, ".init", yes, InitFileName, !IO),
@@ -5270,12 +5267,16 @@
module_name_to_file_name(ModuleName, ".dep", no, DepFileName, !IO),
module_name_to_file_name(ModuleName, ".dv", no, DvFileName, !IO),
+
io.write_strings(DepStream, [
InitFileName, " : ", DepFileName, "\n",
"\techo > ", InitFileName, "\n"
], !IO),
- list.foldl(append_to_init_list(DepStream, InitFileName), Modules, !IO),
-
+ io.write_strings(DepStream, [
+ "\t$(MKLIBINIT) -k ", "$(", MakeVarName, ".cs)", " >> ",
+ InitFileName, "\n"
+ ], !IO),
+
% $(EXTRA_INIT_COMMAND) should expand to a command to
% generate extra entries in the `.init' file for a library.
% It may expand to the empty string.
Index: scripts/Mmake.vars.in
===================================================================
RCS file: /home/mercury1/repository/mercury/scripts/Mmake.vars.in,v
retrieving revision 1.102
diff -u -r1.102 Mmake.vars.in
--- scripts/Mmake.vars.in 24 Feb 2006 07:11:21 -0000 1.102
+++ scripts/Mmake.vars.in 16 May 2006 06:17:39 -0000
@@ -358,6 +358,10 @@
EXTRA_MLLIBS =
LIB_MLLIBS = $(patsubst %,-l%,$(ALL_EXTRA_LIBRARIES))
+# Program used to create the .init file for a library.
+# This is usually just mkinit invoked with the `-k' option.
+MKLIBINIT = mkinit
+
# These only have an effect with `mmc --make'.
LINKAGE = shared
MERCURY_LINKAGE = @DEFAULT_LINKAGE@
Index: util/mkinit.c
===================================================================
RCS file: /home/mercury1/repository/mercury/util/mkinit.c,v
retrieving revision 1.109
diff -u -r1.109 mkinit.c
--- util/mkinit.c 5 May 2006 07:49:29 -0000 1.109
+++ util/mkinit.c 15 May 2006 06:42:43 -0000
@@ -15,6 +15,11 @@
** produces the initialization file (usually called *_init.c) on stdout.
** The initialization file is a small C program that calls the initialization
** functions for all the modules in a Mercury program.
+**
+** Alternatively, if invoked with the -k option, this program produces a
+** list of intialization directives on stdout. This mode of operation is
+** is used when building .init files for libraries.
+**
*/
/*---------------------------------------------------------------------------*/
@@ -256,6 +261,7 @@
static MR_bool output_main_func = MR_TRUE;
static MR_bool need_initialization_code = MR_FALSE;
static MR_bool need_tracing = MR_FALSE;
+static MR_bool output_lib_init = MR_FALSE;
static const char *experimental_complexity = NULL;
static int num_experimental_complexity_procs = 0;
@@ -510,6 +516,8 @@
const char **func_names, int num_func_names);
static void output_main_init_function(Purpose purpose, int num_bunches);
static void output_main(void);
+static void output_lib_init_file(void);
+static void output_init_program(void);
static void process_file(const char *filename);
static void process_init_file(const char *filename);
static void output_init_function(const char *func_name,
@@ -558,9 +566,6 @@
int
main(int argc, char **argv)
{
- int filenum;
- int num_bunches;
- int i;
MR_progname = argv[0];
@@ -573,17 +578,78 @@
set_output_file();
- do_path_search();
- output_headers();
+ if (output_lib_init == MR_TRUE) {
+ output_lib_init_file(); /* Output a .init file. */
+ } else {
+ output_init_program(); /* Output a _init.c file. */
+ }
- if (need_initialization_code) {
- printf("#define MR_MAY_NEED_INITIALIZATION\n\n");
+ if (num_errors > 0) {
+ fputs("/* Force syntax error, since there were */\n", stdout);
+ fputs("/* errors in the generation of this file */\n", stdout);
+ fputs("#error \"You need to remake this file\"\n", stdout);
+ if (output_file_name != NULL) {
+ (void) fclose(stdout);
+ (void) remove(output_file_name);
+ }
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*
+** Output the initialisation file for a Mercury library, the .init file.
+*/
+static void
+output_lib_init_file(void)
+{
+ int filenum;
+ int i;
+
+ for (filenum = 0; filenum < num_files; filenum++) {
+ process_file(files[filenum]);
+ }
+
+ for (i = 0; i < std_module_next; i++) {
+ printf("INIT %s%s\n", std_modules[i], module_suffix[PURPOSE_INIT]);
}
+ for (i = 0; i < req_init_module_next; i++) {
+ printf("REQUIRED_INIT %s\n", req_init_modules[i]);
+ }
+
+ for (i = 0; i < req_final_module_next; i++) {
+ printf("REQUIRED_FINAL %s\n", req_final_modules[i]);
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*
+** Output the initialisation program for a Mercury executable, the *_init.c
+** file.
+*/
+static void
+output_init_program(void)
+{
+ int filenum;
+ int num_bunches;
+ int i;
+
+ do_path_search();
+ output_headers();
+
for (filenum = 0; filenum < num_files; filenum++) {
process_file(files[filenum]);
}
+ if (need_initialization_code) {
+ printf("#define MR_MAY_NEED_INITIALIZATION\n\n");
+ }
+
std_and_special_modules = MR_NEW_ARRAY(const char *,
std_module_next + special_module_next);
@@ -624,19 +690,6 @@
output_main_init_function(PURPOSE_REQ_FINAL, num_bunches);
output_main();
-
- if (num_errors > 0) {
- fputs("/* Force syntax error, since there were */\n", stdout);
- fputs("/* errors in the generation of this file */\n", stdout);
- fputs("#error \"You need to remake this file\"\n", stdout);
- if (output_file_name != NULL) {
- (void) fclose(stdout);
- (void) remove(output_file_name);
- }
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
}
/*---------------------------------------------------------------------------*/
@@ -648,7 +701,7 @@
int i;
String_List *tmp_slist;
- while ((c = getopt(argc, argv, "A:c:g:iI:lo:r:tw:xX:")) != EOF) {
+ while ((c = getopt(argc, argv, "A:c:g:iI:lo:r:tw:xX:k")) != EOF) {
switch (c) {
case 'A':
/*
@@ -738,6 +791,10 @@
experimental_complexity = optarg;
break;
+ case 'k':
+ output_lib_init = MR_TRUE;
+ break;
+
default:
usage();
}
@@ -763,8 +820,9 @@
fputs(" -o file:\toutput to the named file\n", stderr);
fputs(" -r word:\tadd word to the flags for the runtime\n", stderr);
fputs(" -t:\t\tenable execution tracing\n", stderr);
- fputs(" -w entry:\tset the entry point to the egiven label\n", stderr);
+ fputs(" -w entry:\tset the entry point to the given label\n", stderr);
fputs(" -I dir:\tadd dir to the search path for init files\n", stderr);
+ fputs(" -k:\t\tgenerate the .init for a library\n", stderr);
exit(EXIT_FAILURE);
}
--------------------------------------------------------------------------
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