[m-rev.] diff: mercury__<modulename>__required_{init, final}

Julien Fischer juliensf at cs.mu.OZ.AU
Fri May 12 18:15:40 AEST 2006


Estimated hours taken: 2
Branches: main, release

For each module generate a function mercury__<modulename>__required_init
that calls any initialisers in the module.  We only create this function if
there are any user-defined initialisation predicates (or any introduced for
mutable initialisation.) This means that at most one REQUIRED_INIT comment per
module will be required, as opposed to the one per initialise or mutable
declaration we have now.

This change goes part of the way to fixing the bug with initialisers in
libraries not being run.  (The remainder of the fix is a separate change.)
This change also makes it simpler to ensure that the initialisers get executed
in the correct order.

Do the same thing for finalisers.

compiler/llds_out.m:
compiler/mlds_to_c.m:
	Make the above changes to the LLDS and MLDS backends respectively.

Julien.

Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.278
diff -u -r1.278 llds_out.m
--- compiler/llds_out.m	8 May 2006 03:36:01 -0000	1.278
+++ compiler/llds_out.m	12 May 2006 04:58:24 -0000
@@ -5,15 +5,16 @@
 % This file may only be copied under the terms of the GNU General
 % Public License - see the file COPYING in the Mercury distribution.
 %-----------------------------------------------------------------------------%
-
+%
 % File: llds_out.m.
 % Main authors: conway, fjh, zs.
-
+%
 % LLDS - The Low-Level Data Structure.
-
+%
 % This module defines the routines for printing out LLDS,
 % the Low Level Data Structure.
-
+%
+%-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%

 :- module ll_backend.llds_out.
@@ -324,7 +325,8 @@
     list.foldl(io.write_string, Exports, !IO),
     io.write_string("\n", !IO),
     output_c_module_init_list(ModuleName, Modules, RttiDatas, LayoutDatas,
-        Vars, ComplexityProcs, StackLayoutLabels, !DeclSet, !IO),
+        Vars, ComplexityProcs, StackLayoutLabels, UserInitPredCNames,
+        UserFinalPredCNames, !DeclSet, !IO),
     io.set_output_stream(OutputStream, _, !IO).

 :- pred order_layout_datas(list(layout_data)::in, list(layout_data)::out)
@@ -358,10 +360,12 @@
 :- pred output_c_module_init_list(module_name::in, list(comp_gen_c_module)::in,
     list(rtti_data)::in, list(layout_data)::in, list(comp_gen_c_var)::in,
     list(complexity_proc_info)::in, map(label, data_addr)::in,
-    decl_set::in, decl_set::out, io::di, io::uo) is det.
+    list(string)::in, list(string)::in, decl_set::in, decl_set::out,
+    io::di, io::uo) is det.

 output_c_module_init_list(ModuleName, Modules, RttiDatas, LayoutDatas, Vars,
-        ComplexityProcs, StackLayoutLabels, !DeclSet, !IO) :-
+        ComplexityProcs, StackLayoutLabels, InitPredNames, FinalPredNames,
+        !DeclSet, !IO) :-
     MustInit = (pred(Module::in) is semidet :-
         module_defines_label_with_layout(Module, StackLayoutLabels)
     ),
@@ -404,6 +408,24 @@
     io.write_string("init_complexity_procs(void);\n", !IO),
     io.write_string("#endif\n", !IO),

+    (
+        InitPredNames = []
+    ;
+        InitPredNames = [_ | _],
+        io.write_string("void ", !IO),
+        output_init_name(ModuleName, !IO),
+        io.write_string("required_init(void);\n", !IO)
+    ),
+
+    (
+        FinalPredNames = []
+    ;
+        FinalPredNames = [_ | _],
+        io.write_string("void ", !IO),
+        output_init_name(ModuleName, !IO),
+        io.write_string("required_final(void);\n", !IO)
+    ),
+
     globals.io_lookup_bool_option(allow_table_reset, TableReset, !IO),
     (
         TableReset = yes,
@@ -492,6 +514,31 @@
     output_init_complexity_proc_list(ComplexityProcs, !IO),
     io.write_string("}\n", !IO),
     io.write_string("\n#endif\n\n", !IO),
+
+    (
+        InitPredNames = []
+    ;
+        InitPredNames = [_ | _],
+        io.write_string("void ", !IO),
+        output_init_name(ModuleName, !IO),
+        io.write_string("required_init(void)\n", !IO),
+        io.write_string("{\n", !IO),
+        output_required_init_or_final_calls(InitPredNames, !IO),
+        io.write_string("}\n", !IO),
+        io.nl(!IO)
+    ),
+
+    (
+        FinalPredNames = []
+    ;
+        FinalPredNames = [_ | _],
+        io.write_string("void ", !IO),
+        output_init_name(ModuleName, !IO),
+        io.write_string("required_final(void)\n", !IO),
+        io.write_string("{\n", !IO),
+        output_required_init_or_final_calls(FinalPredNames, !IO),
+        io.write_string("}\n", !IO)
+    ),

     (
         TableReset = yes,
@@ -750,8 +797,24 @@
     io.write_string("INIT ", !IO),
     output_init_name(ModuleName, !IO),
     io.write_string("init\n", !IO),
-    list.foldl(output_required_user_init_comment, UserInitPredCNames, !IO),
-    list.foldl(output_required_user_final_comment, UserFinalPredCNames, !IO),
+    % We only print out the REQUIRED_INIT and REQUIRED_FINAL comments
+    % if there are user initialisation/finalisation predicates.
+    (
+        UserInitPredCNames = []
+    ;
+        UserInitPredCNames = [_ | _],
+        io.write_string("REQUIRED_INIT ", !IO),
+        output_init_name(ModuleName, !IO),
+        io.write_string("required_init\n", !IO)
+    ),
+    (
+        UserFinalPredCNames = []
+    ;
+        UserFinalPredCNames = [_ | _],
+        io.write_string("REQUIRED_FINAL ", !IO),
+        output_init_name(ModuleName, !IO),
+        io.write_string("required_final\n", !IO)
+    ),
     io.write_string("ENDINIT\n", !IO),
     io.write_string("*/\n\n", !IO).

@@ -768,6 +831,14 @@
     io.write_string("REQUIRED_FINAL ", !IO),
     io.write_string(CName, !IO),
     io.nl(!IO).
+
+:- pred output_required_init_or_final_calls(list(string)::in, io::di, io::uo)
+    is det.
+
+output_required_init_or_final_calls([], !IO).
+output_required_init_or_final_calls([ Name | Names ], !IO) :-
+    io.write_string("\t" ++ Name ++ "();\n", !IO),
+    output_required_init_or_final_calls(Names, !IO).

 :- pred output_bunch_name(module_name::in, string::in, int::in, io::di, io::uo)
     is det.
Index: compiler/mlds_to_c.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_c.m,v
retrieving revision 1.188
diff -u -r1.188 mlds_to_c.m
--- compiler/mlds_to_c.m	5 May 2006 08:02:56 -0000	1.188
+++ compiler/mlds_to_c.m	5 May 2006 08:06:14 -0000
@@ -5,12 +5,12 @@
 % This file may only be copied under the terms of the GNU General
 % Public License - see the file COPYING in the Mercury distribution.
 %-----------------------------------------------------------------------------%
-%
+%
 % File: mlds_to_c.m.
 % Main author: fjh.
 %
 % Convert MLDS to C/C++ code.
-%
+%
 % TODO:
 %   - RTTI for debugging (module_layout, proc_layout, internal_layout)
 %   - trail ops
@@ -21,7 +21,7 @@
 %     is to change some calls to sorry/2 to unexpected/2).
 %   - packages, classes and inheritance
 %     (currently we just generate all classes as structs)
-%
+%
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%

@@ -154,8 +154,8 @@
 :- pred mlds_output_hdr_file(indent::in, mlds::in, io::di, io::uo) is det.

 mlds_output_hdr_file(Indent, MLDS, !IO) :-
-    MLDS = mlds(ModuleName, AllForeignCode, Imports, Defns, _InitPreds,
-        _FinalPreds),
+    MLDS = mlds(ModuleName, AllForeignCode, Imports, Defns, InitPreds,
+        FinalPreds),
     mlds_output_hdr_start(Indent, ModuleName, !IO),
     io.nl(!IO),
     mlds_output_hdr_imports(Indent, Imports, !IO),
@@ -182,7 +182,7 @@
     io.nl(!IO),
     mlds_output_decls(Indent, MLDS_ModuleName, PublicNonTypeDefns, !IO),
     io.nl(!IO),
-    mlds_output_init_fn_decls(MLDS_ModuleName, !IO),
+    mlds_output_init_fn_decls(MLDS_ModuleName, InitPreds, FinalPreds, !IO),
     io.nl(!IO),
     mlds_output_hdr_end(Indent, ModuleName, !IO).

@@ -300,7 +300,7 @@
     mlds_output_defns(Indent, yes, MLDS_ModuleName, NonTypeDefns, !IO),
     io.nl(!IO),
     mlds_output_init_fn_defns(MLDS_ModuleName, FuncDefns, TypeCtorInfoDefns,
-        !IO),
+        InitPreds, FinalPreds, !IO),
     io.nl(!IO),
     mlds_output_grade_var(!IO),
     io.nl(!IO),
@@ -397,36 +397,25 @@
     output_init_name(ModuleName, !IO),
     io.write_string("init\n", !IO),
     (
-        UserInitPredCNames = [],
+        UserInitPredCNames = []
+    ;
+        UserInitPredCNames = [_ | _],
+        io.write_string("REQUIRED_INIT ", !IO),
+        output_init_name(ModuleName, !IO),
+        io.write_string("required_init\n", !IO)
+    ),
+    (
         UserFinalPredCNames = []
-    ->
-        % There's no point writing out anything if this module doesn't have
-        % any module init or final preds.
-        true
     ;
-        list.foldl(mlds_output_required_user_init_comment,
-            UserInitPredCNames, !IO),
-        list.foldl(mlds_output_required_user_final_comment,
-            UserFinalPredCNames, !IO)
+        UserFinalPredCNames = [_ | _],
+        io.write_string("REQUIRED_FINAL ", !IO),
+        output_init_name(ModuleName, !IO),
+        io.write_string("required_final\n", !IO)
     ),
     % We always write out ENDINIT so that mkinit doesn't scan the whole file.
     io.write_string("ENDINIT\n", !IO),
     io.write_string("*/\n\n", !IO).

-:- pred mlds_output_required_user_init_comment(string::in, io::di, io::uo)
-    is det.
-
-mlds_output_required_user_init_comment(CName, !IO) :-
-    io.write_string("REQUIRED_INIT ", !IO),
-    io.write_string(CName, !IO),
-    io.nl(!IO).
-
-:- pred mlds_output_required_user_final_comment(string::in, io::di, io::uo)
-    is det.
-
-mlds_output_required_user_final_comment(CName, !IO) :-
-    io.write_string("REQUIRED_FINAL " ++ CName ++ "\n", !IO).
-
     % Output any #defines which are required to bootstrap in the hlc
     % grade.
     %
@@ -513,22 +502,44 @@

     % Maybe output the function `mercury__<modulename>__init()'.
     % The body of the function consists of calls MR_init_entry(<function>)
-    % for each function defined in the module.
+    % for each function defined in the module.
+    %
+    % If there are any user-defined intialisation or finalisation predicates
+    % then output the functions: `mercury__<modulename>__required_init()' and
+    % `mercury__<modulename>__required_final()' as necessary.
+    %
     %
-:- pred mlds_output_init_fn_decls(mlds_module_name::in, io::di, io::uo) is det.
+:- pred mlds_output_init_fn_decls(mlds_module_name::in, list(string)::in,
+    list(string)::in, io::di, io::uo) is det.

-mlds_output_init_fn_decls(ModuleName, !IO) :-
+mlds_output_init_fn_decls(ModuleName, InitPreds, FinalPreds, !IO) :-
     output_init_fn_name(ModuleName, "", !IO),
     io.write_string(";\n", !IO),
     output_init_fn_name(ModuleName, "_type_tables", !IO),
     io.write_string(";\n", !IO),
     output_init_fn_name(ModuleName, "_debugger", !IO),
-    io.write_string(";\n", !IO).
+    io.write_string(";\n", !IO),
+    (
+        InitPreds = []
+    ;
+        InitPreds = [_ | _],
+        output_required_fn_name(ModuleName, "required_init", !IO),
+        io.write_string(";\n", !IO)
+    ),
+    (
+        FinalPreds = []
+    ;
+        FinalPreds = [_ | _],
+        output_required_fn_name(ModuleName, "required_final", !IO),
+        io.write_string(";\n", !IO)
+    ).

 :- pred mlds_output_init_fn_defns(mlds_module_name::in, mlds_defns::in,
-    mlds_defns::in, io::di, io::uo) is det.
+    mlds_defns::in, list(string)::in, list(string)::in, io::di, io::uo)
+    is det.

-mlds_output_init_fn_defns(ModuleName, FuncDefns, TypeCtorInfoDefns, !IO) :-
+mlds_output_init_fn_defns(ModuleName, FuncDefns, TypeCtorInfoDefns, InitPreds,
+        FinalPreds, !IO) :-
     output_init_fn_name(ModuleName, "", !IO),
     io.write_string("\n{\n", !IO),
     globals.io_get_globals(Globals, !IO),
@@ -562,7 +573,38 @@
     io.write_string("\n{\n", !IO),
     io.write_string("\tMR_fatal_error(""debugger initialization " ++
         "in MLDS grade"");\n", !IO),
-    io.write_string("}\n", !IO).
+    io.write_string("}\n", !IO),
+    %
+    % Maybe write out wrapper functions that call user-defined intialisation
+    % and finalisation predicates.
+    %
+    (
+        InitPreds = []
+    ;
+        InitPreds = [_ | _],
+        io.nl(!IO),
+        output_required_fn_name(ModuleName, "required_init", !IO),
+        io.write_string("\n{\n", !IO),
+        output_required_calls(InitPreds, !IO),
+        io.write_string("}\n", !IO)
+    ),
+    (
+        FinalPreds = []
+    ;
+        FinalPreds = [_ | _],
+        io.nl(!IO),
+        output_required_fn_name(ModuleName, "required_final", !IO),
+        io.write_string("\n{\n", !IO),
+        output_required_calls(FinalPreds, !IO),
+        io.write_string("}\n", !IO)
+    ).
+
+:- pred output_required_calls(list(string)::in, io::di, io::uo) is det.
+
+output_required_calls([], !IO).
+output_required_calls([ Call | Calls ], !IO) :-
+    io.write_string("\t" ++ Call ++ "();\n", !IO),
+    output_required_calls(Calls, !IO).

 :- pred output_init_fn_name(mlds_module_name::in, string::in,
     io::di, io::uo) is det.
@@ -582,6 +624,29 @@
     io.write_string("__init", !IO),
     io.write_string(Suffix, !IO),
     io.write_string("(void)", !IO).
+
+    % Output a function name of the form:
+    %
+    %   mercury__<modulename>__<suffix>
+    %
+:- pred output_required_fn_name(mlds_module_name::in, string::in,
+    io::di, io::uo) is det.
+
+output_required_fn_name(ModuleName, Suffix, !IO) :-
+    % Here we ensure that we only get one "mercury__" at the start
+    % of the function name.
+    sym_name_to_string(mlds_module_name_to_sym_name(ModuleName), "__",
+        ModuleNameString0),
+    ( string.prefix(ModuleNameString0, "mercury__") ->
+        ModuleNameString = ModuleNameString0
+    ;
+        ModuleNameString = "mercury__" ++ ModuleNameString0
+    ),
+    io.write_string("void ", !IO),
+    io.write_string(ModuleNameString, !IO),
+    io.write_string("__", !IO),
+    io.write_string(Suffix, !IO),
+    io.write_string("(void)", !IO).

 :- pred need_to_init_entries(globals::in) is semidet.


--------------------------------------------------------------------------
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